82 lines
3.5 KiB
Python
82 lines
3.5 KiB
Python
# Part of Odoo. See LICENSE file for full copyright and licensing details.
|
|
|
|
import logging
|
|
import lxml.html
|
|
|
|
from odoo import models, api
|
|
|
|
_logger = logging.getLogger(__name__)
|
|
|
|
|
|
class MailRenderMixinAI(models.AbstractModel):
|
|
_inherit = "mail.render.mixin"
|
|
|
|
@api.model
|
|
def _render_template_get_valid_options(self):
|
|
return super()._render_template_get_valid_options() | {"eval_ai_prompts"}
|
|
|
|
def _valid_field_parameter(self, field, name):
|
|
return name == "eval_ai_prompts" or super()._valid_field_parameter(field, name)
|
|
|
|
@api.model
|
|
def _render_template(self, template_src, model, res_ids, engine='inline_template', add_context=None, options=None):
|
|
result = super()._render_template(
|
|
template_src, model, res_ids,
|
|
engine=engine,
|
|
add_context=add_context,
|
|
options=options,
|
|
)
|
|
if not (options or {}).get("eval_ai_prompts"):
|
|
return result
|
|
|
|
# check if there are html with AI prompts to evaluate, short-circuit if not
|
|
has_ai_prompts = False
|
|
for rendered in result.values():
|
|
if rendered and lxml.html.fromstring(rendered).xpath("//div[hasclass('o_editor_prompt')]"):
|
|
has_ai_prompts = True
|
|
break
|
|
|
|
if not has_ai_prompts:
|
|
return result
|
|
|
|
ai_composer = self.env.ref("ai.ai_mail_template_prompt_evaluator", raise_if_not_found=False)
|
|
if not ai_composer:
|
|
_logger.warning("The AI composer record used to evaluate AI prompts for mails is missing. The prompts are removed.")
|
|
|
|
default_agent = self.env.ref("ai.ai_default_agent", raise_if_not_found=False) or self.env["ai.agent"]
|
|
if not default_agent:
|
|
_logger.warning("The default AI agent is missing. The prompts are removed.")
|
|
|
|
author = self.env.user.partner_id
|
|
if self and 'author_id' in self and len(self) == 1:
|
|
author = self.author_id
|
|
|
|
for res_id in result:
|
|
ai_context = ""
|
|
if ai_composer:
|
|
ai_context += ai_composer.default_prompt or ""
|
|
ai_context += "\n\nUse the following information when necessary to generate the response:\n\n"
|
|
# TODO: How about the recipients list?
|
|
ai_context += f"\nSender: {author.name}"
|
|
# `lang` is already set in the context by _render_field which calls this method.
|
|
ai_context += f"\nRecipient language: {self.env.context.get('lang', 'en_US')}"
|
|
result[res_id] = default_agent._eval_ai_prompts(result[res_id],
|
|
remove_prompts=not (ai_composer and default_agent),
|
|
ai_context=ai_context)
|
|
|
|
return result
|
|
|
|
def _render_field(self, field, res_ids, engine='inline_template',
|
|
# lang options
|
|
compute_lang=False, res_ids_lang=False, set_lang=False,
|
|
# rendering context and options
|
|
add_context=None, options=None):
|
|
# Use the field's eval_ai_prompts attr if no 'eval_ai_prompts' option is provided
|
|
if getattr(self._fields[field], "eval_ai_prompts", False) and "eval_ai_prompts" not in (options or {}):
|
|
options = {**(options or {}), 'eval_ai_prompts': True}
|
|
return super()._render_field(
|
|
field, res_ids, engine=engine,
|
|
compute_lang=compute_lang, set_lang=set_lang, res_ids_lang=res_ids_lang,
|
|
add_context=add_context, options=options,
|
|
)
|