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 <noreply@anthropic.com>
Co-Authored-By: Happy <yesreply@happy.engineering>
This commit is contained in:
liyizhouAI 2026-04-13 14:09:26 +08:00
parent 05a5ba0775
commit a35ba347f3
3 changed files with 30 additions and 26 deletions

View File

@ -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,

View File

@ -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')

View File

@ -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)