No description
Find a file
zhbaor e559f9ef2c feat: 完善温度参数功能与测试覆盖
- 新增温度参数动态处理功能,支持客户端优先级
- 新增 _get_glm_temperature() 方法,智能选择温度参数
- 新增 test_temperature_integration.py 专门的集成测试文件
- 新增36个温度参数相关的测试用例,覆盖所有边界情况
- GLM 请求优先使用客户端温度参数,Kimi 保持配置文件温度参数
- 增强日志记录,明确显示温度参数来源
- 测试结果:182个测试用例全部通过,整体覆盖率达到87%

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude <noreply@anthropic.com>
2025-11-18 20:38:22 +08:00
src feat: 完善温度参数功能与测试覆盖 2025-11-18 20:38:22 +08:00
tests feat: 完善温度参数功能与测试覆盖 2025-11-18 20:38:22 +08:00
.env.example feat: 添加 AI 模型温度参数支持 2025-11-13 10:45:05 +08:00
.gitignore Initial commit: KLM AI 模型融合项目 2025-11-12 23:34:12 +08:00
CLAUDE.md Initial commit: KLM AI 模型融合项目 2025-11-12 23:34:12 +08:00
openai-streaming-format.md Initial commit: KLM AI 模型融合项目 2025-11-12 23:34:12 +08:00
plan.md 优化配置和简化代码:改进开发体验 2025-11-13 09:14:00 +08:00
pytest.ini 优化配置和简化代码:改进开发体验 2025-11-13 09:14:00 +08:00
README.md 优化配置和简化代码:改进开发体验 2025-11-13 09:14:00 +08:00
requirements.txt Initial commit: KLM AI 模型融合项目 2025-11-12 23:34:12 +08:00
ruff.toml Initial commit: KLM AI 模型融合项目 2025-11-12 23:34:12 +08:00
TEST.md feat: 完善温度参数功能与测试覆盖 2025-11-18 20:38:22 +08:00

KLM - AI 模型融合项目

本项目用于将 GLM-4.6 高质量思维链拼接到文笔较好的 Kimi-K2-Instruct 上,达到较好的角色扮演效果。

项目概述

KLM 项目通过结合两种不同的 AI 模型优势,提供更优质的角色扮演体验:

  • GLM-4.6: 提供高质量的思维链(Chain of Thought)
  • Kimi-K2-Instruct: 具备优秀的文笔和表达能力

核心功能

  • 思维链拼接与融合
  • 模型输出优化
  • 角色扮演效果增强

技术架构

项目基于 OpenAI 格式的流式返回进行处理,支持思考内容和正文内容的分离传输与重组。

工作流程图

flowchart TD
    A[客户端请求<br>/v1/chat/completions] --> B[转发请求至 GLM-4.6]

    B --> C{GLM-4.6 流式响应}

    C --> D[第一阶段:思考内容非空<br/>正文内容为空]
    D --> E[原样返回思维链内容]
    E --> F{是否开始返回正文?}
    F -->|否| D

    F -->|是| G[第二阶段:思考内容为空<br/>正文内容非空]
    G --> H[思维链已完成<br/>拼接思维链到请求消息]
    H --> I[将思维链包装为<br/>&lt;thinking&gt;&lt;/thinking&gt;<br/>拼接到user角色消息]
    I --> J[转发拼接后的消息<br/>至 Kimi K2 Instruct]
    J --> K[接收 Kimi K2 Instruct<br/>的响应结果]
    K --> L[将 Kimi K2 Instruct 结果<br/>作为正文继续返回]
    L --> M[完成响应]

时序图

sequenceDiagram
    participant Client as 客户端
    participant API as KLM接口
    participant GLM as GLM-4.6
    participant Kimi as Kimi K2 Instruct

    Client->>API: POST /v1/chat/completions
    API->>GLM: 转发原始请求

    Note over GLM: 第一阶段:返回思维链
    loop 思考内容非空
        GLM-->>API: 思考内容
        API-->>Client: 转发思维链
    end

    Note over GLM: 第二阶段:返回正文
    GLM-->>API: 正文内容开始
    Note over API: 思维链已完成

    API->>API: 将思维链包装为thinking标签
    API->>API: 拼接到user角色消息中
    API->>Kimi: 转发拼接后的消息

    Kimi-->>API: 生成响应结果
    API-->>Client: 继续返回正文内容

    Note over Client,API: 流式响应完成

消息拼接机制

消息处理流程

KLM 项目的核心是智能的消息拼接机制,将 GLM-4.6 的思维链内容无缝整合到发送给 Kimi 的消息中。

拼接逻辑

