Summary
EvaluationPipeline._generate_answer awaits generate_with_usage:
# core/pipeline.py:196
response = await self._llm.generate_with_usage(prompt, ground_truth=ground_truth)
On every provider except Ollama, generate_with_usage is async def (openai.py:257, groq.py:227, mock.py:66, gemini, openrouter) — so this works. On Ollama it is plain def (ollama.py:250; the async variant is separately named generate_with_usage_async, a naming convention no sibling uses).
What actually happens with the Ollama provider
self._llm.generate_with_usage(prompt, ...) executes synchronously inside the event loop — the blocking httpx.Client.post stalls the loop for the whole Ollama generation;
- the call returns a non-awaitable, and
await <non-awaitable> raises TypeError;
_generate_answer's bare except Exception swallows it and returns ("", None, None).
Net effect: pipeline + Ollama produces an empty answer for every question, with no error surfaced — metrics quietly score empty strings. (Before #78/#193 the return was a tuple; the await failed the same way, so this predates and is independent of that fix.)
Suggested direction
Align Ollama with the sibling convention: make generate_with_usage async def (it already has an async twin to fold in), keeping a sync helper under a distinct name only if something needs it. That's an API rename, hence this issue rather than a rider on #193. A regression test could run the pipeline with the (mocked) Ollama provider and assert a non-empty answer comes back — today it can't.
Happy to send the PR for whichever direction you prefer.
Found while fixing #78 (PR #193); every claim above re-verified against current main. Disclosure: investigated and written with AI assistance (Claude).
Summary
EvaluationPipeline._generate_answerawaitsgenerate_with_usage:On every provider except Ollama,
generate_with_usageisasync def(openai.py:257, groq.py:227, mock.py:66, gemini, openrouter) — so this works. On Ollama it is plaindef(ollama.py:250; the async variant is separately namedgenerate_with_usage_async, a naming convention no sibling uses).What actually happens with the Ollama provider
self._llm.generate_with_usage(prompt, ...)executes synchronously inside the event loop — the blockinghttpx.Client.poststalls the loop for the whole Ollama generation;await <non-awaitable>raisesTypeError;_generate_answer's bareexcept Exceptionswallows it and returns("", None, None).Net effect: pipeline + Ollama produces an empty answer for every question, with no error surfaced — metrics quietly score empty strings. (Before #78/#193 the return was a tuple; the await failed the same way, so this predates and is independent of that fix.)
Suggested direction
Align Ollama with the sibling convention: make
generate_with_usageasync def(it already has an async twin to fold in), keeping a sync helper under a distinct name only if something needs it. That's an API rename, hence this issue rather than a rider on #193. A regression test could run the pipeline with the (mocked) Ollama provider and assert a non-empty answer comes back — today it can't.Happy to send the PR for whichever direction you prefer.
Found while fixing #78 (PR #193); every claim above re-verified against current
main. Disclosure: investigated and written with AI assistance (Claude).