Фиксация изменений
This commit is contained in:
Binary file not shown.
Binary file not shown.
Binary file not shown.
BIN
tests/chat/__pycache__/test_direct_service.cpython-312.pyc
Normal file
BIN
tests/chat/__pycache__/test_direct_service.cpython-312.pyc
Normal file
Binary file not shown.
70
tests/chat/test_chat_api_simple_code_explain.py
Normal file
70
tests/chat/test_chat_api_simple_code_explain.py
Normal file
@@ -0,0 +1,70 @@
|
||||
import asyncio
|
||||
|
||||
from app.modules.chat.module import ChatModule
|
||||
from app.modules.chat.task_store import TaskStore
|
||||
from app.schemas.chat import ChatMessageRequest
|
||||
from app.schemas.chat import TaskQueuedResponse
|
||||
from app.modules.shared.event_bus import EventBus
|
||||
from app.modules.shared.retry_executor import RetryExecutor
|
||||
|
||||
|
||||
class _FakeRuntime:
|
||||
async def run(self, **kwargs):
|
||||
raise AssertionError("legacy runtime must not be called")
|
||||
|
||||
|
||||
class _FakeDirectChat:
|
||||
def __init__(self) -> None:
|
||||
self.calls = 0
|
||||
|
||||
async def handle_message(self, request):
|
||||
self.calls += 1
|
||||
return TaskQueuedResponse(
|
||||
task_id="task-1",
|
||||
status="done",
|
||||
)
|
||||
|
||||
|
||||
class _FakeRagSessions:
|
||||
def get(self, rag_session_id: str):
|
||||
return {"rag_session_id": rag_session_id}
|
||||
|
||||
|
||||
class _FakeRepository:
|
||||
def create_dialog(self, dialog_session_id: str, rag_session_id: str) -> None:
|
||||
return None
|
||||
|
||||
def get_dialog(self, dialog_session_id: str):
|
||||
return None
|
||||
|
||||
def add_message(self, dialog_session_id: str, role: str, content: str, task_id: str | None = None, payload: dict | None = None) -> None:
|
||||
return None
|
||||
|
||||
|
||||
def test_chat_messages_endpoint_uses_direct_service(monkeypatch) -> None:
|
||||
monkeypatch.setenv("SIMPLE_CODE_EXPLAIN_ONLY", "true")
|
||||
direct_chat = _FakeDirectChat()
|
||||
module = ChatModule(
|
||||
agent_runner=_FakeRuntime(),
|
||||
event_bus=EventBus(),
|
||||
retry=RetryExecutor(),
|
||||
rag_sessions=_FakeRagSessions(),
|
||||
repository=_FakeRepository(),
|
||||
direct_chat=direct_chat,
|
||||
task_store=TaskStore(),
|
||||
)
|
||||
router = module.public_router()
|
||||
endpoint = next(route.endpoint for route in router.routes if getattr(route, "path", "") == "/api/chat/messages")
|
||||
response = asyncio.run(
|
||||
endpoint(
|
||||
ChatMessageRequest(
|
||||
session_id="dialog-1",
|
||||
project_id="rag-1",
|
||||
message="Explain get_user",
|
||||
),
|
||||
None,
|
||||
)
|
||||
)
|
||||
|
||||
assert response.task_id == "task-1"
|
||||
assert direct_chat.calls == 1
|
||||
61
tests/chat/test_direct_service.py
Normal file
61
tests/chat/test_direct_service.py
Normal file
@@ -0,0 +1,61 @@
|
||||
import asyncio
|
||||
|
||||
from app.modules.chat.direct_service import CodeExplainChatService
|
||||
from app.modules.chat.session_resolver import ChatSessionResolver
|
||||
from app.modules.chat.task_store import TaskStore
|
||||
from app.modules.rag.explain.models import ExplainIntent, ExplainPack
|
||||
from app.schemas.chat import ChatFileContext, ChatMessageRequest
|
||||
|
||||
|
||||
class _FakeRetriever:
|
||||
def build_pack(self, rag_session_id: str, user_query: str, *, file_candidates: list[dict] | None = None) -> ExplainPack:
|
||||
return ExplainPack(
|
||||
intent=ExplainIntent(raw_query=user_query, normalized_query=user_query),
|
||||
missing=["code_excerpts"],
|
||||
)
|
||||
|
||||
|
||||
class _FakeLlm:
|
||||
def __init__(self) -> None:
|
||||
self.calls = 0
|
||||
|
||||
def generate(self, prompt_name: str, user_input: str, *, log_context: str | None = None) -> str:
|
||||
self.calls += 1
|
||||
return "should not be called"
|
||||
|
||||
|
||||
class _FakeDialogs:
|
||||
def get(self, dialog_session_id: str):
|
||||
return None
|
||||
|
||||
|
||||
def test_direct_service_skips_llm_when_evidence_is_insufficient() -> None:
|
||||
messages: list[tuple[str, str, str, str | None]] = []
|
||||
llm = _FakeLlm()
|
||||
task_store = TaskStore()
|
||||
service = CodeExplainChatService(
|
||||
retriever=_FakeRetriever(),
|
||||
llm=llm,
|
||||
session_resolver=ChatSessionResolver(_FakeDialogs(), lambda rag_session_id: rag_session_id == "rag-1"),
|
||||
task_store=task_store,
|
||||
message_sink=lambda dialog_session_id, role, content, task_id=None: messages.append((dialog_session_id, role, content, task_id)),
|
||||
)
|
||||
|
||||
result = asyncio.run(
|
||||
service.handle_message(
|
||||
ChatMessageRequest(
|
||||
session_id="dialog-1",
|
||||
project_id="rag-1",
|
||||
message="Explain get_user",
|
||||
files=[ChatFileContext(path="app/api/users.py", content="", content_hash="x")],
|
||||
)
|
||||
)
|
||||
)
|
||||
|
||||
task = task_store.get(result.task_id)
|
||||
assert task is not None
|
||||
assert task.answer is not None
|
||||
assert "Недостаточно опоры в коде" in task.answer
|
||||
assert result.status == "done"
|
||||
assert llm.calls == 0
|
||||
assert [item[1] for item in messages] == ["user", "assistant"]
|
||||
Reference in New Issue
Block a user