From a35ba347f38ca9c6d14bc4dfe3c754e59f1a2bc0 Mon Sep 17 00:00:00 2001 From: liyizhouAI Date: Mon, 13 Apr 2026 14:09:26 +0800 Subject: [PATCH] fix: use SiliconFlow free LLM+embedding for Graphiti - Graphiti LLM: SiliconFlow Qwen/Qwen2.5-7B-Instruct (free, supports structured output) - Graphiti Embedding: SiliconFlow BAAI/bge-m3 (free, OpenAI-compatible) - MiniMax Coding Plan doesn't support structured output needed by Graphiti - Separate GRAPHITI_LLM_* config from main LLM_* config - Remove _wait_for_episodes call (Graphiti processes synchronously) Generated with [Claude Code](https://claude.ai/code) via [Happy](https://happy.engineering) Co-Authored-By: Claude Co-Authored-By: Happy --- backend/app/api/graph.py | 19 ++--------------- backend/app/config.py | 10 +++++++++ backend/app/services/graphiti_client.py | 27 ++++++++++++++++--------- 3 files changed, 30 insertions(+), 26 deletions(-) diff --git a/backend/app/api/graph.py b/backend/app/api/graph.py index b59fd0ea..f20d1a6a 100644 --- a/backend/app/api/graph.py +++ b/backend/app/api/graph.py @@ -444,23 +444,8 @@ def build_graph(): progress_callback=add_progress_callback ) - # 等待Zep处理完成(查询每个episode的processed状态) - task_manager.update_task( - task_id, - message=t('progress.waitingZepProcess'), - progress=55 - ) - - def wait_progress_callback(msg, progress_ratio): - progress = 55 + int(progress_ratio * 35) # 55% - 90% - task_manager.update_task( - task_id, - message=msg, - progress=progress - ) - - builder._wait_for_episodes(episode_uuids, wait_progress_callback) - + # Graphiti 同步处理,不需要轮询 episode 状态 + # 获取图谱数据 task_manager.update_task( task_id, diff --git a/backend/app/config.py b/backend/app/config.py index 195762d9..37ad0ee9 100644 --- a/backend/app/config.py +++ b/backend/app/config.py @@ -37,6 +37,16 @@ class Config: NEO4J_USER = os.environ.get('NEO4J_USER', 'neo4j') NEO4J_PASSWORD = os.environ.get('NEO4J_PASSWORD', 'foresight2026') + # Graphiti LLM 配置(SiliconFlow,用于图谱构建的 structured output) + GRAPHITI_LLM_API_KEY = os.environ.get('GRAPHITI_LLM_API_KEY') + GRAPHITI_LLM_BASE_URL = os.environ.get('GRAPHITI_LLM_BASE_URL', 'https://api.siliconflow.cn/v1') + GRAPHITI_LLM_MODEL = os.environ.get('GRAPHITI_LLM_MODEL', 'Qwen/Qwen2.5-7B-Instruct') + + # Embedding 配置(SiliconFlow 免费 BAAI/bge-m3) + EMBEDDING_API_KEY = os.environ.get('EMBEDDING_API_KEY') + EMBEDDING_BASE_URL = os.environ.get('EMBEDDING_BASE_URL', 'https://api.siliconflow.cn/v1') + EMBEDDING_MODEL = os.environ.get('EMBEDDING_MODEL', 'BAAI/bge-m3') + # 兼容旧配置:ZEP_API_KEY 不再需要 ZEP_API_KEY = os.environ.get('ZEP_API_KEY', 'deprecated') diff --git a/backend/app/services/graphiti_client.py b/backend/app/services/graphiti_client.py index fcf5bb9f..c8f667fb 100644 --- a/backend/app/services/graphiti_client.py +++ b/backend/app/services/graphiti_client.py @@ -159,21 +159,30 @@ class GraphitiClient: from graphiti_core.llm_client.openai_generic_client import OpenAIGenericClient from graphiti_core.llm_client.config import LLMConfig + # Use SiliconFlow LLM for Graphiti (better structured output support) + graphiti_api_key = Config.GRAPHITI_LLM_API_KEY or Config.LLM_API_KEY + graphiti_base_url = Config.GRAPHITI_LLM_BASE_URL or Config.LLM_BASE_URL + graphiti_model = Config.GRAPHITI_LLM_MODEL or Config.LLM_MODEL_NAME + llm_config = LLMConfig( - api_key=Config.LLM_API_KEY, - model=Config.LLM_MODEL_NAME, - small_model=Config.LLM_MODEL_NAME, - base_url=Config.LLM_BASE_URL, + api_key=graphiti_api_key, + model=graphiti_model, + small_model=graphiti_model, + base_url=graphiti_base_url, ) llm_client = OpenAIGenericClient(config=llm_config) - # Embedder: custom MiniMax embedder (their API uses 'texts' not 'input') - embedder = MiniMaxEmbedder( - api_key=Config.LLM_API_KEY, - base_url=Config.LLM_BASE_URL, + # Embedder: SiliconFlow free BAAI/bge-m3 (OpenAI-compatible) + from graphiti_core.embedder.openai import OpenAIEmbedder, OpenAIEmbedderConfig + embedder_config = OpenAIEmbedderConfig( + api_key=Config.EMBEDDING_API_KEY or Config.LLM_API_KEY, + base_url=Config.EMBEDDING_BASE_URL or "https://api.siliconflow.cn/v1", + embedding_model=Config.EMBEDDING_MODEL or "BAAI/bge-m3", + embedding_dim=1024, ) + embedder = OpenAIEmbedder(config=embedder_config) - # Reranker: use the same LLM config (MiniMax-compatible) + # Reranker: use the LLM config (MiniMax) from graphiti_core.cross_encoder.openai_reranker_client import OpenAIRerankerClient reranker = OpenAIRerankerClient(config=llm_config)