mirror of
https://github.com/langbot-app/LangBot.git
synced 2026-11-03 22:32:27 +08:00
fix(api): preserve integer knowledge ingestion task IDs
This commit is contained in:
@@ -255,3 +255,107 @@ async def test_chat_management_uses_scoped_history_and_real_connection_queues(re
|
||||
== []
|
||||
)
|
||||
assert len(adapter.websocket_group_session.message_lists[pipeline]) == 1
|
||||
|
||||
|
||||
@pytest.mark.asyncio
|
||||
@pytest.mark.parametrize('extension', ['txt', 'zip'])
|
||||
async def test_knowledge_upload_returns_real_integer_task_id(resources, tmp_path, monkeypatch, extension):
|
||||
import asyncio
|
||||
import io
|
||||
import zipfile
|
||||
|
||||
from langbot.pkg.api.context import ExecutionContext
|
||||
from langbot.pkg.core.taskmgr import AsyncTaskManager
|
||||
from langbot.pkg.entity.persistence.rag import File
|
||||
from langbot.pkg.entity.persistence.workspace import Workspace, WorkspaceExecutionState
|
||||
from langbot.pkg.storage.mgr import StorageMgr
|
||||
from langbot.pkg.storage.providers import localstorage
|
||||
|
||||
api, ap, engine = resources
|
||||
workspace = '00000000-0000-0000-0000-00000000000a'
|
||||
request = context(workspace)
|
||||
execution = ExecutionContext.from_request(request)
|
||||
kb_data = {
|
||||
'uuid': 'ingestion-kb',
|
||||
'workspace_uuid': workspace,
|
||||
'name': 'Ingestion',
|
||||
'knowledge_engine_plugin_id': 'test/engine',
|
||||
'collection_id': 'ingestion-kb',
|
||||
'creation_settings': {},
|
||||
'retrieval_settings': {},
|
||||
'initialized': True,
|
||||
}
|
||||
async with engine.begin() as connection:
|
||||
await connection.execute(
|
||||
sa.insert(Workspace).values(
|
||||
uuid=workspace,
|
||||
instance_uuid=request.instance_uuid,
|
||||
name='Ingestion',
|
||||
slug='ingestion',
|
||||
source='cloud_projection',
|
||||
)
|
||||
)
|
||||
await connection.execute(
|
||||
sa.insert(WorkspaceExecutionState).values(
|
||||
workspace_uuid=workspace, instance_uuid=request.instance_uuid, active_generation=1, source='cloud'
|
||||
)
|
||||
)
|
||||
await connection.execute(sa.insert(KnowledgeBase).values(**kb_data))
|
||||
ap.event_loop = asyncio.get_running_loop()
|
||||
ap.task_mgr = AsyncTaskManager(ap)
|
||||
monkeypatch.setattr(localstorage, 'LOCAL_STORAGE_PATH', str(tmp_path / 'uploads'))
|
||||
ap.storage_mgr = StorageMgr(ap)
|
||||
ap.storage_mgr.storage_provider = localstorage.LocalStorageProvider(ap)
|
||||
entered, release = asyncio.Event(), asyncio.Event()
|
||||
|
||||
async def ingest(_plugin_id, _payload):
|
||||
entered.set()
|
||||
await release.wait()
|
||||
return {'document_id': 'engine-document', 'status': 'completed'}
|
||||
|
||||
ap.plugin_connector = SimpleNamespace(
|
||||
is_enable_plugin=True,
|
||||
require_workspace_context=AsyncMock(side_effect=lambda scope: scope),
|
||||
list_knowledge_engines=AsyncMock(
|
||||
return_value=[{'plugin_id': 'test/engine', 'capabilities': ['doc_ingestion']}]
|
||||
),
|
||||
call_rag_ingest=AsyncMock(side_effect=ingest),
|
||||
)
|
||||
await ap.rag_mgr.load_knowledge_base(execution, KnowledgeBase(**kb_data))
|
||||
content = b'A document for ingestion.'
|
||||
if extension == 'zip':
|
||||
buffer = io.BytesIO()
|
||||
with zipfile.ZipFile(buffer, 'w') as archive:
|
||||
archive.writestr('document.txt', content)
|
||||
content = buffer.getvalue()
|
||||
upload = await ap.storage_mgr.save_scoped(
|
||||
execution, owner_type='upload_document', owner='ingestion-test', key='document.' + extension, value=content
|
||||
)
|
||||
try:
|
||||
task_id = await api.execute('knowledge.file.store', request, {'kb_uuid': kb_data['uuid'], 'file_id': upload})
|
||||
assert type(task_id) is int
|
||||
task = ap.task_mgr.get_task_by_id(
|
||||
task_id, instance_uuid=request.instance_uuid, workspace_uuid=workspace, placement_generation=1
|
||||
)
|
||||
assert task is not None and task.kind == 'knowledge-operation'
|
||||
await asyncio.wait_for(entered.wait(), 5)
|
||||
async with engine.connect() as connection:
|
||||
pending = (
|
||||
(await connection.execute(sa.select(File).where(File.workspace_uuid == workspace))).mappings().one()
|
||||
)
|
||||
assert pending['kb_id'] == kb_data['uuid'] and pending['status'] == 'processing'
|
||||
release.set()
|
||||
await asyncio.wait_for(task.task, 5)
|
||||
async with engine.connect() as connection:
|
||||
stored = (await connection.execute(sa.select(File).where(File.uuid == pending['uuid']))).mappings().one()
|
||||
assert stored['status'] == 'completed' and stored['engine_document_id'] == 'engine-document'
|
||||
assert not await ap.storage_mgr.exists_scoped_object_key(
|
||||
execution, upload, expected_owner_type='upload_document'
|
||||
)
|
||||
finally:
|
||||
release.set()
|
||||
tasks = [wrapper.task for wrapper in ap.task_mgr.get_all_tasks()]
|
||||
for task in tasks:
|
||||
if not task.done():
|
||||
task.cancel()
|
||||
await asyncio.gather(*tasks, return_exceptions=True)
|
||||
|
||||
@@ -123,7 +123,7 @@ def fake_knowledge_app():
|
||||
app.knowledge_service.get_files_by_knowledge_base = AsyncMock(
|
||||
return_value=[{'uuid': 'test-file-uuid', 'filename': 'test.pdf'}]
|
||||
)
|
||||
app.knowledge_service.store_file = AsyncMock(return_value='test-task-id')
|
||||
app.knowledge_service.store_file = AsyncMock(return_value=17)
|
||||
app.knowledge_service.delete_file = AsyncMock()
|
||||
app.knowledge_service.retrieve_knowledge_base = AsyncMock(return_value=[{'content': 'test result', 'score': 0.95}])
|
||||
|
||||
@@ -304,7 +304,7 @@ class TestKnowledgeBaseFilesEndpoints:
|
||||
assert called.await_args.args[0].workspace_uuid == '00000000-0000-0000-0000-00000000000a'
|
||||
assert called.await_args.args[1:] == ('test-kb-uuid', 'test-file-id')
|
||||
assert called.await_args.kwargs == {'parser_plugin_id': 'test/parser'}
|
||||
assert data['data'] == {'task_id': 'test-task-id'}
|
||||
assert data['data'] == {'task_id': 17}
|
||||
|
||||
@pytest.mark.asyncio
|
||||
async def test_delete_file_from_knowledge_base(self, quart_test_client, fake_knowledge_app):
|
||||
|
||||
Reference in New Issue
Block a user