当 GLM-4.6 完成思维链生成后,系统会:

  1. 识别用户消息:在消息列表中找到用户发送的最新消息
  2. 加载消息模板:从 src/utils/message_template.txt 文件加载预定义的模板
  3. 模板格式化:使用用户输入和思维链内容填充模板中的占位符:
    • {user_input}:替换为用户的原始消息内容
    • {thinking_content}:替换为 GLM-4.6 的思维链内容
  4. 替换用户消息:将格式化后的模板内容替换原始用户消息
  5. 保持其他消息不变:系统消息和助手消息保持原样

模板文件

消息模板存储在 src/utils/message_template.txt 文件中:

用户的原始输入是:
{user_input}

这是另一个模型的思考内容:
{thinking_content}

请遵循以上的思考内容,不得改变角色的心理活动,不得改变角色之间的关系,不得改变故事的情节,对细节加以润色,输出最终的结果。

代码实现

消息拼接的核心逻辑在 src/services/kimi_client.py 中:

def _load_message_template(self) -> str:
    """加载消息模板"""
    try:
        template_path = Path(__file__).parent.parent / "utils" / "message_template.txt"
        with open(template_path, "r", encoding="utf-8") as f:
            template = f.read()
        return template
    except Exception as e:
        # 如果模板加载失败,使用默认模板
        default_template = "用户的原始输入是:\n{user_input}\n\n..."
        return default_template

def _wrap_thinking_content(
    self, original_messages: List[ChatMessage], thinking_content: str
) -> List[ChatMessage]:
    """将思维链内容包装到用户消息中"""
    for msg in original_messages:
        if msg.role == "user":
            # 使用模板格式化消息内容
            wrapped_content = self.message_template.format(
                user_input=msg.content,
                thinking_content=thinking_content
            )
            # 创建新的消息...

消息拼接示例

假设客户端发送了以下对话:

原始对话历史

[
  {"role": "system", "content": "你是一个专业的作家助手"},
  {"role": "user", "content": "请帮我写一个关于友谊的小故事"},
  {"role": "assistant", "content": "我很乐意帮您写故事。您希望故事有什么特别的主题或风格吗?"}
]

新的用户请求

{"role": "user", "content": "写一个关于两个朋友在不同城市保持友谊的故事"}

GLM-4.6 思维链生成

GLM-4.6 会生成如下思维链:

我需要写一个关于异地友谊的故事。首先考虑故事的核心要素:
1. 两位主角的背景和性格
2. 他们如何成为朋友
3. 因为什么原因分隔两地
4. 他们如何维持友谊
5. 故事的温馨结尾

我想设计一个关于大学生毕业后分别在不同城市工作,但通过定期视频通话、互相寄送礼物等方式维持深厚友谊的故事...

发送给 Kimi 的最终消息

经过 KLM 系统处理后,发送给 Kimi 的消息会变成:

[
  {"role": "system", "content": "你是一个专业的作家助手"},
  {"role": "user", "content": "用户的原始输入是:\n写一个关于两个朋友在不同城市保持友谊的故事\n\n这是另一个模型的思考内容:\n我需要写一个关于异地友谊的故事。首先考虑故事的核心要素:\n1. 两位主角的背景和性格\n2. 他们如何成为朋友\n3. 因为什么原因分隔两地\n4. 他们如何维持友谊\n5. 故事的温馨结尾\n\n我想设计一个关于大学生毕业后分别在不同城市工作,但通过定期视频通话、互相寄送礼物等方式维持深厚友谊的故事...\n\n请遵循以上的思考内容,不得改变角色的心理活动,不得改变角色之间的关系,不得改变故事的情节,对细节加以润色,输出最终的结果"},
  {"role": "assistant", "content": "我很乐意帮您写故事。您希望故事有什么特别的主题或风格吗?"}
]

设计优势

基于模板的消息拼接方式具有以下优势:

  1. 模板化管理:消息格式通过模板文件管理,便于维护和修改
  2. 松耦合设计:代码逻辑与消息内容分离,降低系统耦合度
  3. 灵活配置:可通过修改模板文件调整消息格式,无需修改代码
  4. 容错机制:模板加载失败时自动使用默认模板,确保系统稳定性
  5. 可扩展性:易于添加新的占位符和模板变量
  6. 多语言支持:模板文件支持 UTF-8 编码,便于多语言场景应用
  7. 版本控制友好:模板文件可独立进行版本管理和追踪

Python 实现架构设计

推荐技术栈

Web 框架和 HTTP 处理

  • FastAPI: 现代异步 Web 框架,原生支持流式响应和 OpenAPI 文档
  • httpx: 异步 HTTP 客户端,用于与 GLM 和 Kimi API 通信
  • uvicorn: ASGI 服务器,用于部署 FastAPI 应用

