feat(memory): add session-based chat history and user metadata retrieval

- Add ChatSessionCache to manage chat history per session
- Add SEARCH_USER_METADATA cypher query for retrieving user entity metadata
- Add "str" mode support to StructResponse for raw text extraction
- Add content_str field to MemorySearchResult for pre-formatted content
- Fix sandbox URL by removing hardcoded port
- Add description field to entity search results
- Remove history from UserInput schema, use session_id instead
This commit is contained in:
Eternity
2026-05-06 16:24:53 +08:00
parent 6b68ee9fc8
commit 3f9740412a
19 changed files with 387 additions and 117 deletions

View File

@@ -27,6 +27,7 @@ from app.services import task_service, workspace_service
from app.services.memory_agent_service import MemoryAgentService
from app.services.memory_agent_service import get_end_user_connected_config as get_config
from app.services.model_service import ModelConfigService
from app.utils.tmp_session import ChatSessionCache
load_dotenv()
api_logger = get_api_logger()
@@ -300,60 +301,39 @@ async def read_server(
if knowledge:
user_rag_memory_id = str(knowledge.id)
session_id = user_input.session_id.hex
api_logger.info(
f"Read service: group={user_input.end_user_id}, storage_type={storage_type}, user_rag_memory_id={user_rag_memory_id}, workspace_id={workspace_id}")
f"Read service: group={user_input.end_user_id}, storage_type={storage_type}, user_rag_memory_id={user_rag_memory_id}, workspace_id={workspace_id}, session_id={session_id}")
try:
# result = await memory_agent_service.read_memory(
# user_input.end_user_id,
# user_input.message,
# user_input.history,
# user_input.search_switch,
# config_id,
# db,
# storage_type,
# user_rag_memory_id
# )
# if str(user_input.search_switch) == "2":
# retrieve_info = result['answer']
# history = await SessionService(store).get_history(user_input.end_user_id, user_input.end_user_id,
# user_input.end_user_id)
# query = user_input.message
#
# # 调用 memory_agent_service 的方法生成最终答案
# result['answer'] = await memory_agent_service.generate_summary_from_retrieve(
# end_user_id=user_input.end_user_id,
# retrieve_info=retrieve_info,
# history=history,
# query=query,
# config_id=config_id,
# db=db
# )
# if "信息不足,无法回答" in result['answer']:
# result['answer'] = retrieve_info
memory_config = get_config(user_input.end_user_id, db)
service = MemoryService(
db,
memory_config["memory_config_id"],
end_user_id=user_input.end_user_id
)
session_cache = ChatSessionCache(session_id)
search_result = await service.read(
user_input.message,
SearchStrategy(user_input.search_switch)
SearchStrategy(user_input.search_switch),
history=await session_cache.get_history(),
)
intermediate_outputs = []
sub_queries = set()
for memory in search_result.memories:
sub_queries.add(str(memory.query))
idx = 0
if user_input.search_switch in [SearchStrategy.DEEP, SearchStrategy.NORMAL]:
intermediate_outputs.append({
"type": "problem_split",
"title": "问题拆分",
"data": [
{
"id": f"Q{idx+1}",
"id": f"Q{(idx := idx + 1)}",
"question": question
}
for idx, question in enumerate(sub_queries)
for question in sub_queries
if question
]
})
perceptual_data = [
@@ -375,16 +355,24 @@ async def read_server(
"raw_result": search_result.memories,
"total": len(search_result.memories),
})
answer = await memory_agent_service.generate_summary_from_retrieve(
end_user_id=user_input.end_user_id,
retrieve_info=search_result.content,
history=[],
query=user_input.message,
config_id=config_id,
db=db
)
await session_cache.append_many(
[
{"role": "user", "content": user_input.message},
{"role": "assistant", "content": answer}
]
)
result = {
'answer': await memory_agent_service.generate_summary_from_retrieve(
end_user_id=user_input.end_user_id,
retrieve_info=search_result.content,
history=[],
query=user_input.message,
config_id=config_id,
db=db
),
"intermediate_outputs": intermediate_outputs
'answer': answer,
"intermediate_outputs": intermediate_outputs,
"session_id": session_id,
}
return success(data=result, msg="回复对话消息成功")
@@ -480,9 +468,11 @@ async def read_server_async(
if knowledge: user_rag_memory_id = str(knowledge.id)
api_logger.info(f"Async read: storage_type={storage_type}, user_rag_memory_id={user_rag_memory_id}")
try:
session_id = user_input.session_id.hex
session_cache = ChatSessionCache(session_id)
task = celery_app.send_task(
"app.core.memory.agent.read_message",
args=[user_input.end_user_id, user_input.message, user_input.history, user_input.search_switch,
args=[user_input.end_user_id, user_input.message, await session_cache.get_history(), user_input.search_switch,
config_id, storage_type, user_rag_memory_id]
)
api_logger.info(f"Read task queued: {task.id}")