dotb_ai-platform/tests/test_aihub_two_pass.py
2026-09-25 09:55:25 +07:00

120 lines
4.2 KiB
Python

import json
import httpx
import pytest
from ai_platform.infrastructure.aihub import AiHubClient, AiHubError
from ai_platform.infrastructure.scoring import _scoring_system_prompt, _scoring_user_prompt
VKEY = "request-only-vkey-test-secret"
def completion(content: str) -> httpx.Response:
return httpx.Response(
200,
json={"choices": [{"message": {"content": content}}]},
)
@pytest.mark.asyncio
async def test_two_pass_adapter_uses_same_model_timeout_and_vkey_without_putting_key_in_prompts():
requests: list[httpx.Request] = []
def handler(request: httpx.Request) -> httpx.Response:
requests.append(request)
body = json.loads(request.content)
assert body["model"] == "openai/gpt-4o-mini"
assert body["stream"] is False
assert body["response_format"] == {"type": "json_object"}
assert request.headers["authorization"] == f"Bearer {VKEY}"
assert request.extensions["timeout"]["read"] == 7
return completion(
'{"items":[{"signal":"ý định","detail":"Hỏi điều kiện đăng ký","source":"message-1"}]}'
if len(requests) == 1
else '{"score":81,"confidence":0.91,"reasoning":"Quan tâm rõ ràng"}'
)
http_client = httpx.AsyncClient(transport=httpx.MockTransport(handler))
client = AiHubClient("https://aihub.test", http_client)
snapshot = {
"lead_profile": {"name": "Example", "custom_fields": {"region": "north"}},
"conversations": [
{
"messages": [
{
"message_id": "message-1",
"sender_type": "contact",
"content": "Please send me requirements.",
}
]
}
],
}
try:
evidence = await client.extract_evidence(
model="openai/gpt-4o-mini", snapshot=snapshot, vkey=VKEY, timeout=7
)
score = await client.score(
model="openai/gpt-4o-mini",
system_prompt=_scoring_system_prompt("Đánh giá theo hồ sơ AI đã cấu hình."),
user_prompt=_scoring_user_prompt(snapshot, evidence.model_dump(mode="json")),
vkey=VKEY,
timeout=7,
)
finally:
await client.aclose()
assert score.score == 81
assert score.confidence == 0.91
assert len(requests) == 2
for request in requests:
body = json.loads(request.content)
prompt = " ".join(message["content"] for message in body["messages"])
assert VKEY not in prompt
assert '"points"' not in prompt
assert '"rule_weight"' not in prompt
assert '"ai_weight"' not in prompt
assert "message-1" in json.loads(requests[0].content)["messages"][1]["content"]
assert "EVIDENCE" in json.loads(requests[1].content)["messages"][1]["content"]
@pytest.mark.asyncio
async def test_aihub_errors_have_stable_codes_and_do_not_expose_response_or_request_secret():
def handler(_request: httpx.Request) -> httpx.Response:
return httpx.Response(429, text=f"private response mentions {VKEY}")
client = AiHubClient(
"https://aihub.test", httpx.AsyncClient(transport=httpx.MockTransport(handler))
)
try:
with pytest.raises(AiHubError) as error:
await client.extract_evidence(model="openai/gpt-4o-mini", snapshot={}, vkey=VKEY)
finally:
await client.aclose()
assert error.value.error_code == "aihub_http_error"
assert VKEY not in str(error.value)
assert "private response" not in str(error.value)
@pytest.mark.asyncio
async def test_aihub_rejects_response_that_echoes_request_vkey():
client = AiHubClient(
"https://aihub.test",
httpx.AsyncClient(
transport=httpx.MockTransport(
lambda _request: completion(
json.dumps({"items": [{"signal": "s", "detail": VKEY, "source": "m"}]})
)
)
),
)
try:
with pytest.raises(AiHubError) as error:
await client.extract_evidence(model="openai/gpt-4o-mini", snapshot={}, vkey=VKEY)
finally:
await client.aclose()
assert error.value.error_code == "aihub_invalid_response"
assert VKEY not in str(error.value)