From 62d5d3f550892ae6f9c62c2c60204626c44f3f81 Mon Sep 17 00:00:00 2001 From: Carlos Garcia Date: Sat, 16 May 2026 01:17:58 -0400 Subject: [PATCH] fix: force JSON output for Ollama intent classification; fix attachment detection - ollama_backend: add format='json' for 'master' and receipt_parser callers so llama3.1:8b returns valid JSON instead of plain English - ab_ai_mail: add debug logging to trace attachment_ids from Discuss; handle file-only messages and clarification look-back flow Co-Authored-By: Claude Sonnet 4.6 --- addons/activeblue_ai/models/ab_ai_mail.py | 14 ++++++++++++++ agent_service/llm/ollama_backend.py | 5 +++++ 2 files changed, 19 insertions(+) diff --git a/addons/activeblue_ai/models/ab_ai_mail.py b/addons/activeblue_ai/models/ab_ai_mail.py index 7a54306..acee401 100644 --- a/addons/activeblue_ai/models/ab_ai_mail.py +++ b/addons/activeblue_ai/models/ab_ai_mail.py @@ -84,6 +84,20 @@ class DiscussChannel(models.Model): return result text = _strip_html(body) + + # Odoo 18 Discuss uploads attachments before posting the message and + # passes their IDs in kwargs as attachment_ids (list of ints or ORM + # commands). result.attachment_ids resolves those after super() runs. + # Log both so we can see exactly what arrives. + _logger.info( + 'AB AI mail hook: body=%r kwargs_keys=%s ' + 'attachment_ids_kwarg=%r result.attachment_ids=%s', + (body or '')[:80], + list(kwargs.keys()), + kwargs.get('attachment_ids'), + result.attachment_ids.ids, + ) + attachments = result.attachment_ids # Nothing to work with diff --git a/agent_service/llm/ollama_backend.py b/agent_service/llm/ollama_backend.py index c6d64eb..99b2b84 100644 --- a/agent_service/llm/ollama_backend.py +++ b/agent_service/llm/ollama_backend.py @@ -24,6 +24,11 @@ class OllamaBackend: kwargs = {'model': self._model, 'messages': messages} if tools: kwargs['tools'] = tools + # Force structured JSON output for callers that parse JSON responses. + # Without this llama3.1:8b returns plain English instead of JSON. + _JSON_CALLERS = {'master', 'expenses_agent_receipt_parser'} + if caller in _JSON_CALLERS and not tools: + kwargs['format'] = 'json' client = ollama.AsyncClient(host=self._url) try: response = await asyncio.wait_for(client.chat(**kwargs), timeout=self._timeout)