数据处理

  • pydantic: 数据验证和序列化,处理 OpenAI 格式的请求/响应
  • orjson: 高性能 JSON 处理,支持流式数据解析

配置和日志

  • python-dotenv: 环境变量管理
  • loguru: 现代化日志库
  • typer: 现代化命令行界面库,用于创建开发工具和项目管理命令,如服务启动、配置验证、连接测试等

异步处理

  • asyncio: Python 原生异步编程
  • aiofiles: 异步文件操作

开发工具

  • ruff: 代码检查和格式化(已配置)
  • mypy: 静态类型检查
  • pytest: 测试框架

项目目录结构

klm/
├── src/
│   ├── __init__.py
│   ├── main.py                 # FastAPI应用入口
│   ├── config/
│   │   ├── __init__.py
│   │   └── settings.py         # 配置管理
│   ├── models/
│   │   ├── __init__.py
│   │   ├── openai.py          # OpenAI格式数据模型
│   │   └── internal.py        # 内部数据结构
│   ├── services/
│   │   ├── __init__.py
│   │   ├── glm_client.py      # GLM-4.6客户端
│   │   ├── kimi_client.py     # Kimi K2 Instruct客户端
│   │   └── fusion_service.py  # 模型融合核心逻辑
│   ├── api/
│   │   ├── __init__.py
│   │   ├── v1/
│   │   │   ├── __init__.py
│   │   │   └── chat.py        # /v1/chat/completions端点
│   │   └── middleware.py      # 中间件
│   └── utils/
│       ├── __init__.py
│       ├── logger.py          # 日志工具
│       └── streaming.py       # 流式处理工具
├── tests/
│   ├── __init__.py
│   ├── test_models.py
│   ├── test_services.py
│   └── test_api.py
├── requirements.txt
├── pyproject.toml
├── .env.example
└── README.md

核心模块设计

1. 数据模型层 (models/)

  • 定义 OpenAI 格式的请求/响应数据结构
  • 使用 pydantic 进行数据验证
  • 支持流式数据的增量更新
  • 处理 reasoning_content 和 content 字段分离

2. 服务层 (services/)

  • GLM 客户端: 处理与 GLM-4.6 的 API 通信,解析思维链
  • Kimi 客户端: 处理与 Kimi K2 Instruct 的 API 通信
  • 融合服务: 核心业务逻辑,管理两阶段请求流程

3. API 层 (api/)

  • 实现 OpenAI 兼容的/v1/chat/completions 端点
  • 流式响应处理
  • 请求路由和中间件

4. 工具层 (utils/)

  • 日志记录和监控
  • 流式数据处理工具
  • 通用辅助函数

技术实现要点

流式处理架构

  • 使用异步生成器处理流式数据
  • 实现两阶段响应的状态管理
  • 确保数据传输的实时性和完整性
  • 支持 reasoning_content 和 content 的无缝切换

错误处理和监控

  • 全面的异常捕获和处理
  • 请求链路追踪
  • 性能监控和日志记录
  • 优雅降级机制

配置管理

  • 环境变量配置
  • API 密钥安全管理
  • 运行时配置热重载

技术选择说明

为什么使用 httpx 而不是 OpenAI 客户端库?

对于 KLM 这种 AI 模型融合中间件项目,推荐使用httpx + 自定义逻辑而不是 OpenAI 客户端库,原因如下:

  1. 完全控制: 可以精确处理每个流式数据块,支持 GLM-4.6 特有的 reasoning_content 字段
  2. 灵活解析: 支持自定义的数据解析和状态管理逻辑
  3. 状态管理: 能够实现两阶段响应的状态跟踪和思维链拼接
  4. 错误处理: 更细粒度的异常处理和重试机制
  5. 代理架构: 作为中间件,需要深度控制请求转发和响应处理流程

开发流程

代码质量保证

# 运行代码检查和格式化
ruff check --fix . --unsafe-fixes && ruff format .

测试

详细的测试指南请参考 测试文档,包含环境设置、测试命令和覆盖率要求。

快速测试命令:

# 运行所有测试(推荐)
uv run pytest tests/ -v

# 生成覆盖率报告
uv run pytest tests/ -v --cov=src --cov-report=html

# 查看未覆盖的行号
uv run pytest tests/ -v --cov=src --cov-report=term-missing

# 设置覆盖率阈值
uv run pytest tests/ -v --cov=src --cov-fail-under=80

注意: 项目已配置 pytest.ini 文件自动设置 pythonpath = src,无需手动设置 PYTHONPATH

文档

使用方法

具体使用方法请参考项目文档。