Enhance voice interaction and transcript handling in the assistant

- Add a new Docker configuration for the UI in launch.json to facilitate development.
- Refactor pipeline.py to integrate a TranscriptProcessor for managing user and assistant transcripts, including event handlers for real-time updates and message handling.
- Update useVoicePreview.ts to establish a data channel for sending and receiving text messages, improving interaction flow.
- Modify AssistantPage.tsx to support displaying chat messages and sending user input, enhancing the user experience during voice interactions.
- Revise DebugTranscriptPanel to dynamically render chat messages with timestamps, improving the visual representation of conversation history.
This commit is contained in:
Xin Wang
2026-06-10 15:11:34 +08:00
parent b711350c0c
commit 2c2af1f2cd
4 changed files with 223 additions and 28 deletions

View File

@@ -10,11 +10,19 @@ from loguru import logger
from models import AssistantConfig
from services.pipecat.service_factory import create_services
from pipecat.frames.frames import EndFrame, TTSSpeakFrame
from pipecat.frames.frames import (
EndFrame,
InterruptionTaskFrame,
TranscriptionFrame,
TransportMessageUrgentFrame,
TTSSpeakFrame,
)
from pipecat.pipeline.pipeline import Pipeline
from pipecat.pipeline.runner import PipelineRunner
from pipecat.pipeline.task import PipelineParams, PipelineTask
from pipecat.processors.aggregators.openai_llm_context import OpenAILLMContext
from pipecat.processors.transcript_processor import TranscriptProcessor
from pipecat.utils.time import time_now_iso8601
async def run_pipeline(transport, cfg: AssistantConfig) -> None:
@@ -32,14 +40,20 @@ async def run_pipeline(transport, cfg: AssistantConfig) -> None:
context = OpenAILLMContext(messages=[{"role": "system", "content": cfg.prompt}])
context_aggregator = llm.create_context_aggregator(context)
# 转写收集:user 侧收 ASR 最终转写,assistant 侧聚合 TTS 实际播报的文本,
# 统一通过 data channel 推给前端聊天记录面板。
transcript = TranscriptProcessor()
pipeline = Pipeline(
[
transport.input(),
stt,
transcript.user(),
context_aggregator.user(),
llm,
tts,
transport.output(),
transcript.assistant(),
context_aggregator.assistant(),
]
)
@@ -52,6 +66,39 @@ async def run_pipeline(transport, cfg: AssistantConfig) -> None:
),
)
@transcript.event_handler("on_transcript_update")
async def on_transcript_update(_processor, frame):
# 每条最终转写(用户/助手)推给前端,前端据此渲染聊天记录
for msg in frame.messages:
await task.queue_frame(
TransportMessageUrgentFrame(
message={
"type": "transcript",
"role": msg.role,
"content": msg.content,
"timestamp": msg.timestamp,
}
)
)
@transport.event_handler("on_app_message")
async def on_app_message(_transport, message, _sender):
# 前端文字输入:先打断当前播报,再当作一条用户最终转写注入,
# 走与语音完全相同的 转写→上下文→LLM→TTS 链路
if not isinstance(message, dict) or message.get("type") != "user-text":
return
text = str(message.get("text") or "").strip()
if not text:
return
await task.queue_frames(
[
InterruptionTaskFrame(),
TranscriptionFrame(
text=text, user_id="debug", timestamp=time_now_iso8601()
),
]
)
@transport.event_handler("on_client_connected")
async def on_client_connected(_transport, _client):
if cfg.greeting: