fix(hermes): 改用 anthropic Python SDK 直呼,棄用需要 claude CLI 的 claude-agent-sdk
Some checks failed
CD Pipeline / build-and-deploy (push) Has been cancelled

根因:claude-agent-sdk 需要 spawn claude CLI,prod pod 沒有 CLI 所以 SDK 回空。
修法:改用 anthropic.AsyncAnthropic().messages.create() 直呼 API。
model: claude-haiku-4-5-20251001(快速低成本,適合 Telegram QA)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
Your Name
2026-04-25 03:08:51 +08:00
parent c14f23b33a
commit d467cac709
2 changed files with 35 additions and 20 deletions

View File

@@ -1,19 +1,20 @@
"""Hermes 自然語言閘道 — ADR-094
Layer 1 意圖路由(關鍵字正則)→ Claude Agent SDK 呼 → Telegram 格式化輸出。
Layer 1 意圖路由(關鍵字正則)→ Anthropic Python SDK 呼 → Telegram 格式化輸出。
2026-04-24 Claude Sonnet 4.6 (WS4 Hermes NL)
2026-04-24 Claude Sonnet 4.6 (WS4 Hermes NL T1+T2+T3): hermes_dispatch_log DB 寫入 /
Redis per-chat_id 速率限制 / Multi-turn session (Redis Hash TTL=300s)
2026-04-25 Claude Sonnet 4.6: 改用 anthropic Python SDK 直呼,棄用需要 CLI 的
claude-agent-sdkprod pod 無 claude CLIsdk call 回傳空字串)
"""
from __future__ import annotations
import asyncio
import re
import time
import anthropic as _anthropic
import structlog
from claude_agent_sdk import query, ClaudeAgentOptions
from claude_agent_sdk.types import ResultMessage
from sqlalchemy import text
from src.core.config import settings
@@ -43,8 +44,6 @@ _ROUTING_RULES: list[tuple[re.Pattern, str]] = [
(re.compile(r"(實作|implement|develop|功能|feature)", re.IGNORECASE), "fullstack-engineer"),
]
_HERMES_BUDGET_USD = 0.05
# ─────────────────────────────────────────────────────────────────────────────
# T2速率限制常數ADR-094
# ─────────────────────────────────────────────────────────────────────────────
@@ -222,25 +221,18 @@ async def process_nl_message(
t0 = time.monotonic()
# 呼叫 Claude Agent SDK
# 呼叫 Anthropic Python SDK直呼 messages.create不依賴 claude CLI
success = False
error_type: str | None = None
try:
sdk_env: dict[str, str] = {}
if settings.CLAUDE_API_KEY:
sdk_env["ANTHROPIC_API_KEY"] = settings.CLAUDE_API_KEY
options = ClaudeAgentOptions(
system_prompt=system_prompt,
max_turns=3,
permission_mode="dontAsk",
max_budget_usd=_HERMES_BUDGET_USD,
env=sdk_env,
_client = _anthropic.AsyncAnthropic(api_key=settings.CLAUDE_API_KEY or None)
_msg = await _client.messages.create(
model="claude-haiku-4-5-20251001",
max_tokens=1500,
system=system_prompt,
messages=[{"role": "user", "content": prompt_with_ctx}],
)
result_text = ""
async for event in query(prompt=prompt_with_ctx, options=options):
if isinstance(event, ResultMessage):
result_text = getattr(event, "result", "") or ""
break
result_text = _msg.content[0].text if _msg.content else ""
if not result_text:
result_text = "_Agent 回應為空請稍後再試。_"