1324f1575d
- 重寫 action.yaml:支援所有 LLM providers 的 inputs - 重寫 Dockerfile:python:3.11-slim + git - 重寫 entrypoint.sh:啟動 app/main.py - app/config.py:環境變數與 LLM 自動偵測 - app/llm.py:OpenAI-compatible 統一介面 - app/gitea.py:PR diff 取得與 comment 發布 - app/roles.py:從 prompts/roles/*.yaml 載入角色 - app/main.py:pipeline 骨架,log 每個主要階段 - app/prompts/roles/:五個角色定義(Aria/Rex/Zara/Leo/Maya)
51 lines
1.6 KiB
Python
51 lines
1.6 KiB
Python
import json
|
|
import requests
|
|
from config import get_llm_config
|
|
|
|
|
|
def chat(system_prompt: str, user_content: str) -> str:
|
|
"""呼叫 LLM,回傳回應文字。失敗時拋出例外。"""
|
|
provider, api_key, base_url, model = get_llm_config()
|
|
if not provider:
|
|
raise RuntimeError("未設定任何 LLM API Key")
|
|
|
|
print(f" [LLM] provider={provider} model={model}")
|
|
|
|
# 所有服務統一用 OpenAI-compatible chat completions 介面
|
|
url = f"{base_url.rstrip('/')}/chat/completions"
|
|
headers = {
|
|
"Content-Type": "application/json",
|
|
"Authorization": f"Bearer {api_key}",
|
|
}
|
|
# Claude 額外 header
|
|
if provider == "claude":
|
|
headers["anthropic-version"] = "2023-06-01"
|
|
|
|
payload = {
|
|
"model": model,
|
|
"messages": [
|
|
{"role": "system", "content": system_prompt},
|
|
{"role": "user", "content": user_content},
|
|
],
|
|
"temperature": 0.2,
|
|
}
|
|
|
|
resp = requests.post(url, headers=headers, json=payload, timeout=120)
|
|
resp.raise_for_status()
|
|
return resp.json()["choices"][0]["message"]["content"]
|
|
|
|
|
|
def chat_json(system_prompt: str, user_content: str) -> list:
|
|
"""呼叫 LLM 並解析 JSON 陣列回應。失敗時回傳空陣列。"""
|
|
try:
|
|
text = chat(system_prompt, user_content)
|
|
# 去除可能的 markdown code block
|
|
text = text.strip()
|
|
if text.startswith("```"):
|
|
text = text.split("\n", 1)[1]
|
|
text = text.rsplit("```", 1)[0]
|
|
return json.loads(text)
|
|
except Exception as e:
|
|
print(f" [LLM] 解析失敗: {e}")
|
|
return []
|