Files
mrleo1nidandClaude Opus 5 84d8aaa848 Этап 7: долговременная память
- Факты о пользователе в SQLite, в системном промпте с номерами
- Инструменты remember / update_memory / forget, автоматическое запоминание отключается
- Цикл вызова инструментов со стримингом (до 5 кругов), проверка и приведение аргументов
- Откат без инструментов для моделей, которые их не поддерживают, с одним предупреждением
- Действия в журнале, вкладка «Память» в настройках
- Фейковый OpenAI-совместимый сервер для тестов, тесты полного цикла через Assistant

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-17 04:27:16 +03:00

68 lines
2.3 KiB
Python

import pytest
from agr_assistent.config import ProviderConfig
from agr_assistent.llm.client import (
LLMClient,
LLMError,
TextDelta,
ToolCall,
ToolCalls,
ToolsNotSupportedError,
)
from tests.fake_llm import FakeLLMServer, Reply
_TOOLS = [{"type": "function", "function": {"name": "remember", "parameters": {"type": "object"}}}]
def _client(server: FakeLLMServer) -> LLMClient:
return LLMClient(
ProviderConfig("fake", server.base_url, "key", "fake-model"),
temperature=0.5,
timeout_seconds=10,
)
def test_text_and_tool_calls_are_assembled(fake_llm: FakeLLMServer) -> None:
fake_llm.replies.append(
Reply(text="Сейчас запомню.", tool_calls=[("remember", '{"text": "Любит кофе"}')])
)
events = list(_client(fake_llm).stream_chat([{"role": "user", "content": "привет"}], _TOOLS))
text = "".join(event.text for event in events if isinstance(event, TextDelta))
assert text == "Сейчас запомню."
assert events[-1] == ToolCalls([ToolCall("call_0", "remember", '{"text": "Любит кофе"}')])
assert fake_llm.requests[0]["tools"] == _TOOLS
def test_tools_are_not_sent_when_absent(fake_llm: FakeLLMServer) -> None:
fake_llm.replies.append(Reply(text="ок"))
list(_client(fake_llm).stream_chat([{"role": "user", "content": "привет"}]))
assert "tools" not in fake_llm.requests[0]
@pytest.mark.parametrize(
"message",
[
"registry.ollama.ai/library/gemma:2b does not support tools",
"No endpoints found that support tool use",
],
)
def test_tools_not_supported_is_recognized(fake_llm: FakeLLMServer, message: str) -> None:
fake_llm.replies.append(Reply(status=400, error=message))
with pytest.raises(ToolsNotSupportedError):
list(_client(fake_llm).stream_chat([{"role": "user", "content": "привет"}], _TOOLS))
def test_other_api_errors_stay_generic(fake_llm: FakeLLMServer) -> None:
fake_llm.replies.append(Reply(status=400, error="context too long"))
with pytest.raises(LLMError) as error:
list(_client(fake_llm).stream_chat([{"role": "user", "content": "привет"}], _TOOLS))
assert not isinstance(error.value, ToolsNotSupportedError)
assert "context too long" in str(error.value)