Compare commits

...

1 Commits

Author SHA1 Message Date
Martin Guitteny ddb8387c03 ️(summary) change summary pipeline for improvements
Add number of subject approximation based on transcript
length.
Add TLDR generation with already generated summary
Change generation of parts in one prompt
2025-10-13 18:38:37 +02:00
2 changed files with 104 additions and 26 deletions
+30 -10
View File
@@ -8,6 +8,7 @@ import tempfile
import time
from pathlib import Path
from typing import Any, Mapping, Optional
import math
import openai
import sentry_sdk
@@ -103,6 +104,12 @@ def create_retry_session():
session.mount("https://", HTTPAdapter(max_retries=retries))
return session
def add_line_numbers(transcript: str):
"""Add line numbers to a text file."""
lines = transcript.splitlines()
lines = [line for line in lines if line.strip()]
numbered_lines = [f"{i + 1}: {line}" for i, line in enumerate(lines)]
return "\n".join(numbered_lines)
class LLMException(Exception):
"""LLM call failed."""
@@ -386,28 +393,36 @@ def summarize_transcription(self, transcript: str, email: str, sub: str, title:
llm_service = LLMService()
tldr = llm_service.call(PROMPT_SYSTEM_TLDR, transcript)
token_estimate = len(transcript) // 3.6
t = round(0.5 + 2.3 * math.log1p((token_estimate / 3800) ** 2))
nb_parts = max(1, t)
logger.info("TLDR generated")
transcript = add_line_numbers(transcript)
logger.info("Transcription with line numbers: \n%s", transcript)
parts = llm_service.call(
PROMPT_SYSTEM_PLAN, transcript, response_format=FORMAT_PLAN
PROMPT_SYSTEM_PLAN.format(nb_parts_min=nb_parts-2, nb_parts_max=nb_parts+2), "Transcript : \n" + transcript, response_format=FORMAT_PLAN
)
logger.info("Plan generated")
res = json.loads(parts)
parts = res.get("titles", [])
parts = res.get("parts", [])
logger.info("Parts to summarize: %s", parts)
parts_summarized = []
parts_titles = ""
for part in parts:
prompt_user_part = PROMPT_USER_PART.format(part=part, transcript=transcript)
logger.info("Summarizing part: %s", part)
parts_summarized.append(llm_service.call(PROMPT_SYSTEM_PART, prompt_user_part))
parts_titles += f"- {part['title']}, lignes {part['plages_lignes']}\n"
raw_summary = llm_service.call(
PROMPT_SYSTEM_PART,
f"Plan:\n{parts_titles}\n\nTranscript:\n{transcript}",
)
logger.info("Parts summarized")
raw_summary = "\n\n".join(parts_summarized)
next_steps = llm_service.call(
PROMPT_SYSTEM_NEXT_STEP, transcript, response_format=FORMAT_NEXT_STEPS
)
@@ -419,7 +434,12 @@ def summarize_transcription(self, transcript: str, email: str, sub: str, title:
cleaned_summary = llm_service.call(PROMPT_SYSTEM_CLEANING, raw_summary)
logger.info("Summary cleaned")
summary = tldr + "\n\n" + cleaned_summary + "\n\n" + next_steps
tldr = llm_service.call(
PROMPT_SYSTEM_TLDR,
"transcript :\n" + transcript + "\n\nsummary :\n" + cleaned_summary,
)
summary = tldr + "\n\n" + raw_summary + "\n\n" + next_steps
data = {
"title": settings.summary_title_template.format(
+74 -16
View File
@@ -4,14 +4,50 @@ PROMPT_SYSTEM_TLDR = """Tu es un agent dont le rôle est de créer un TL;DR (ré
### Résumé TL;DR
[Résumé concis et structuré]"""
PROMPT_SYSTEM_PLAN = """Ta tâche est de diviser le contenu du transcript en sujets concrets correspondant aux grands axes discutés durant la réunion. Ne crée pas de catégories génériques. Les titres doivent être courts, précis et représentatifs des échanges. Veille à ce que chaque sujet soit distinct et quaucun thème ne soit répété. Tu te limiteras à 5 ou 6 sujets maximum.
L'introduction, ordre du jour, conclusion, etc. seront rajoutés a posteriori. Si il n'y a pas de sujets clairs, réponds "Général".
"""
PROMPT_SYSTEM_PLAN = """Ta tâche consiste à identifier les sujets abordés dans un transcript, cest-à-dire les thèmes précis et concrets correspondant aux grands axes réellement discutés durant la réunion.
- Ninclus pas de catégories génériques.
- Les titres doivent être courts, précis et représentatifs des échanges.
- Chaque sujet doit être distinct, sans répétition de thèmes.
- Tu fera entre {nb_parts_min} et {nb_parts_max} sujets.
Pour chaque sujet identifié :
- Donne le titre du sujet
- Indique la ou les plages de lignes (numérotées) du transcript correspondant à ce sujet (une ou plusieurs par sujet, si nécessaire : [[début, fin], ...]).
Lintroduction, lordre du jour, la conclusion, etc., seront ajoutés ultérieurement.
Si aucun sujet clair nest repéré, réponds exactement : "Général"."""
PROMPT_SYSTEM_PART = """Tu es un agent dont le rôle est de créer une partie du résumé d'un compte rendu de réunion. Tu utiliseras un style synthétique, administratif, à la troisième personne, sans affect. Tu recevras en entrée le transcript, et le titre du sujet correspondant. Ta tâche est de rédiger un résumé concis de cette partie et uniquement cette partie, en te concentrant uniquement sur les informations essentielles et pertinentes. Le résumé de chaque partie doit tenir en 4 à 6 phrases maximum, sans entrer dans les détails mineurs. Tu répondras dans le format suivant :
### Titre du sujet [Traduire ce titre selon la langue du transcript]
[Résumé concis et structuré de la partie du transcript]
"""
PROMPT_SYSTEM_PART = """
Tu es un agent dont le rôle est de rédiger le résumé complet dun compte rendu de réunion.
Tu utiliseras un style synthétique, administratif, à la troisième personne, sans affect.
En entrée, tu recevras :
- Lintégralité du transcript de la réunion,
- Un plan indiquant pour chaque sujet : son titre et la plage de lignes correspondante.
- Les notes prises par un utilisateur durant la réunion contenant des points important à aborder dans le transcript.
Consignes :
- Générer un résumé pour chacune des parties définies dans le plan.
- Pour chaque partie :
- Résumer les lignes indiquées et en lien avec le sujet.,
- Utiliser exclusivement des bullet points clairs et concis,
- Ne pas dépasser 4 ou 5 bullet points par partie,
- Se limiter aux informations essentielles et pertinentes,
- Éviter tout détail secondaire ou interprétation.
- mettre en avant les points écrits dans les notes de l'utilisateur.
- mettre en gras les noms propres (personnes, entreprises, produits, etc.)
Format de sortie attendu : un enchaînement de résumés, un par sujet, par exemple :
### [Titre du sujet 1]
- [Point essentiel 1]
- [Point essentiel 2]
- [Point essentiel 3]
### [Titre du sujet 2]
- [Point essentiel 1]
- [Point essentiel 2]
(...)
"""
PROMPT_USER_PART = """Titre de la partie à résumer : {part}
Transcript complet :
@@ -57,15 +93,37 @@ FORMAT_NEXT_STEPS = {
}
FORMAT_PLAN = {
"type": "json_schema",
"json_schema": {
"name": "Titles",
"schema": {
"type": "json_schema",
"json_schema": {
"name": "PlanWithLineRanges",
"strict": True,
"schema": {
"type": "object",
"additionalProperties": False,
"required": ["parts"],
"properties": {
"parts": {
"type": "array",
"items": {
"type": "object",
"properties": {"titles": {"type": "array", "items": {"type": "string"}}},
"required": ["titles"],
"additionalProperties": False,
},
"strict": True,
},
"required": ["title", "plages_lignes"],
"properties": {
"title": { "type": "string" },
"plages_lignes": {
"type": "array",
"minItems": 1,
"items": {
"type": "array",
"items": { "type": "integer", "minimum": 1 },
"minItems": 2,
"maxItems": 2
}
}
}
}
}
}
}
}
}