fix: NewAPI key strip sk- prefix + LLM wiki graceful fallback

This commit is contained in:
小唯 2026-07-02 01:00:23 +08:00
parent 57ac628b3f
commit c86f5bc304
1 changed files with 28 additions and 12 deletions

View File

@ -40,7 +40,7 @@ STATE_FILE = os.path.expanduser("~/.hermes/wiki_curator_state.json")
# LLM 配置
LLM_API = "http://127.0.0.1:3000/v1/chat/completions"
LLM_MODEL = "minimaxai/minimax-m3"
LLM_MODEL = "minimaxai/minimax-m2.7" # m3 sometimes returns empty, use m2.7
# 扫描时排除的目录名称(大小写不敏感)
EXCLUDE_DIRS = {
@ -259,7 +259,11 @@ def _get_llm_key() -> str:
cfg_path = os.path.expanduser("~/.hermes/config.yaml")
with open(cfg_path) as f:
cfg = yaml.safe_load(f)
return cfg.get("providers", {}).get("newapi-local", {}).get("api_key", "")
raw = cfg.get("providers", {}).get("newapi-local", {}).get("api_key", "")
# NewAPI 的 key 不需要 sk- 前缀
if raw.startswith("sk-"):
raw = raw[3:]
return raw
except Exception:
pass
# 回退到环境变量
@ -273,27 +277,39 @@ def _extract_with_llm(content: str, filepath: str) -> dict | None:
print(" ⚠️ No LLM API key found (check config.yaml or NEWAPI_API_KEY env)")
return None
prompt = f'''Analyze this technical document. Extract concepts (what things are), entities (specific instances), and relations (how they connect).
Return JSON ONLY:
{{"concepts": [{{"name":"...","summary":"..."}}],
"entities": [{{"name":"...","attributes":{{}}}}],
"relations": [{{"source":"...","relation":"uses|contains|depends_on|part_of|implements","target":"..."}}]}}
prompt = f'''Extract concepts, entities, and relations from this document.
Return ONLY valid JSON:
{{"concepts":[{{"name":"...","summary":"..."}}],"entities":[{{"name":"...","attributes":{{}}}}],"relations":[{{"source":"...","relation":"uses|contains|depends_on|part_of|implements","target":"..."}}]}}
Document: {content[:3000]}
Document:
{content[:2000]}
'''
try:
resp = requests.post(LLM_API,
headers={"Authorization": f"Bearer {llm_key}", "Content-Type": "application/json"},
json={"model": LLM_MODEL, "messages": [{"role": "user", "content": prompt}], "temperature": 0.1},
json={
"model": LLM_MODEL,
"messages": [
{"role": "system", "content": "You are a knowledge extraction assistant. Always respond with valid JSON only."},
{"role": "user", "content": prompt}
],
"temperature": 0.1,
"max_tokens": 1000,
},
timeout=30)
data = resp.json()
if "error" in data and data["error"].get("message"):
print(f" ⚠️ LLM API error: {data['error']['message'][:60]}")
return None
choices = data.get("choices", [])
if not choices:
print(" ⚠️ LLM returned empty choices (API/model may be unavailable)")
return None
text = choices[0].get("message", {}).get("content", "")
if not text:
print(" ⚠️ LLM returned empty content")
msg = choices[0].get("message", {})
text = msg.get("content", "") or ""
if not text.strip():
finish = choices[0].get("finish_reason", "")
print(f" ⚠️ LLM returned empty content (finish={finish})")
return None
# Parse JSON from response
json_match = re.search(r'\{[\s\S]*\}', text)