fix: timeout do provedor nunca chegava ao httpx; endpoint agora visível
Causa do 'Provedor de LLM indisponível' no ambiente com Ollama local foi externa: OLLAMA_BASE_URL exportada no shell (http://localhost:11434/v1) vence o .env na interpolação do docker-compose, e localhost dentro do container é o próprio container. Nada no app indicava a URL em uso. Dois defeitos de código que tornavam isso indetectável — e um deles produziria a mesma mensagem mesmo com a URL correta: - _BaseProvider criava o httpx.AsyncClient com o atributo de classe (120 s) e as subclasses atribuíam self.timeout depois. O httpx congela o timeout na construção, então os 300 s pedidos pelo Ollama nunca valeram: um primeiro atendimento com modelo frio era cortado em 120 s com exatamente a mensagem 'provedor indisponível'. O timeout agora é passado ao super(). - LLMProviderError de conexão não citava o endereço tentado; o log dizia só 'All connection attempts failed'. Passa a incluir a endpoint, com credenciais user:pass@ redigidas. /api/health expõe llm_endpoint para comparação direta com o .env. README e .env.example documentam a precedência shell > .env, o fato de /v1 ser a superfície OpenAI-compatível (o adaptador usa /api/chat nativo) e a latência medida do primeiro atendimento.
This commit is contained in:
1 parent
ebf430c535
commit
68861b502c
7 files changed
+188
-8
No files matched your search
@@ -240,3 +240,63 @@ def test_system_prompt_declares_the_off_topic_scope():
|
||||
assert "receita" in lowered
|
||||
assert "apenas do texto bíblico" in lowered
|
||||
assert "não use os trechos recuperados" in lowered
|
||||
|
||||
|
||||
# --------------------------------------------------------------------------- #
|
||||
# Timeout efetivo e erros acionáveis
|
||||
# --------------------------------------------------------------------------- #
|
||||
|
||||
|
||||
def close(provider):
|
||||
import asyncio
|
||||
|
||||
asyncio.run(provider.aclose())
|
||||
|
||||
|
||||
@pytest.mark.parametrize(
|
||||
"provider_factory,esperado",
|
||||
[
|
||||
(lambda: OllamaProvider(base_url="http://x", model="m"), 300),
|
||||
(lambda: OllamaProvider(base_url="http://x", model="m", timeout=45), 45),
|
||||
(lambda: OpenAIProvider(base_url="http://x", model="m", api_key="k"), 120),
|
||||
(lambda: AnthropicProvider(base_url="http://x", model="m", api_key="k"), 120),
|
||||
],
|
||||
)
|
||||
def test_configured_timeout_reaches_the_http_client(provider_factory, esperado):
|
||||
"""Atribuir `self.timeout` depois de criar o cliente não muda o cliente.
|
||||
|
||||
O `httpx.AsyncClient` congela o timeout na construção. Atribuir o atributo
|
||||
em seguida deixava o Ollama preso aos 120 s da classe mesmo pedindo 300 —
|
||||
pouco para um modelo local em CPU, e o sintoma é justamente "provedor
|
||||
indisponível".
|
||||
"""
|
||||
provider = provider_factory()
|
||||
|
||||
assert provider._client.timeout.read == esperado
|
||||
close(provider)
|
||||
|
||||
|
||||
def test_connection_error_names_the_endpoint():
|
||||
"""Sem a URL, o operador vê só 'falha de conexão' e não sabe o que testar.
|
||||
|
||||
Foi assim que um `OLLAMA_BASE_URL` herdado do shell, apontando para
|
||||
`localhost` dentro do container, ficou invisível: o log dizia apenas "All
|
||||
connection attempts failed".
|
||||
"""
|
||||
provider = OllamaProvider(base_url="http://127.0.0.1:1", model="m")
|
||||
|
||||
with pytest.raises(LLMProviderError) as excinfo:
|
||||
collect(provider)
|
||||
|
||||
assert "127.0.0.1:1" in str(excinfo.value)
|
||||
|
||||
|
||||
def test_connection_error_does_not_leak_the_api_key():
|
||||
provider = OpenAIProvider(
|
||||
base_url="http://127.0.0.1:1", model="m", api_key="sk-segredo-real"
|
||||
)
|
||||
|
||||
with pytest.raises(LLMProviderError) as excinfo:
|
||||
collect(provider)
|
||||
|
||||
assert "sk-segredo-real" not in str(excinfo.value)
|
||||
Reference in new issue
Block a user