feat(memory): Add memory config API controller and end user info endpoints
- Create new memory_config_api_controller.py for dedicated memory configuration management - Add /end_user/info GET endpoint to retrieve end user information (aliases, metadata) - Add /end_user/info/update POST endpoint to update end user details - Move /memory/configs endpoint from memory_api_controller to memory_config_api_controller - Extract _get_current_user helper function to build user context from API key auth - Support optional app_id parameter in end user creation with UUID validation - Update service controller imports with alphabetical ordering and multi-line formatting - Register memory_config_api_controller router in service module initialization - Refactor memory_api_controller imports for consistency and clarity
This commit is contained in:
@@ -4,11 +4,6 @@
|
||||
本模块提供统一的搜索服务接口,支持关键词搜索、语义搜索和混合搜索。
|
||||
"""
|
||||
|
||||
from typing import TYPE_CHECKING
|
||||
|
||||
if TYPE_CHECKING:
|
||||
from app.schemas.memory_config_schema import MemoryConfig
|
||||
|
||||
from app.core.memory.storage_services.search.hybrid_search import HybridSearchStrategy
|
||||
from app.core.memory.storage_services.search.keyword_search import KeywordSearchStrategy
|
||||
from app.core.memory.storage_services.search.search_strategy import (
|
||||
@@ -29,115 +24,87 @@ __all__ = [
|
||||
|
||||
|
||||
# ============================================================================
|
||||
# 向后兼容的函数式API
|
||||
# 向后兼容的函数式API (DEPRECATED - 未被使用)
|
||||
# ============================================================================
|
||||
# 为了兼容旧代码,提供与 src/search.py 相同的函数式接口
|
||||
# 所有调用方均直接使用 app.core.memory.src.search.run_hybrid_search
|
||||
# 保留注释以备参考
|
||||
|
||||
|
||||
async def run_hybrid_search(
|
||||
query_text: str,
|
||||
search_type: str = "hybrid",
|
||||
end_user_id: str | None = None,
|
||||
apply_id: str | None = None,
|
||||
user_id: str | None = None,
|
||||
limit: int = 50,
|
||||
include: list[str] | None = None,
|
||||
alpha: float = 0.6,
|
||||
use_forgetting_curve: bool = False,
|
||||
memory_config: "MemoryConfig" = None,
|
||||
**kwargs
|
||||
) -> dict:
|
||||
"""运行混合搜索(向后兼容的函数式API)
|
||||
|
||||
这是一个向后兼容的包装函数,将旧的函数式API转换为新的基于类的API。
|
||||
|
||||
Args:
|
||||
query_text: 查询文本
|
||||
search_type: 搜索类型("hybrid", "keyword", "semantic")
|
||||
end_user_id: 组ID过滤
|
||||
apply_id: 应用ID过滤
|
||||
user_id: 用户ID过滤
|
||||
limit: 每个类别的最大结果数
|
||||
include: 要包含的搜索类别列表
|
||||
alpha: BM25分数权重(0.0-1.0)
|
||||
use_forgetting_curve: 是否使用遗忘曲线
|
||||
memory_config: MemoryConfig object containing embedding_model_id
|
||||
**kwargs: 其他参数
|
||||
|
||||
Returns:
|
||||
dict: 搜索结果字典,格式与旧API兼容
|
||||
"""
|
||||
from app.core.memory.llm_tools.openai_embedder import OpenAIEmbedderClient
|
||||
from app.core.models.base import RedBearModelConfig
|
||||
from app.db import get_db_context
|
||||
from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
||||
from app.services.memory_config_service import MemoryConfigService
|
||||
|
||||
if not memory_config:
|
||||
raise ValueError("memory_config is required for search")
|
||||
|
||||
# 初始化客户端
|
||||
connector = Neo4jConnector()
|
||||
with get_db_context() as db:
|
||||
config_service = MemoryConfigService(db)
|
||||
embedder_config_dict = config_service.get_embedder_config(str(memory_config.embedding_model_id))
|
||||
embedder_config = RedBearModelConfig(**embedder_config_dict)
|
||||
embedder_client = OpenAIEmbedderClient(embedder_config)
|
||||
|
||||
try:
|
||||
# 根据搜索类型选择策略
|
||||
if search_type == "keyword":
|
||||
strategy = KeywordSearchStrategy(connector=connector)
|
||||
elif search_type == "semantic":
|
||||
strategy = SemanticSearchStrategy(
|
||||
connector=connector,
|
||||
embedder_client=embedder_client
|
||||
)
|
||||
else: # hybrid
|
||||
strategy = HybridSearchStrategy(
|
||||
connector=connector,
|
||||
embedder_client=embedder_client,
|
||||
alpha=alpha,
|
||||
use_forgetting_curve=use_forgetting_curve
|
||||
)
|
||||
|
||||
# 执行搜索
|
||||
result = await strategy.search(
|
||||
query_text=query_text,
|
||||
end_user_id=end_user_id,
|
||||
limit=limit,
|
||||
include=include,
|
||||
alpha=alpha,
|
||||
use_forgetting_curve=use_forgetting_curve,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
# 转换为旧格式
|
||||
result_dict = result.to_dict()
|
||||
|
||||
# 保存到文件(如果指定了output_path)
|
||||
output_path = kwargs.get('output_path', 'search_results.json')
|
||||
if output_path:
|
||||
import json
|
||||
import os
|
||||
from datetime import datetime
|
||||
|
||||
try:
|
||||
# 确保目录存在
|
||||
out_dir = os.path.dirname(output_path)
|
||||
if out_dir:
|
||||
os.makedirs(out_dir, exist_ok=True)
|
||||
|
||||
# 保存结果
|
||||
with open(output_path, "w", encoding="utf-8") as f:
|
||||
json.dump(result_dict, f, ensure_ascii=False, indent=2, default=str)
|
||||
print(f"Search results saved to {output_path}")
|
||||
except Exception as e:
|
||||
print(f"Error saving search results: {e}")
|
||||
return result_dict
|
||||
|
||||
finally:
|
||||
await connector.close()
|
||||
|
||||
|
||||
__all__.append("run_hybrid_search")
|
||||
# async def run_hybrid_search(
|
||||
# query_text: str,
|
||||
# search_type: str = "hybrid",
|
||||
# end_user_id: str | None = None,
|
||||
# apply_id: str | None = None,
|
||||
# user_id: str | None = None,
|
||||
# limit: int = 50,
|
||||
# include: list[str] | None = None,
|
||||
# alpha: float = 0.6,
|
||||
# use_forgetting_curve: bool = False,
|
||||
# memory_config: "MemoryConfig" = None,
|
||||
# **kwargs
|
||||
# ) -> dict:
|
||||
# """运行混合搜索(向后兼容的函数式API)"""
|
||||
# from app.core.memory.llm_tools.openai_embedder import OpenAIEmbedderClient
|
||||
# from app.core.models.base import RedBearModelConfig
|
||||
# from app.db import get_db_context
|
||||
# from app.repositories.neo4j.neo4j_connector import Neo4jConnector
|
||||
# from app.services.memory_config_service import MemoryConfigService
|
||||
#
|
||||
# if not memory_config:
|
||||
# raise ValueError("memory_config is required for search")
|
||||
#
|
||||
# connector = Neo4jConnector()
|
||||
# with get_db_context() as db:
|
||||
# config_service = MemoryConfigService(db)
|
||||
# embedder_config_dict = config_service.get_embedder_config(str(memory_config.embedding_model_id))
|
||||
# embedder_config = RedBearModelConfig(**embedder_config_dict)
|
||||
# embedder_client = OpenAIEmbedderClient(embedder_config)
|
||||
#
|
||||
# try:
|
||||
# if search_type == "keyword":
|
||||
# strategy = KeywordSearchStrategy(connector=connector)
|
||||
# elif search_type == "semantic":
|
||||
# strategy = SemanticSearchStrategy(
|
||||
# connector=connector,
|
||||
# embedder_client=embedder_client
|
||||
# )
|
||||
# else:
|
||||
# strategy = HybridSearchStrategy(
|
||||
# connector=connector,
|
||||
# embedder_client=embedder_client,
|
||||
# alpha=alpha,
|
||||
# use_forgetting_curve=use_forgetting_curve
|
||||
# )
|
||||
#
|
||||
# result = await strategy.search(
|
||||
# query_text=query_text,
|
||||
# end_user_id=end_user_id,
|
||||
# limit=limit,
|
||||
# include=include,
|
||||
# alpha=alpha,
|
||||
# use_forgetting_curve=use_forgetting_curve,
|
||||
# **kwargs
|
||||
# )
|
||||
#
|
||||
# result_dict = result.to_dict()
|
||||
#
|
||||
# output_path = kwargs.get('output_path', 'search_results.json')
|
||||
# if output_path:
|
||||
# import json
|
||||
# import os
|
||||
# from datetime import datetime
|
||||
#
|
||||
# try:
|
||||
# out_dir = os.path.dirname(output_path)
|
||||
# if out_dir:
|
||||
# os.makedirs(out_dir, exist_ok=True)
|
||||
# with open(output_path, "w", encoding="utf-8") as f:
|
||||
# json.dump(result_dict, f, ensure_ascii=False, indent=2, default=str)
|
||||
# print(f"Search results saved to {output_path}")
|
||||
# except Exception as e:
|
||||
# print(f"Error saving search results: {e}")
|
||||
# return result_dict
|
||||
#
|
||||
# finally:
|
||||
# await connector.close()
|
||||
#
|
||||
# __all__.append("run_hybrid_search")
|
||||
|
||||
Reference in New Issue
Block a user