Files
EPEEAIKit/art-agent/backend/app/memory.py

100 lines
2.9 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
"""
Mem0 记忆层初始化与健康检查。
启动时验证 Ollama 可达和模型可用,失败则抛出 RuntimeError 阻止后端启动。
"""
import logging
import httpx
from mem0 import Memory
from app.config import (
get_deepseek_api_key,
get_ollama_base_url,
get_mem0_embedding_model,
)
logger = logging.getLogger(__name__)
_memory: Memory | None = None
def _check_ollama_health() -> None:
"""检查 Ollama 服务是否可达,以及 embedding 模型是否已安装。"""
base_url = get_ollama_base_url()
model_name = get_mem0_embedding_model()
try:
resp = httpx.get(f"{base_url}/api/tags", timeout=5)
resp.raise_for_status()
except (httpx.ConnectError, httpx.TimeoutException, httpx.HTTPStatusError) as e:
raise RuntimeError(
f"无法连接 Ollama 服务({base_url})。"
f"请确认 Ollama 已启动:启动方式参见 https://ollama.com\n"
f"原始错误:{e}"
) from e
models = resp.json().get("models", [])
installed = [m.get("name", "").split(":")[0] for m in models]
if model_name not in installed:
raise RuntimeError(
f"Ollama 已运行,但未找到 embedding 模型 '{model_name}'\n"
f"已安装的模型:{installed}\n"
f"请运行ollama pull {model_name}"
)
logger.info("Ollama 健康检查通过:%s 模型可用", model_name)
def init_memory() -> Memory:
"""初始化 Mem0 Memory 单例。首次调用时执行健康检查。"""
global _memory
if _memory is not None:
return _memory
_check_ollama_health()
deepseek_key = get_deepseek_api_key()
if not deepseek_key:
raise RuntimeError(
"DEEPSEEK_API_KEY 未配置。Mem0 需要该 key 进行事实提取。\n"
"请在 .env 中设置 DEEPSEEK_API_KEY"
)
config = {
"llm": {
"provider": "deepseek",
"config": {
"model": "deepseek-chat",
"temperature": 0.1,
"max_tokens": 1500,
"api_key": deepseek_key,
},
},
"embedder": {
"provider": "ollama",
"config": {
"model": get_mem0_embedding_model(),
"ollama_base_url": get_ollama_base_url(),
},
},
"vector_store": {
"provider": "qdrant",
"config": {
"collection_name": "epeekit_memories",
"embedding_model_dims": 768,
"path": "./data/qdrant",
},
},
}
_memory = Memory.from_config(config)
logger.info("Mem0 记忆层初始化成功")
return _memory
def get_memory() -> Memory:
"""获取已初始化的 Memory 实例。未初始化时自动调用 init_memory()。"""
if _memory is None:
return init_memory()
return _memory