flexigo-support-bot / tests /llm /test_groq.py
victor34593993's picture
multi-key failover + grounding + isolation
6edcbff verified
Raw
History Blame
3.34 kB
from __future__ import annotations
import httpx
import pytest
import respx
from app.llm.base import ProviderError, RateLimitError
from app.llm.groq import GroqProvider
URL = "https://api.groq.com/openai/v1/chat/completions"
def _provider() -> GroqProvider:
return GroqProvider(api_key="k")
@respx.mock
async def test_groq_returns_content():
respx.post(URL).mock(
return_value=httpx.Response(
200,
json={"choices": [{"finish_reason": "stop", "message": {"content": "hola"}}]},
)
)
r = await _provider().chat(messages=[{"role": "user", "content": "x"}], tools=[], model="m")
assert r.content == "hola"
assert r.tool_calls == []
@respx.mock
async def test_groq_parses_tool_calls():
respx.post(URL).mock(
return_value=httpx.Response(
200,
json={
"choices": [
{
"finish_reason": "tool_calls",
"message": {
"content": None,
"tool_calls": [
{
"id": "c1",
"type": "function",
"function": {
"name": "lookup_order",
"arguments": '{"email":"a@b.c"}',
},
}
],
},
}
]
},
)
)
r = await _provider().chat(
messages=[{"role": "user", "content": "x"}], tools=[], model="llama-3.1-8b-instant"
)
assert r.tool_calls[0].name == "lookup_order"
assert r.tool_calls[0].arguments == {"email": "a@b.c"}
@respx.mock
async def test_groq_captures_token_usage():
respx.post(URL).mock(
return_value=httpx.Response(
200,
json={
"choices": [{"finish_reason": "stop", "message": {"content": "ok"}}],
"usage": {"prompt_tokens": 120, "completion_tokens": 30, "total_tokens": 150},
},
)
)
r = await _provider().chat(messages=[{"role": "user", "content": "x"}], tools=[], model="m")
assert r.usage["total_tokens"] == 150
assert r.usage["prompt_tokens"] == 120
@respx.mock
async def test_groq_429_raises_ratelimit():
respx.post(URL).mock(return_value=httpx.Response(429, text="slow down"))
with pytest.raises(RateLimitError):
await _provider().chat(messages=[{"role": "user", "content": "x"}], tools=[], model="m")
@respx.mock
async def test_groq_500_raises_provider_error():
respx.post(URL).mock(return_value=httpx.Response(500, text="boom"))
with pytest.raises(ProviderError):
await _provider().chat(messages=[{"role": "user", "content": "x"}], tools=[], model="m")
@respx.mock
async def test_groq_malformed_200_raises_provider_error_for_failover():
# 200 OK but no choices → must become ProviderError so the router fails over.
respx.post(URL).mock(return_value=httpx.Response(200, json={"unexpected": True}))
with pytest.raises(ProviderError):
await _provider().chat(messages=[{"role": "user", "content": "x"}], tools=[], model="m")