| 1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495 |
- import pytest
- import app.adapters.text2mem as module
- from app.adapters.text2mem import Text2MemAgent
- from app.db import MemoryRepository
- from app.llm import LLMUnavailable
- class OfflineLLM:
- async def chat(self, *_args, **_kwargs):
- raise LLMUnavailable("test offline")
- class DisabledEmbedding:
- configured = False
- class FailingLLM:
- async def chat(self, *_args, **_kwargs):
- raise RuntimeError("temporary provider failure")
- def build_agent(monkeypatch, tmp_path) -> tuple[Text2MemAgent, MemoryRepository]:
- repo = MemoryRepository()
- repo.path = tmp_path / "memory.json"
- monkeypatch.setattr(module, "embedding_client", DisabledEmbedding())
- agent = Text2MemAgent()
- agent.repo = repo
- agent.llm = OfflineLLM()
- return agent, repo
- @pytest.mark.asyncio
- async def test_text2mem_explicit_write(monkeypatch, tmp_path):
- agent, repo = build_agent(monkeypatch, tmp_path)
- response = await agent.chat("记住:我偏好使用 Python 和 FastAPI")
- assert response.system == "text2mem"
- assert response.memory_events[0]["status"] == "created"
- memories = await repo.list_memories("text2mem")
- assert memories[0].content.startswith("记住")
- assert memories[0].memory_type == "semantic"
- @pytest.mark.asyncio
- async def test_text2mem_writes_all_four_memory_types_and_does_not_store_question(
- monkeypatch,
- tmp_path,
- ):
- agent, repo = build_agent(monkeypatch, tmp_path)
- statements = [
- "记住:我偏好使用 Python 和 FastAPI,代码要求严格类型注解。",
- "我正在开发一个企业内部智能知识库问答项目,使用通义千问和 RAG。",
- "更新一下:检索重排功能已经完成 75%,下一步补充效果评测集。",
- "上次部署测试环境时遇到向量索引构建超时,最后通过分批导入文档解决。",
- "以后修复代码时按这个流程:先复现问题,再定位原因,修改后运行测试。",
- ]
- for statement in statements:
- await agent.chat(statement)
- memories = await repo.list_memories("text2mem")
- assert len(memories) == 5
- assert [item.memory_type for item in memories].count("semantic") == 2
- assert {item.memory_type for item in memories} == {
- "semantic",
- "episodic",
- "procedural",
- "task-state",
- }
- response = await agent.chat("上次部署遇到了什么问题?")
- assert len(await repo.list_memories("text2mem")) == 5
- assert response.memory_events == []
- assert any("向量索引构建超时" in item.content for item in response.memory_context)
- assert all(item.memory_type == "episodic" for item in response.memory_context)
- def test_text2mem_write_classifier_rejects_normal_questions():
- assert Text2MemAgent._should_encode("我的项目使用什么数据库?") is False
- assert Text2MemAgent._should_encode("上次部署遇到了什么问题?") is False
- assert Text2MemAgent._should_encode("记住:项目数据库使用 PostgreSQL。") is True
- @pytest.mark.asyncio
- async def test_text2mem_falls_back_when_configured_model_call_fails(monkeypatch, tmp_path):
- agent, _ = build_agent(monkeypatch, tmp_path)
- agent.llm = FailingLLM()
- response = await agent.chat("记住:我偏好使用 Python 和 FastAPI。")
- assert response.mode == "local-fallback"
- assert "模型调用失败" in response.answer
- assert response.memory_events[0]["status"] == "created"
|