81 lines
2.7 KiB
Python
81 lines
2.7 KiB
Python
from json.decoder import JSONDecodeError
|
|
from logging import getLogger
|
|
|
|
from requests.exceptions import RequestException
|
|
|
|
from odoo import api, fields, models, modules
|
|
from odoo.exceptions import UserError
|
|
from odoo.addons.ai.utils.llm_api_service import LLMApiService
|
|
|
|
_logger = getLogger(__name__)
|
|
|
|
|
|
class VoipCall(models.Model):
|
|
_inherit = "voip.call"
|
|
|
|
transcript = fields.Text()
|
|
transcription_status = fields.Selection(
|
|
[
|
|
("pending", "Pending"), # waiting for cron
|
|
("queued", "Queued"), # picked by cron, might get stuck in this state
|
|
("done", "Done"), # success
|
|
("error", "Error"), # API failure
|
|
("too_big_to_process", "Too long to process"), # >25 MB
|
|
("no_audio", "No audio"), # attachment missing
|
|
],
|
|
default="no_audio",
|
|
copy=False,
|
|
index=True,
|
|
)
|
|
summary = fields.Char(string="Summary", copy=False)
|
|
|
|
@api.model
|
|
def _cron_transcribe_recent_voip_call(self):
|
|
call = self.search(
|
|
[("transcription_status", "=", "pending")],
|
|
order="create_date desc",
|
|
limit=1,
|
|
)
|
|
if not call:
|
|
return
|
|
call.transcription_status = "queued"
|
|
if not modules.module.current_test:
|
|
self.env.cr.commit()
|
|
domain = [
|
|
("res_model", "=", "voip.call"),
|
|
("res_id", "=", call.id),
|
|
("mimetype", "=", "audio/ogg"),
|
|
]
|
|
recordings = self.env["ir.attachment"].search(domain, order="create_date desc")
|
|
|
|
if not recordings:
|
|
call.transcription_status = "no_audio"
|
|
return
|
|
|
|
if len(recordings) > 1:
|
|
_logger.warning(
|
|
"Call %s has multiple recordings; processing only the newest one (%s).", call.id, recordings[0].id
|
|
)
|
|
|
|
recording = recordings[0]
|
|
|
|
try:
|
|
text = LLMApiService(self.env).get_transcription(recording.raw, "audio/ogg")
|
|
except (RequestException, JSONDecodeError, UserError):
|
|
_logger.exception("Call %s: transcription failed", call.id)
|
|
call.transcription_status = "error"
|
|
return
|
|
|
|
call.transcript = (call.transcript or "") + text
|
|
call.transcription_status = "done"
|
|
|
|
# Generate one-liner summary
|
|
try:
|
|
ai_agent = self.env.ref('voip_ai.voip_call_summary_agent', raise_if_not_found=False)
|
|
if call.transcript:
|
|
summary_response = ai_agent.get_direct_response(prompt=call.transcript)
|
|
if summary_response:
|
|
call.summary = summary_response[0]
|
|
except (RequestException, JSONDecodeError, UserError):
|
|
_logger.exception("Call %s: one-liner summary generation failed", call.id)
|