mirror of
https://github.com/Monadical-SAS/reflector.git
synced 2025-12-21 20:59:05 +00:00
feat: add background information field to room model
- Add background_information field to Room database table and model - Create database migration for the new field - Update API schemas (CreateRoom, UpdateRoom) to handle background_information - Integrate room context into AI summarization prompts - Add background_information field to frontend room form - Update TypeScript types from regenerated OpenAPI spec The background information will be used to provide context for AI-generated summaries, helping create more appropriate and relevant meeting summaries. 🤖 Generated with [opencode](https://opencode.ai) Co-Authored-By: opencode <noreply@opencode.ai>
This commit is contained in:
@@ -0,0 +1,26 @@
|
||||
"""add_room_background_information
|
||||
|
||||
Revision ID: 082fa608201c
|
||||
Revises: b7df9609542c
|
||||
Create Date: 2025-07-29 01:41:37.912195
|
||||
|
||||
"""
|
||||
from typing import Sequence, Union
|
||||
|
||||
from alembic import op
|
||||
import sqlalchemy as sa
|
||||
|
||||
|
||||
# revision identifiers, used by Alembic.
|
||||
revision: str = '082fa608201c'
|
||||
down_revision: Union[str, None] = 'b7df9609542c'
|
||||
branch_labels: Union[str, Sequence[str], None] = None
|
||||
depends_on: Union[str, Sequence[str], None] = None
|
||||
|
||||
|
||||
def upgrade() -> None:
|
||||
op.add_column('room', sa.Column('background_information', sa.Text(), nullable=True))
|
||||
|
||||
|
||||
def downgrade() -> None:
|
||||
op.drop_column('room', 'background_information')
|
||||
@@ -39,6 +39,7 @@ rooms = sqlalchemy.Table(
|
||||
sqlalchemy.Column(
|
||||
"is_shared", sqlalchemy.Boolean, nullable=False, server_default=false()
|
||||
),
|
||||
sqlalchemy.Column("background_information", sqlalchemy.Text),
|
||||
sqlalchemy.Index("idx_room_is_shared", "is_shared"),
|
||||
)
|
||||
|
||||
@@ -58,6 +59,7 @@ class Room(BaseModel):
|
||||
"none", "prompt", "automatic", "automatic-2nd-participant"
|
||||
] = "automatic-2nd-participant"
|
||||
is_shared: bool = False
|
||||
background_information: str = ""
|
||||
|
||||
|
||||
class RoomController:
|
||||
@@ -106,6 +108,7 @@ class RoomController:
|
||||
recording_type: str,
|
||||
recording_trigger: str,
|
||||
is_shared: bool,
|
||||
background_information: str = "",
|
||||
):
|
||||
"""
|
||||
Add a new room
|
||||
@@ -121,6 +124,7 @@ class RoomController:
|
||||
recording_type=recording_type,
|
||||
recording_trigger=recording_trigger,
|
||||
is_shared=is_shared,
|
||||
background_information=background_information,
|
||||
)
|
||||
query = rooms.insert().values(**room.model_dump())
|
||||
try:
|
||||
|
||||
@@ -454,15 +454,47 @@ class PipelineMainFinalSummaries(PipelineMainFromTopics):
|
||||
Generate summaries from the topics
|
||||
"""
|
||||
|
||||
async def get_room(self):
|
||||
"""Get room information for the transcript"""
|
||||
if not self._transcript.room_id:
|
||||
return None
|
||||
return await rooms_controller.get_by_id(self._transcript.room_id)
|
||||
|
||||
def get_processors(self) -> list:
|
||||
return [
|
||||
TranscriptFinalSummaryProcessor.as_threaded(
|
||||
transcript=self._transcript,
|
||||
room=getattr(self, '_room', None),
|
||||
callback=self.on_long_summary,
|
||||
on_short_summary=self.on_short_summary,
|
||||
),
|
||||
]
|
||||
|
||||
async def create(self) -> Pipeline:
|
||||
self.prepare()
|
||||
|
||||
# get transcript
|
||||
self._transcript = transcript = await self.get_transcript()
|
||||
|
||||
# get room information
|
||||
self._room = await self.get_room()
|
||||
|
||||
# create pipeline
|
||||
processors = self.get_processors()
|
||||
pipeline = Pipeline(*processors)
|
||||
pipeline.options = self
|
||||
pipeline.logger.bind(transcript_id=transcript.id)
|
||||
pipeline.logger.info(f"{self.__class__.__name__} pipeline created")
|
||||
|
||||
# push topics
|
||||
topics = self.get_transcript_topics(transcript)
|
||||
for topic in topics:
|
||||
await self.push(topic)
|
||||
|
||||
await self.flush()
|
||||
|
||||
return pipeline
|
||||
|
||||
|
||||
class PipelineMainWaveform(PipelineMainFromTopics):
|
||||
"""
|
||||
|
||||
@@ -135,7 +135,7 @@ class Messages:
|
||||
|
||||
|
||||
class SummaryBuilder:
|
||||
def __init__(self, llm, filename: str | None = None, logger=None):
|
||||
def __init__(self, llm, filename: str | None = None, logger=None, room=None):
|
||||
self.transcript: str | None = None
|
||||
self.recap: str | None = None
|
||||
self.summaries: list[dict] = []
|
||||
@@ -147,6 +147,7 @@ class SummaryBuilder:
|
||||
self.llm_instance: LLM = llm
|
||||
self.model_name: str = llm.model_name
|
||||
self.logger = logger or structlog.get_logger()
|
||||
self.room = room
|
||||
self.m = Messages(model_name=self.model_name, logger=self.logger)
|
||||
if filename:
|
||||
self.read_transcript_from_file(filename)
|
||||
@@ -465,26 +466,31 @@ class SummaryBuilder:
|
||||
self.logger.debug("--- extract main subjects")
|
||||
|
||||
m = Messages(model_name=self.model_name, logger=self.logger)
|
||||
m.add_system(
|
||||
(
|
||||
"You are an advanced transcription summarization assistant."
|
||||
"Your task is to summarize discussions by focusing only on the main ideas contributed by participants."
|
||||
# Prevent generating another transcription
|
||||
"Exclude direct quotes and unnecessary details."
|
||||
# Do not mention others participants just because they didn't contributed
|
||||
"Only include participant names if they actively contribute to the subject."
|
||||
# Prevent generation of summary with "no others participants contributed" etc
|
||||
"Keep summaries concise and focused on main subjects without adding conclusions such as 'no other participant contributed'. "
|
||||
# Avoid: In the discussion, they talked about...
|
||||
"Do not include contextual preface. "
|
||||
# Prevention to have too long summary
|
||||
"Summary should fit in a single paragraph. "
|
||||
# Using other pronouns that the participants or the group
|
||||
'Mention the participants or the group using "they".'
|
||||
# Avoid finishing the summary with "No conclusions were added by the summarizer"
|
||||
"Do not mention conclusion if there is no conclusion"
|
||||
)
|
||||
|
||||
system_prompt = (
|
||||
"You are an advanced transcription summarization assistant."
|
||||
"Your task is to summarize discussions by focusing only on the main ideas contributed by participants."
|
||||
# Prevent generating another transcription
|
||||
"Exclude direct quotes and unnecessary details."
|
||||
# Do not mention others participants just because they didn't contributed
|
||||
"Only include participant names if they actively contribute to the subject."
|
||||
# Prevent generation of summary with "no others participants contributed" etc
|
||||
"Keep summaries concise and focused on main subjects without adding conclusions such as 'no other participant contributed'. "
|
||||
# Avoid: In the discussion, they talked about...
|
||||
"Do not include contextual preface. "
|
||||
# Prevention to have too long summary
|
||||
"Summary should fit in a single paragraph. "
|
||||
# Using other pronouns that the participants or the group
|
||||
'Mention the participants or the group using "they".'
|
||||
# Avoid finishing the summary with "No conclusions were added by the summarizer"
|
||||
"Do not mention conclusion if there is no conclusion"
|
||||
)
|
||||
|
||||
# Add room context if available
|
||||
if self.room and self.room.background_information:
|
||||
system_prompt += f"\n\nContext about this meeting room: {self.room.background_information}"
|
||||
|
||||
m.add_system(system_prompt)
|
||||
m.add_user(
|
||||
f"# Transcript\n\n{self.transcript}\n\n"
|
||||
+ (
|
||||
|
||||
@@ -12,9 +12,10 @@ class TranscriptFinalSummaryProcessor(Processor):
|
||||
INPUT_TYPE = TitleSummary
|
||||
OUTPUT_TYPE = FinalLongSummary
|
||||
|
||||
def __init__(self, transcript=None, **kwargs):
|
||||
def __init__(self, transcript=None, room=None, **kwargs):
|
||||
super().__init__(**kwargs)
|
||||
self.transcript = transcript
|
||||
self.room = room
|
||||
self.chunks: list[TitleSummary] = []
|
||||
self.llm = LLM.get_instance(model_name="NousResearch/Hermes-3-Llama-3.1-8B")
|
||||
self.builder = None
|
||||
@@ -23,7 +24,7 @@ class TranscriptFinalSummaryProcessor(Processor):
|
||||
self.chunks.append(data)
|
||||
|
||||
async def get_summary_builder(self, text) -> SummaryBuilder:
|
||||
builder = SummaryBuilder(self.llm)
|
||||
builder = SummaryBuilder(self.llm, room=self.room)
|
||||
builder.set_transcript(text)
|
||||
await builder.identify_participants()
|
||||
await builder.generate_summary()
|
||||
|
||||
@@ -33,6 +33,7 @@ class Room(BaseModel):
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
is_shared: bool
|
||||
background_information: str
|
||||
|
||||
|
||||
class Meeting(BaseModel):
|
||||
@@ -55,6 +56,7 @@ class CreateRoom(BaseModel):
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
is_shared: bool
|
||||
background_information: str = ""
|
||||
|
||||
|
||||
class UpdateRoom(BaseModel):
|
||||
@@ -67,6 +69,7 @@ class UpdateRoom(BaseModel):
|
||||
recording_type: str
|
||||
recording_trigger: str
|
||||
is_shared: bool
|
||||
background_information: str = ""
|
||||
|
||||
|
||||
class DeletionStatus(BaseModel):
|
||||
@@ -108,6 +111,7 @@ async def rooms_create(
|
||||
recording_type=room.recording_type,
|
||||
recording_trigger=room.recording_trigger,
|
||||
is_shared=room.is_shared,
|
||||
background_information=room.background_information,
|
||||
)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user