Refactor pipeline and assistant page components for improved structure and performance
- Remove unused imports and classes from pipeline.py to streamline the codebase. - Consolidate dynamic variable handling and workflow management in AssistantPage, enhancing clarity and maintainability. - Update WorkflowEditor to utilize a more modular approach, improving the overall architecture and reducing complexity. - Enhance the import structure across components for better organization and readability.
This commit is contained in:
131
backend/services/pipecat/workflow_services.py
Normal file
131
backend/services/pipecat/workflow_services.py
Normal file
@@ -0,0 +1,131 @@
|
||||
"""Workflow model resource loading and runtime service switching."""
|
||||
|
||||
from models import AssistantConfig
|
||||
from services.pipecat.service_factory import (
|
||||
config_with_resource,
|
||||
create_llm,
|
||||
create_stt,
|
||||
create_tts,
|
||||
)
|
||||
|
||||
from pipecat.frames.frames import (
|
||||
ManuallySwitchServiceFrame,
|
||||
OutputTransportMessageUrgentFrame,
|
||||
)
|
||||
from pipecat.pipeline.llm_switcher import LLMSwitcher
|
||||
from pipecat.pipeline.service_switcher import ServiceSwitcher
|
||||
from pipecat.processors.frame_processor import FrameProcessor
|
||||
|
||||
|
||||
def build_workflow_voice_switcher(
|
||||
cfg: AssistantConfig, capability: str, base_service: FrameProcessor
|
||||
):
|
||||
"""Build one switcher and an ID lookup for every referenced voice resource."""
|
||||
create = create_stt if capability == "ASR" else create_tts
|
||||
settings = cfg.graph.get("settings") or {}
|
||||
default_key = (
|
||||
"defaultAsrResourceId" if capability == "ASR" else "defaultTtsResourceId"
|
||||
)
|
||||
default_id = str(settings.get(default_key) or "")
|
||||
services_by_id = {}
|
||||
for resource_id, resource in cfg.workflow_model_resources.items():
|
||||
if resource.capability != capability:
|
||||
continue
|
||||
services_by_id[resource_id] = (
|
||||
base_service
|
||||
if resource_id == default_id
|
||||
else create(config_with_resource(cfg, resource))
|
||||
)
|
||||
primary = services_by_id.get(default_id, base_service)
|
||||
services = [primary]
|
||||
services.extend(
|
||||
service for service in services_by_id.values() if service is not primary
|
||||
)
|
||||
if base_service is not primary:
|
||||
services.append(base_service)
|
||||
return ServiceSwitcher(services=services), services_by_id, primary
|
||||
|
||||
|
||||
def build_workflow_llm_switcher(cfg: AssistantConfig, base_service):
|
||||
"""Build an LLM switcher for the global model and Agent overrides."""
|
||||
settings = cfg.graph.get("settings") or {}
|
||||
default_id = str(settings.get("defaultLlmResourceId") or "")
|
||||
services_by_id = {}
|
||||
for resource_id, resource in cfg.workflow_model_resources.items():
|
||||
if resource.capability != "LLM":
|
||||
continue
|
||||
services_by_id[resource_id] = (
|
||||
base_service
|
||||
if resource_id == default_id
|
||||
else create_llm(config_with_resource(cfg, resource))
|
||||
)
|
||||
primary = services_by_id.get(default_id, base_service)
|
||||
services = [primary]
|
||||
services.extend(
|
||||
service for service in services_by_id.values() if service is not primary
|
||||
)
|
||||
if base_service is not primary:
|
||||
services.append(base_service)
|
||||
return LLMSwitcher(llms=services), services_by_id, primary
|
||||
|
||||
|
||||
|
||||
|
||||
class WorkflowServiceController:
|
||||
"""Switch one Workflow stage's model resources without leaking state."""
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
*,
|
||||
worker,
|
||||
llm_services: dict[str, FrameProcessor],
|
||||
voice_services: dict[str, dict[str, FrameProcessor]],
|
||||
current_services: dict[str, FrameProcessor],
|
||||
) -> None:
|
||||
self._worker = worker
|
||||
self._services = {
|
||||
"llm": llm_services,
|
||||
"asr": voice_services["asr"],
|
||||
"tts": voice_services["tts"],
|
||||
}
|
||||
self._current = dict(current_services)
|
||||
self._defaults = dict(current_services)
|
||||
|
||||
async def switch(
|
||||
self,
|
||||
llm_resource_id: str | None,
|
||||
asr_resource_id: str | None,
|
||||
tts_resource_id: str | None,
|
||||
) -> None:
|
||||
requested = (
|
||||
("llm", llm_resource_id),
|
||||
("asr", asr_resource_id),
|
||||
("tts", tts_resource_id),
|
||||
)
|
||||
for kind, resource_id in requested:
|
||||
target = (
|
||||
self._services[kind].get(resource_id)
|
||||
if resource_id
|
||||
else self._defaults[kind]
|
||||
)
|
||||
if target is None:
|
||||
raise ValueError(
|
||||
f"Workflow {kind.upper()} 资源未加载:{resource_id}"
|
||||
)
|
||||
if self._current[kind] is target:
|
||||
continue
|
||||
|
||||
await self._worker.queue_frame(
|
||||
ManuallySwitchServiceFrame(service=target)
|
||||
)
|
||||
self._current[kind] = target
|
||||
await self._worker.queue_frame(
|
||||
OutputTransportMessageUrgentFrame(
|
||||
message={
|
||||
"type": "service-switched",
|
||||
"capability": kind.upper(),
|
||||
"resourceId": resource_id,
|
||||
}
|
||||
)
|
||||
)
|
||||
|
||||
Reference in New Issue
Block a user