fix(api): enforce global ollama endpoint order
All checks were successful
Code Review / ai-code-review (push) Successful in 11s
CD Pipeline / tests (push) Successful in 5m13s
CD Pipeline / build-and-deploy (push) Successful in 3m31s
CD Pipeline / post-deploy-checks (push) Successful in 1m18s

This commit is contained in:
Your Name
2026-05-19 12:31:56 +08:00
parent 5fa0e1452c
commit 45cd55b2da
7 changed files with 359 additions and 228 deletions

View File

@@ -20,7 +20,7 @@ import structlog
from src.core.config import get_settings
from src.services.model_registry import get_model
from src.services.ollama_endpoint_resolver import resolve_ollama_endpoint
from src.services.ollama_endpoint_resolver import resolve_ollama_order
logger = structlog.get_logger(__name__)
settings = get_settings()
@@ -120,26 +120,54 @@ class LocalCodeReviewService:
"格式:每個問題獨立一行,以「⚠️」開頭。如果沒有問題,說「✅ 程式碼品質良好」\n\n"
f"=== Diff ===\n{diff[:40000]}\n=== 結束 ==="
)
try:
http = await self._get_http()
resp = await http.post(
f"{resolve_ollama_endpoint('code_review')}/api/generate",
json={
"model": _MODEL_OLLAMA,
"prompt": prompt,
"stream": False,
"options": {"num_predict": 1024, "temperature": 0.1},
},
)
if resp.status_code == 200:
text = resp.json().get("response", "").strip()
issues = text.count("⚠️")
logger.info("pr_review_ollama_done", pr_id=pr_id, issues=issues)
return {"review_text": text, "issues_count": issues, "model": _MODEL_OLLAMA, "provider": "ollama"}
except httpx.TimeoutException:
logger.warning("pr_review_ollama_timeout", pr_id=pr_id)
except Exception as e:
logger.error("pr_review_ollama_failed", pr_id=pr_id, error=str(e))
http = await self._get_http()
for endpoint in resolve_ollama_order("code_review"):
if not endpoint.url:
continue
try:
resp = await http.post(
f"{endpoint.url}/api/generate",
json={
"model": _MODEL_OLLAMA,
"prompt": prompt,
"stream": False,
"options": {"num_predict": 1024, "temperature": 0.1},
},
)
if resp.status_code == 200:
text = resp.json().get("response", "").strip()
issues = text.count("⚠️")
logger.info(
"pr_review_ollama_done",
pr_id=pr_id,
issues=issues,
provider=endpoint.provider_name,
)
return {
"review_text": text,
"issues_count": issues,
"model": _MODEL_OLLAMA,
"provider": endpoint.provider_name,
}
logger.warning(
"pr_review_ollama_http_error",
pr_id=pr_id,
provider=endpoint.provider_name,
status=resp.status_code,
)
except httpx.TimeoutException:
logger.warning(
"pr_review_ollama_timeout",
pr_id=pr_id,
provider=endpoint.provider_name,
)
except Exception as e:
logger.error(
"pr_review_ollama_failed",
pr_id=pr_id,
provider=endpoint.provider_name,
error=str(e),
)
return None
async def _review_with_gemini(
@@ -243,26 +271,55 @@ class LocalCodeReviewService:
"格式:每個問題以「⚠️」開頭,如無問題說「✅ Push 品質正常」\n"
"5 行以內,繁體中文。"
)
try:
http = await self._get_http()
resp = await http.post(
f"{resolve_ollama_endpoint('code_review')}/api/generate",
json={
"model": _MODEL_OLLAMA,
"prompt": prompt,
"stream": False,
"options": {"num_predict": 512, "temperature": 0.1},
},
)
if resp.status_code == 200:
text = resp.json().get("response", "").strip()
issues = text.count("⚠️")
logger.info("push_review_ollama_done", repo=repo_name, branch=branch, issues=issues)
return {"review_text": text, "issues_count": issues, "model": _MODEL_OLLAMA, "provider": "ollama"}
except httpx.TimeoutException:
logger.warning("push_review_ollama_timeout", repo=repo_name)
except Exception as e:
logger.error("push_review_ollama_failed", repo=repo_name, error=str(e))
http = await self._get_http()
for endpoint in resolve_ollama_order("code_review"):
if not endpoint.url:
continue
try:
resp = await http.post(
f"{endpoint.url}/api/generate",
json={
"model": _MODEL_OLLAMA,
"prompt": prompt,
"stream": False,
"options": {"num_predict": 512, "temperature": 0.1},
},
)
if resp.status_code == 200:
text = resp.json().get("response", "").strip()
issues = text.count("⚠️")
logger.info(
"push_review_ollama_done",
repo=repo_name,
branch=branch,
issues=issues,
provider=endpoint.provider_name,
)
return {
"review_text": text,
"issues_count": issues,
"model": _MODEL_OLLAMA,
"provider": endpoint.provider_name,
}
logger.warning(
"push_review_ollama_http_error",
repo=repo_name,
provider=endpoint.provider_name,
status=resp.status_code,
)
except httpx.TimeoutException:
logger.warning(
"push_review_ollama_timeout",
repo=repo_name,
provider=endpoint.provider_name,
)
except Exception as e:
logger.error(
"push_review_ollama_failed",
repo=repo_name,
provider=endpoint.provider_name,
error=str(e),
)
return None
async def close(self) -> None: