Use FastGPT app opener for greetings
This commit is contained in:
@@ -147,7 +147,6 @@ class LLMConfig:
|
||||
variables: dict[str, str] = field(default_factory=dict)
|
||||
detail: bool = False
|
||||
timeout_sec: float = 60.0
|
||||
send_system_prompt: bool = False
|
||||
|
||||
@property
|
||||
def is_fastgpt(self) -> bool:
|
||||
@@ -160,7 +159,7 @@ class LLMConfig:
|
||||
@property
|
||||
def uses_local_context_history(self) -> bool:
|
||||
"""Whether the pipeline should seed and maintain local LLM context history."""
|
||||
return not self.is_fastgpt or self.send_system_prompt
|
||||
return not self.is_fastgpt
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@@ -233,9 +232,11 @@ def config_from_dict(data: dict) -> EngineConfig:
|
||||
agent = _dict(data.get("agent"))
|
||||
if agent.get("greeting") == "":
|
||||
agent["greeting"] = None
|
||||
if agent.get("greeting_mode") not in (None, "generated", "fixed", "off"):
|
||||
raise ValueError("agent.greeting_mode must be one of: generated, fixed, off")
|
||||
response_state = ResponseStateConfig(**_dict(agent.pop("response_state")))
|
||||
if agent.get("greeting_mode") not in (None, "generated", "fixed", "off", "fastgpt_opener"):
|
||||
raise ValueError(
|
||||
"agent.greeting_mode must be one of: generated, fixed, off, fastgpt_opener"
|
||||
)
|
||||
response_state = ResponseStateConfig(**_dict(agent.pop("response_state", None)))
|
||||
if response_state.max_prefix_chars < 1:
|
||||
raise ValueError("agent.response_state.max_prefix_chars must be greater than 0")
|
||||
if not response_state.tag:
|
||||
@@ -255,6 +256,10 @@ def config_from_dict(data: dict) -> EngineConfig:
|
||||
llm["app_id"] = None
|
||||
if not isinstance(llm.get("variables"), dict):
|
||||
llm["variables"] = {}
|
||||
if agent.get("greeting_mode") == "fastgpt_opener" and llm["provider"] != "fastgpt":
|
||||
raise ValueError(
|
||||
"agent.greeting_mode='fastgpt_opener' requires services.llm.provider='fastgpt'"
|
||||
)
|
||||
|
||||
turn = _dict(data.get("turn"))
|
||||
vad = _dict(turn.get("vad"))
|
||||
|
||||
@@ -170,7 +170,6 @@ class FastGPTLLMService(LLMService):
|
||||
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,
|
||||
@@ -183,7 +182,6 @@ class FastGPTLLMService(LLMService):
|
||||
|
||||
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(
|
||||
api_key=api_key,
|
||||
@@ -246,6 +244,8 @@ class FastGPTLLMService(LLMService):
|
||||
return _first_nonempty_text(
|
||||
chat_config.get("welcomeText"),
|
||||
app_payload.get("welcomeText"),
|
||||
app_payload.get("opener"),
|
||||
app_payload.get("intro"),
|
||||
)
|
||||
|
||||
async def fetch_welcome_text(self) -> str | None:
|
||||
@@ -261,7 +261,7 @@ class FastGPTLLMService(LLMService):
|
||||
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}")
|
||||
logger.info(f"FastGPT app opener loaded for appId={self._app_id}")
|
||||
return text or None
|
||||
except FastGPTError as exc:
|
||||
logger.warning(f"FastGPT chat init failed: {exc}")
|
||||
@@ -279,26 +279,15 @@ class FastGPTLLMService(LLMService):
|
||||
|
||||
def _build_fastgpt_messages(self, context: LLMContext) -> list[dict[str, str]]:
|
||||
raw_messages = context.get_messages()
|
||||
messages: list[dict[str, str]] = []
|
||||
|
||||
if self._send_system_prompt:
|
||||
for message in raw_messages:
|
||||
if not isinstance(message, dict) or message.get("role") != "system":
|
||||
continue
|
||||
text = _message_text(message)
|
||||
if text:
|
||||
messages.append({"role": "system", "content": text})
|
||||
|
||||
for message in reversed(raw_messages):
|
||||
if not isinstance(message, dict) or message.get("role") != "user":
|
||||
continue
|
||||
text = _message_text(message)
|
||||
if text:
|
||||
messages.append({"role": "user", "content": text})
|
||||
return messages
|
||||
return [{"role": "user", "content": text}]
|
||||
|
||||
messages.append({"role": "user", "content": self._greeting_prompt})
|
||||
return messages
|
||||
return [{"role": "user", "content": self._greeting_prompt}]
|
||||
|
||||
async def _process_context(self, context: LLMContext) -> None:
|
||||
messages = self._build_fastgpt_messages(context)
|
||||
|
||||
@@ -196,15 +196,17 @@ async def run_pipeline_with_serializer(
|
||||
logger.info(f"{client_label} websocket client connected")
|
||||
if config.agent.greeting_mode == "fixed" and config.agent.greeting:
|
||||
await task.queue_frames([TTSSpeakFrame(config.agent.greeting)])
|
||||
elif config.agent.greeting_mode == "generated":
|
||||
elif config.agent.greeting_mode == "fastgpt_opener":
|
||||
if isinstance(llm, FastGPTLLMService):
|
||||
welcome = await llm.fetch_welcome_text()
|
||||
if welcome:
|
||||
await task.queue_frames([TTSSpeakFrame(welcome)])
|
||||
else:
|
||||
await task.queue_frames([LLMRunFrame()])
|
||||
logger.warning("FastGPT opener requested but no opener text was returned")
|
||||
else:
|
||||
await task.queue_frames([LLMRunFrame()])
|
||||
raise RuntimeError("agent.greeting_mode='fastgpt_opener' requires FastGPT LLM service")
|
||||
elif config.agent.greeting_mode == "generated":
|
||||
await task.queue_frames([LLMRunFrame()])
|
||||
|
||||
@transport.event_handler("on_client_disconnected")
|
||||
async def on_client_disconnected(_transport, _client):
|
||||
|
||||
@@ -63,7 +63,6 @@ def create_llm_service(
|
||||
base_url=config.base_url or "http://localhost:3000",
|
||||
chat_id=chat_id or config.chat_id,
|
||||
app_id=config.app_id,
|
||||
send_system_prompt=config.send_system_prompt,
|
||||
greeting_prompt=greeting_prompt,
|
||||
timeout=config.timeout_sec,
|
||||
settings=FastGPTLLMSettings(
|
||||
|
||||
Reference in New Issue
Block a user