diff --git a/.github/workflows/integration-test.yml b/.github/workflows/integration-test.yml index fe348dd..2096bfb 100644 --- a/.github/workflows/integration-test.yml +++ b/.github/workflows/integration-test.yml @@ -411,12 +411,12 @@ jobs: scheduled=$(echo "$stats" | jq '[.queued_documents_counts | to_entries[].value] | add // 0') locked=$(echo "$stats" | jq '[.queued_documents_locked_counts | to_entries[].value] | add // 0') echo "Attempt $i: queued_documents=$scheduled locked=$locked" - if [ "$scheduled" = "0" ]; then + if [ "$scheduled" = "0" ] && [ "$locked" = "0" ]; then echo "Queue drained" break fi if [ "$i" = "30" ]; then - echo "Timeout: queue did not drain to zero (queued_documents=$scheduled)" + echo "Timeout: queue did not drain to zero (queued_documents=$scheduled locked=$locked)" exit 1 fi sleep 10 diff --git a/context_chat_backend/controller.py b/context_chat_backend/controller.py index 63766aa..12d86fa 100644 --- a/context_chat_backend/controller.py +++ b/context_chat_backend/controller.py @@ -4,7 +4,7 @@ # import time -from nc_py_api.ex_app.providers.task_processing import TaskProcessingProvider +from nc_py_api.ex_app.providers.task_processing import ShapeDescriptor, ShapeType, TaskProcessingProvider, TaskType # isort: off from .chain.types import ContextException @@ -100,26 +100,115 @@ def get_enabled_state() -> bool: last_enabled_check = time.time() return app_enabled.is_set() + def enabled_handler(enabled: bool, nc: NextcloudApp | AsyncNextcloudApp) -> str: + SEARCH_TASKTYPE_ID = 'context_chat:context_chat_search' + SEARCH_PROVIDER_ID = 'context_chat-context_chat_search' + CC_TASKTYPE_ID = 'context_chat:context_chat' + CC_PROVIDER_ID = 'context_chat-context_chat' + + # todo: translate user-facing texts try: if enabled: - provider = TaskProcessingProvider( - id='context_chat-context_chat_search', + search_tasktype = TaskType( + id=SEARCH_TASKTYPE_ID, + name='Context Chat search', + description='Search with Context Chat.', + input_shape=[ + ShapeDescriptor( + name='prompt', + description='Search your documents, files and more', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='scopeType', + description='Any of the following values: "none", "provider".', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='scopeList', + description='List of providers', + shape_type=ShapeType.LIST_OF_TEXTS, + ), + ShapeDescriptor( + name='scopeListMeta', + description='Required to nicely render the scope list in assistant', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='limit', + description='Maximum number of results returned by Context Chat', + shape_type=ShapeType.NUMBER, + ), + ], + output_shape=[ + ShapeDescriptor( + name='sources', + description='The sources that were found', + shape_type=ShapeType.LIST_OF_TEXTS, + ), + ], + ) + + search_provider = TaskProcessingProvider( + id=SEARCH_PROVIDER_ID, name='Context Chat', - task_type='context_chat:context_chat_search', + task_type=SEARCH_TASKTYPE_ID, expected_runtime=30, input_shape_defaults={ 'limit': 10, }, ) - nc.providers.task_processing.register(provider) - provider = TaskProcessingProvider( - id='context_chat-context_chat', + nc.providers.task_processing.register(search_provider, search_tasktype) + + cc_tasktype = TaskType( + id=CC_TASKTYPE_ID, + name='Context Chat', + description='Ask a question about your data.', + input_shape=[ + ShapeDescriptor( + name='prompt', + description='Ask a question about your documents, files and more', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='scopeType', + description='Any of the following values: "none", "source", "provider".', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='scopeList', + description='List of sources or providers', + shape_type=ShapeType.LIST_OF_TEXTS, + ), + ShapeDescriptor( + name='scopeListMeta', + description='Required to nicely render the scope list in assistant', + shape_type=ShapeType.TEXT, + ), + ], + output_shape=[ + ShapeDescriptor( + name='output', + description='The text generated by the model', + shape_type=ShapeType.TEXT, + ), + ShapeDescriptor( + name='sources', + description='The sources referenced to generate the above response', + shape_type=ShapeType.LIST_OF_TEXTS, + ), + ], + ) + + cc_provider = TaskProcessingProvider( + id=CC_PROVIDER_ID, name='Context Chat', - task_type='context_chat:context_chat', + task_type=CC_TASKTYPE_ID, expected_runtime=30, ) - nc.providers.task_processing.register(provider) + nc.providers.task_processing.register(cc_provider, cc_tasktype) + app_enabled.set() if THREAD_STOP_EVENT.is_set(): # If the threads were previously stopped, we start them again @@ -128,6 +217,9 @@ def enabled_handler(enabled: bool, nc: NextcloudApp | AsyncNextcloudApp) -> str: THREAD_STOP_EVENT.clear() else: app_enabled.clear() + nc.providers.task_processing.unregister(SEARCH_PROVIDER_ID) + nc.providers.task_processing.unregister(CC_PROVIDER_ID) + wait_for_bg_threads() except Exception as e: logger.exception('Error in enabled handler:', exc_info=e)