Update LLM configuration to support FastGPT integration. Modify requirements to include fastgpt-python-sdk, enhance greeting messages, and adjust LLM service creation to handle app_id. Implement welcome text fetching for FastGPT and improve context handling in the pipeline based on LLM provider. Update related configurations and properties for better integration.
This commit is contained in:
@@ -13,6 +13,7 @@ from pipecat.frames.frames import (
|
||||
CancelFrame,
|
||||
EndFrame,
|
||||
Frame,
|
||||
InterruptionFrame,
|
||||
LLMContextFrame,
|
||||
LLMFullResponseEndFrame,
|
||||
LLMFullResponseStartFrame,
|
||||
@@ -134,6 +135,24 @@ class FastGPTLLMSettings(LLMSettings):
|
||||
detail: bool = False
|
||||
|
||||
|
||||
def _default_fastgpt_settings(*, model: str = "fastgpt") -> FastGPTLLMSettings:
|
||||
return FastGPTLLMSettings(
|
||||
model=model,
|
||||
system_instruction=None,
|
||||
temperature=None,
|
||||
max_tokens=None,
|
||||
top_p=None,
|
||||
top_k=None,
|
||||
frequency_penalty=None,
|
||||
presence_penalty=None,
|
||||
seed=None,
|
||||
filter_incomplete_user_turns=False,
|
||||
user_turn_completion_config=None,
|
||||
variables={},
|
||||
detail=False,
|
||||
)
|
||||
|
||||
|
||||
class FastGPTLLMService(LLMService):
|
||||
"""FastGPT LLM service using chatId server-side memory and workflow variables."""
|
||||
|
||||
@@ -145,18 +164,20 @@ class FastGPTLLMService(LLMService):
|
||||
api_key: str,
|
||||
base_url: str,
|
||||
chat_id: str | None = None,
|
||||
app_id: str | None = None,
|
||||
send_system_prompt: bool = False,
|
||||
greeting_prompt: str | None = None,
|
||||
timeout: float = 60.0,
|
||||
settings: FastGPTLLMSettings | None = None,
|
||||
**kwargs,
|
||||
) -> None:
|
||||
default_settings = self.Settings(model="fastgpt")
|
||||
default_settings = _default_fastgpt_settings()
|
||||
if settings is not None:
|
||||
default_settings.apply_update(settings)
|
||||
super().__init__(settings=default_settings, **kwargs)
|
||||
|
||||
self._chat_id = chat_id or f"voice_{uuid.uuid4().hex[:16]}"
|
||||
self._app_id = (app_id or "").strip()
|
||||
self._send_system_prompt = send_system_prompt
|
||||
self._greeting_prompt = (greeting_prompt or "你好").strip() or "你好"
|
||||
self._client = AsyncChatClient(
|
||||
@@ -166,6 +187,10 @@ class FastGPTLLMService(LLMService):
|
||||
)
|
||||
self._active_response = None
|
||||
|
||||
@property
|
||||
def app_id(self) -> str:
|
||||
return self._app_id
|
||||
|
||||
@property
|
||||
def chat_id(self) -> str:
|
||||
return self._chat_id
|
||||
@@ -184,6 +209,63 @@ class FastGPTLLMService(LLMService):
|
||||
await self._close_active_response()
|
||||
await super().cancel(frame)
|
||||
|
||||
async def _handle_interruptions(self, _: InterruptionFrame) -> None:
|
||||
await self._close_active_response()
|
||||
await super()._handle_interruptions(_)
|
||||
|
||||
@staticmethod
|
||||
def _welcome_text_from_init_payload(payload: Any) -> str:
|
||||
if not isinstance(payload, dict):
|
||||
return ""
|
||||
|
||||
for container in (payload.get("app"), payload.get("data"), payload):
|
||||
if not isinstance(container, dict):
|
||||
continue
|
||||
nested_app = container.get("app")
|
||||
if isinstance(nested_app, dict):
|
||||
text = FastGPTLLMService._welcome_text_from_app(nested_app)
|
||||
if text:
|
||||
return text
|
||||
text = FastGPTLLMService._welcome_text_from_app(container)
|
||||
if text:
|
||||
return text
|
||||
return ""
|
||||
|
||||
@staticmethod
|
||||
def _welcome_text_from_app(app_payload: dict[str, Any]) -> str:
|
||||
chat_config = (
|
||||
app_payload.get("chatConfig")
|
||||
if isinstance(app_payload.get("chatConfig"), dict)
|
||||
else {}
|
||||
)
|
||||
return _first_nonempty_text(
|
||||
chat_config.get("welcomeText"),
|
||||
app_payload.get("welcomeText"),
|
||||
)
|
||||
|
||||
async def fetch_welcome_text(self) -> str | None:
|
||||
"""Return FastGPT app welcome text from chat init when ``app_id`` is configured."""
|
||||
if not self._app_id:
|
||||
return None
|
||||
|
||||
try:
|
||||
response = await self._client.get_chat_init(
|
||||
appId=self._app_id,
|
||||
chatId=self._chat_id,
|
||||
)
|
||||
response.raise_for_status()
|
||||
text = self._welcome_text_from_init_payload(response.json())
|
||||
if text:
|
||||
logger.info(f"FastGPT welcomeText loaded for appId={self._app_id}")
|
||||
return text or None
|
||||
except FastGPTError as exc:
|
||||
logger.warning(f"FastGPT chat init failed: {exc}")
|
||||
except httpx.HTTPError as exc:
|
||||
logger.warning(f"FastGPT chat init HTTP error: {exc}")
|
||||
except Exception as exc:
|
||||
logger.warning(f"FastGPT chat init error: {exc}")
|
||||
return None
|
||||
|
||||
async def _close_active_response(self) -> None:
|
||||
response = self._active_response
|
||||
self._active_response = None
|
||||
@@ -217,6 +299,12 @@ class FastGPTLLMService(LLMService):
|
||||
messages = self._build_fastgpt_messages(context)
|
||||
variables = self._settings.variables or None
|
||||
|
||||
logger.info(
|
||||
"FastGPT chat completion "
|
||||
f"chatId={self._chat_id} appId={self._app_id or '-'} "
|
||||
f"variables={sorted((variables or {}).keys())} messages={messages!r}"
|
||||
)
|
||||
|
||||
await self.start_ttfb_metrics()
|
||||
|
||||
try:
|
||||
|
||||
Reference in New Issue
Block a user