"""Pipecat LLMService 工厂。 Phase 1 spike 的选型结论固化在这里:**复用 Pipecat 自带的 `DeepSeekLLMService`**, 不自写 `FallbackProvider → LLMService` 适配器。 理由(详见笔记库 `P1-Flows兼容性Spike结论.md`): 1. 它自带 `DeepSeekLLMAdapter`,处理"思考模式下必须把 reasoning_content 原样回传"这个约束——**正是本项目 P0 阶段踩过的坑**,框架已经做了。 2. `thinking` 默认就是 disabled,与本项目既有结论一致。 3. 支持自定义 `base_url`,将来要接本地 vLLM 也能用。 4. Flows 硬要求 `LLMService` 实例,而 `pipecat.flows` 的 `LLMAdapter` **只管摘要生成**,不是 provider 适配器——想保留 `FallbackProvider` 必须自己写 `LLMService` 子类,成本不划算。 **代价**:失去 `FallbackProvider` 的本地 vLLM 降级。当前本机 vLLM 已停用, fallback 实际没有可用目标,所以先只用 DeepSeek。将来若需双后端, Pipecat 有 `LLMSwitcher` 可用,不必自写。 """ from __future__ import annotations import logging from ..config import LLMConfig log = logging.getLogger(__name__) def create_llm_service(cfg: LLMConfig): """按配置造 Pipecat LLMService。 目前只支持 DeepSeek(OpenAI 兼容)。其它后端返回 None,调用方应当 回退到 legacy 路径,而不是带着一个坏 service 继续。 """ if cfg.name != "deepseek": log.warning("Flows 路径暂不支持后端 %r,请继续使用 legacy", cfg.name) return None from pipecat.services.deepseek.llm import DeepSeekLLMService # **必须显式覆盖模型名。** # Pipecat 的默认是 `deepseek-v4-flash`,该模型不存在,用默认值会 400。 # 见 P0-DeepSeek验证报告.md:真实清单只有 deepseek-flash 与 deepseek-v4-pro。 settings = DeepSeekLLMService.Settings( model=cfg.model, # 显式关闭思考。Pipecat 的默认恰好也是 disabled,但写出来更安全: # 将来默认值变化时不会悄悄改变行为,也不至于把思考内容送进 TTS。 thinking=DeepSeekLLMService.ThinkingConfig(type="disabled"), max_tokens=cfg.max_tokens, ) return DeepSeekLLMService( api_key=cfg.api_key, base_url=cfg.base_url, settings=settings, ) __all__ = ["create_llm_service"]