Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

refactor(assistant rag): use assistant templates for RAG/QAF #173

Merged
merged 4 commits into from
Oct 24, 2024

Conversation

MasterKenth
Copy link
Contributor

@MasterKenth MasterKenth commented Oct 15, 2024

Replace create_rag_stream with functionally equivalent assistant template implementation to unify RAG and templates.

Main benefit is ability to edit QAF and scoring templates on the fly without code changes and redeployment.

How to test

Add the following templates to your database (mongo). QAF and scoring searches for templates with specific IDs so _qaf and _rag_scoring must exist. Templates starting with _ are not shown in the frontend.

{
            id: '_qaf',
            meta: {
                name: 'QAF',
                description: 'QAF template - do not use directly',
                sample_questions: []
            },
            streams: [
                {
                    pipeline: 'rag_scoring'
                },
                {
                    provider: 'openai',
                    settings: {
                        model: 'gpt-4o',
                        temperature: 0
                    },
                    messages: [
                        {
                            timestamp: '',
                            role: 'system',
                            content: 'You are a helpful AI assistant that helps people with answering questions about planning permission.<br> If you can\'t find the answer in the search result below, just say (in Swedish) "Tyvärr kan jag inte svara på det." Don\'t try to make up an answer.<br> If the question is not related to the context, politely respond that you are tuned to only answer questions that are related to the context.<br> The questions are going to be asked in Swedish. Your response must always be in Swedish.'
                        },
                        {
                            timestamp: '',
                            role: 'user',
                            content: '{query}'
                        },
                        {
                            timestamp: '',
                            role: 'user',
                            content: 'Here are the results of the search:\n\n {rag_output}'
                        }
                    ]
                }
            ]
        },
        {
            id: '_rag_scoring',
            meta: {
                name: 'RAG scoring',
                description: '',
                sample_questions: []
            },
            streams: [
                {
                    provider: 'openai',
                    settings: {
                        model: 'gpt-4o',
                        temperature: 0,
                        response_format: {
                            type: 'json_schema',
                            json_schema: {
                                name: 'score_schema',
                                schema: {
                                    type: 'object',
                                    properties: {
                                        score: {
                                            type: 'number'
                                        }
                                    }
                                }
                            }
                        }
                    },
                    messages: [
                        {
                            timestamp: '',
                            role: 'system',
                            content: 'You are a scoring systems that classifies documents from 0-100 based on how well they answer a query.'
                        },
                        {
                            timestamp: '',
                            role: 'user',
                            content: 'Query: {query}\n\nDocument: {rag_document}'
                        }
                    ]
                }
            ]
        }

For QAF ask a question and it should answer mostly the same as before.

For chat with RAG you can duplicate the _qaf template and change ID and add files_collection_id and it should work the same as asking a QAF question.

Misc Technical

  • Implementation is slightly different from create_rag_stream which exploited function calls to format the LLM response. This new approach instead more aptly utilizes response_format to ensure JSON is returned from the LLM.
  • files_collection_id does not need to be set for _qaf or _rag_scoring; they are inferred from usage.

@MasterKenth MasterKenth changed the title refactor(assistant rag): use db template instead of static qaf implementation refactor(assistant rag): use assistant templates for RAG/QAF Oct 16, 2024
@nRamstedt
Copy link
Member

I suspect something has changed the rag pipeline as I get different answers from my assistant (with rag) switching to this branch from master. Everything else work flawlessly 👍

@zilaei
Copy link
Member

zilaei commented Oct 18, 2024

Getting error Exception in ASGI application when trying to create a question (http://0.0.0.0:8000/view/questions/create) after I changed the model in the assistant view http://0.0.0.0:8000/assistants/_rag_scoring to GPT-4.
Switching the model back did not correct the error.

Error log:

ERROR:    Exception in ASGI application
Traceback (most recent call last):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/uvicorn/protocols/http/httptools_impl.py", line 401, in run_asgi
    result = await app(  # type: ignore[func-returns-value]
             ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/uvicorn/middleware/proxy_headers.py", line 70, in __call__
    return await self.app(scope, receive, send)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/fastapi/applications.py", line 1054, in __call__
    await super().__call__(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/applications.py", line 116, in __call__
    await self.middleware_stack(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/errors.py", line 186, in __call__
    raise exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/errors.py", line 164, in __call__
    await self.app(scope, receive, _send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/cors.py", line 91, in __call__
    await self.simple_response(scope, receive, send, request_headers=headers)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/cors.py", line 146, in simple_response
    await self.app(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 189, in __call__
    with collapse_excgroups():
  File "/opt/homebrew/Cellar/[email protected]/3.11.9/Frameworks/Python.framework/Versions/3.11/lib/python3.11/contextlib.py", line 158, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_utils.py", line 88, in collapse_excgroups
    raise exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 191, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/middleware.py", line 20, in remove_trailing_slash
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 165, in call_next
    raise app_exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 151, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 189, in __call__
    with collapse_excgroups():
  File "/opt/homebrew/Cellar/[email protected]/3.11.9/Frameworks/Python.framework/Versions/3.11/lib/python3.11/contextlib.py", line 158, in __exit__
    self.gen.throw(typ, value, traceback)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_utils.py", line 88, in collapse_excgroups
    raise exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 191, in __call__
    response = await self.dispatch_func(request, call_next)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/middleware.py", line 26, in add_git_revision_to_request_header
    response = await call_next(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 165, in call_next
    raise app_exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/base.py", line 151, in coro
    await self.app(scope, receive_or_disconnect, send_no_error)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/middleware/exceptions.py", line 62, in __call__
    await wrap_app_handling_exceptions(self.app, conn)(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_exception_handler.py", line 55, in wrapped_app
    raise exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_exception_handler.py", line 44, in wrapped_app
    await app(scope, receive, sender)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/routing.py", line 746, in __call__
    await route.handle(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/routing.py", line 288, in handle
    await self.app(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/routing.py", line 75, in app
    await wrap_app_handling_exceptions(app, request)(scope, receive, send)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_exception_handler.py", line 55, in wrapped_app
    raise exc
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/_exception_handler.py", line 44, in wrapped_app
    await app(scope, receive, sender)
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/starlette/routing.py", line 70, in app
    response = await func(request)
               ^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/logger/route_class.py", line 21, in custom_route_handler
    response = await original_route_handler(request)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/fastapi/routing.py", line 285, in app
    raise e
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/fastapi/routing.py", line 275, in app
    solved_result = await solve_dependencies(
                    ^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/fastapi/dependencies/utils.py", line 598, in solve_dependencies
    solved = await call(**sub_values)
             ^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/qaf/dependencies.py", line 118, in run_llm_on_question_create_action
    response = await ask_llm_raq_question(question=question.question.content, collection_name=directory_name)
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/llm/service.py", line 58, in ask_llm_raq_question
    return await join_final_output(stream(question))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/utils/stream.py", line 187, in join_final_output
    return await join(filter_final_output(async_iterable))
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/utils/async_generator.py", line 67, in join
    lst = await collect(async_generator)
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/utils/async_generator.py", line 48, in collect
    return [item async for item in async_generator]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/utils/async_generator.py", line 48, in <listcomp>
    return [item async for item in async_generator]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/utils/stream.py", line 123, in filter_final_output
    async for output in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 275, in and_then
    async for values, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 129, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 275, in and_then
    async for values, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 129, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 281, in and_then
    async for v in iter_v:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 275, in and_then
    async for values, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 129, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/assistant/pipeline/rag_scoring.py", line 72, in run_rag_stream
    async for r in full_stream(query[0]):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 275, in and_then
    async for values, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 129, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 275, in and_then
    async for values, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 129, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 633, in and_then
    async for value, to_reyield in self._reyield(self(input)):
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 547, in _reyield
    async for u in async_iterable:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 106, in _wrap
    async for value in values:
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 714, in gather
    ] = await asyncio.gather(*(consume_async_generator(gen) for gen in final_u))
        ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 709, in consume_async_generator
    return [item async for item in generator]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/Library/Caches/pypoetry/virtualenvs/fai-backend-UUgeoJ4g-py3.11/lib/python3.11/site-packages/langstream/core/stream.py", line 709, in <listcomp>
    return [item async for item in generator]
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/ehszil2023/code/labbing_testing/F-AI/fai-rag-app/fai-backend/fai_backend/assistant/pipeline/rag_scoring.py", line 59, in scoring_stream
    score = json.loads(full)['score']
            ^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.9/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/__init__.py", line 346, in loads
    return _default_decoder.decode(s)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.9/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 337, in decode
    obj, end = self.raw_decode(s, idx=_w(s, 0).end())
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/opt/homebrew/Cellar/[email protected]/3.11.9/Frameworks/Python.framework/Versions/3.11/lib/python3.11/json/decoder.py", line 355, in raw_decode
    raise JSONDecodeError("Expecting value", s, err.value) from None
json.decoder.JSONDecodeError: Expecting value: line 1 column 1 (char 0)

@MasterKenth MasterKenth merged commit b5dca2b into master Oct 24, 2024
2 checks passed
@MasterKenth MasterKenth deleted the refactor/rag-scoring-assistant-template branch October 24, 2024 14:28
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants