1.作者介绍

韦昊,男,西安工程大学电子信息学院,2025级研究生

研究方向:机器视觉与人工智能

电子邮件:2154548512@qq.com

程锡贵,男,西安工程大学电子信息学院,2025级研究生,张宏伟人工智能题组

研究方向:机器视觉与人工智能

电子邮件:15327178796@163.com

2.关于理论方面的知识介绍

2.1 硅基流动平台一站式大模型云服务

硅基流动(SiliconCloud)是硅基流动公司推出的一站式大模型云服务平台 ,致力于为开发者和企业提供高效、低成本且全面的生成式人工智能(GenAI)模型服务,包括 IaaS、PaaS 和 MaaS。其核心目标是通过优化大模型使用体验,帮助用户实现 “Token 自由”,即以更低成本和更高效率使用先进的大语言模型(LLMs)及其他生成式人工智能(AI)模型。

主要特点与功能

丰富的大模型支持:平台集成多种主流开源大模型,涵盖但不限于:文本生成模型(如 DeepSeek R1 & V3、Qwen2.5、GLM-4、Llama-3.X、Gemma-2、InternLM、Yi-1.5 等)和图片生成模型(如 Janus-Pro、Stable Diffusion(SDXL)、FLUX 等)。

多模态模型:支持文本生成语音、文本生成图像、文本生成视频等功能。代码生成模型包括 Qwen2.5-Coder-32B-Instruct 等。

高性价比优势:提供行业内较低的 API 调用价格。对于 9B 及以下的模型,平台提供永久免费 API 服务,适合个人开发者及小型项目使用。

图一 硅基流动首页图

2.2 deepseek-ai/DeepSeek-V3

图二 模型架构图

模型定位: 深度求索(DeepSeek-AI)推出的新一代 MoE(混合专家)架构通用大语言模型,旨在实现高性能与低成本推理的完美平衡。

核心架构: MoE 稀疏激活架构,拥有 671B 的总参数量,但每次推理仅激活 37B 参数,兼顾了强大的模型容量与高效的计算效率。

上下文窗口: 支持高达 128K 的超长上下文,能够轻松处理长文档、代码库、法律合同等复杂任务

长文本优化(MLA): 采用多头潜在注意力(MLA)技术,大幅压缩 KV 缓存,使得在处理 128K 长文本时依然保持高速和稳定,避免了性能下降和显存溢出问题

图三 MOE

DeepSeek中的MOE

为了在负载均衡 和模型性能之间取得更好的平衡,DeepSeek开创了一种无辅助损失的负载均衡策略:为每个专家引入一个偏差项,并将其添加到相应的亲和力分数中以确定top-K路由,具体来说:如果其对应的专家过载,我们将偏差项减少b ;如果其对应的专家负载不足,我们将偏差项增加b ,其中b 是一个称为偏差更新速度的超参数。

图四 MLA 多头潜在注意力

MLA 多头潜在注意力

本质就是在计算注意力之前进行各种向量降维(用于降低注意力计算和后端推理的计算量)和加入旋转位置编码(RoPE)(目的是:通过旋转矩阵将位置信息融入词向量的内积计算中,从而在注意力机制中隐式编码相对位置关系)。

2.3 硅基流动API接入

3.关于实验过程的介绍,完整实验代码,测试结果

3.1完整代码

目录结构

config.ini: 存储API配置(base_url, api_key, model等)。

entities: 定义消息实体,用于统一对话格式。

providers/llm_provider.py: 封装API调用逻辑,包括非流式和流式。

providers/chat_repository.py: 管理对话历史存储和加载。

services: 对话服务,整合 LLM 调用和历史管理。

utils: 加载 config.ini 配置。

main.py: 主入口,实现终端交互循环。

requirements.txt: 列出依赖

entities下的message.py
from typing import Literal
from dataclasses import dataclass
from datetime import datetime

@dataclass
class Message:
    role: Literal["user", "assistant", "system"]
    content: str
    timestamp: str = None

    def __post_init__(self):
        if self.timestamp is None:
            self.timestamp = datetime.now().isoformat()

    def to_dict(self):
        return {
            "role": self.role,
            "content": self.content,
            "timestamp": self.timestamp
        }
providers下的chat_repository.py
import json
import os
from typing import List
from entities.message import Message

class ChatRepository:
    def __init__(self, history_file: str):
        self.history_file = history_file

    def load_history(self) -> List[Message]:
        """从文件加载历史消息"""
        if not os.path.exists(self.history_file):
            return []
        messages = []
        with open(self.history_file, 'r', encoding='utf-8') as f:
            for line in f:
                line = line.strip()
                if line:
                    data = json.loads(line)
                    messages.append(Message(
                        role=data["role"],
                        content=data["content"],
                        timestamp=data.get("timestamp")
                    ))
        return messages

    def append_message(self, message: Message):
        """追加一条消息到文件"""
        with open(self.history_file, 'a', encoding='utf-8') as f:
            f.write(json.dumps(message.to_dict(), ensure_ascii=False) + '\n')

    def clear_history(self):
        """清空历史文件"""
        if os.path.exists(self.history_file):
            os.remove(self.history_file)

providers下的llm_prodiver.py
import requests
import json
from typing import List, Dict, Generator, Optional
# 假设这是你项目中定义的 Message 实体类
from entities.message import Message

class LLMProvider:
    def __init__(self, base_url: str, api_key: str, model: str, max_tokens: int, temperature: float):
        # 移除 URL 末尾的斜杠,防止拼接路径时出现双斜杠
        self.base_url = base_url.rstrip('/')
        self.api_key = api_key
        self.model = model
        self.max_tokens = max_tokens
        self.temperature = temperature
        # 构造标准的 API 请求头,通常采用 Bearer Token 鉴权方式
        self.headers = {
            "Content-Type": "application/json",
            "Authorization": f"Bearer {self.api_key}"
        }

    def _build_payload(self, messages: List[Dict], stream: bool) -> Dict:
        """构建发送给大模型 API 的请求体 (遵循 OpenAI 接口规范)"""
        return {
            "model": self.model,
            "messages": messages,
            "max_tokens": self.max_tokens,
            "temperature": self.temperature,
            "stream": stream,     # 控制是否开启流式输出
            "top_p": 0.9          # 控制生成文本的多样性
        }

    def chat_completion(self, messages: List[Dict]) -> str:
        """非流式调用,等待模型生成完毕后返回完整回答"""
        payload = self._build_payload(messages, stream=False)
        
        # 发起同步 POST 请求
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers=self.headers,
            json=payload,
            timeout=60
        )
        
        # 检查 HTTP 状态码,非 200 则抛出异常
        if response.status_code != 200:
            raise Exception(f"API 请求失败: {response.status_code} - {response.text}")
            
        # 解析返回的 JSON 数据
        data = response.json()
        
        # 从标准的 OpenAI 响应结构中提取最终回复的文本内容
        return data["choices"][0]["message"]["content"]

    def chat_completion_stream(self, messages: List[Dict]) -> Generator[str, None, None]:
        """流式调用,逐个产出 (yield) token,用于实现打字机效果"""
        payload = self._build_payload(messages, stream=True)
        
        # 发起 POST 请求,开启 stream=True 以接收 Server-Sent Events (SSE) 数据流
        response = requests.post(
            f"{self.base_url}/chat/completions",
            headers=self.headers,
            json=payload,
            stream=True,
            timeout=60
        )
        
        if response.status_code != 200:
            raise Exception(f"API 请求失败: {response.status_code} - {response.text}")
            
        # 核心逻辑:遍历流式响应的每一行数据
        for line in response.iter_lines():
            if line:
                # 将 bytes 解码为字符串
                line = line.decode('utf-8')
                
                # SSE 协议标准:数据通常以 "data: " 开头
                if line.startswith("data: "):
                    # 截取 "data: " 后面的实际 JSON 字符串
                    data_str = line[6:]
                    
                    # API 约定:以 "data: [DONE]" 标识流式输出结束
                    if data_str == "[DONE]":
                        break
                        
                    try:
                        # 解析这一数据块 (chunk) 的 JSON
                        chunk = json.loads(data_str)
                        
                        # 获取当前数据块的增量内容 (delta)
                        delta = chunk["choices"][0]["delta"]
                        
                        # 只有当 delta 中包含 "content" 字段时,才说明生成了新的文本内容
                        if "content" in delta:
                            # 产出 (yield) 这个字/词,供外部循环调用实时显示
                            yield delta["content"]
                    except json.JSONDecodeError:
                        # 如果出现 JSON 解析错误(例如数据截断),直接跳过继续处理下一行
                        continue

service下的chat_service.py
from typing import List, Generator
from entities.message import Message
from providers.llm_provider import LLMProvider
from providers.chat_repository import ChatRepository

class ChatService:
    def __init__(self, llm_provider: LLMProvider, repository: ChatRepository, system_prompt: str = None):
        self.llm = llm_provider
        self.repo = repository
        self.system_prompt = system_prompt

    def _build_messages_for_api(self, history: List[Message]) -> List[dict]:
        """将内部的 Message 实体列表转换为大模型 API 所需的标准字典数组格式"""
        messages = []
        
        # 核心逻辑:如果设置了 system prompt(系统提示词),必须将其作为第一条消息注入
        # 这决定了 AI 的人设、回答格式和核心行为准则
        if self.system_prompt:
            messages.append({"role": "system", "content": self.system_prompt})
            
        # 遍历历史对话记录,将上下文按顺序加入,让大模型拥有记忆
        for msg in history:
            messages.append({"role": msg.role, "content": msg.content})
        return messages

    # --- 拆分 1:非流式方法(只负责 return) ---
    def send_message(self, user_input: str) -> str:
        """发送用户消息,获取助手完整回复(非流式)。"""
        # 1. 从存储介质(数据库/本地文件)中加载之前的历史对话
        history = self.repo.load_history()
        user_msg = Message(role="user", content=user_input)
        
        # 2. 构造包含历史记录的 API 消息体,并将当前用户的最新输入追加到末尾
        api_messages = self._build_messages_for_api(history)
        api_messages.append({"role": "user", "content": user_input})

        # 3. 发起网络请求,阻塞等待大模型生成完整的回复
        response = self.llm.chat_completion(api_messages)
        
        # 4. 核心持久化逻辑:将“用户的问题”和“AI的完整回答”保存到本地记录中
        # 这样下一次调用 load_history() 时就能带上这次的对话
        self.repo.append_message(user_msg)
        assistant_msg = Message(role="assistant", content=response)
        self.repo.append_message(assistant_msg)
        
        return response

    # --- 拆分 2:流式方法(只负责 yield) ---
    def send_message_stream(self, user_input: str) -> Generator[str, None, None]:
        """发送用户消息,流式获取助手回复。"""
        history = self.repo.load_history()
        user_msg = Message(role="user", content=user_input)
        
        api_messages = self._build_messages_for_api(history)
        api_messages.append({"role": "user", "content": user_input})

        # 核心逻辑:定义一个空字符串,用于在流式产出时“拼接”完整的回答
        # 因为我们虽然是一段段发给前端,但最终保存到数据库里需要一段完整的文本
        full_response = ""
        
        # 遍历底层 LLMProvider yield 出来的每一个 token(字/词)
        for token in self.llm.chat_completion_stream(api_messages):
            # 将每个 token 拼接到完整回复中
            full_response += token
            # 实时将 token 抛给上层调用者(通常是 UI 层),实现打字机效果
            yield token
            
        # 核心持久化逻辑:当 for 循环结束时,意味着流式输出完毕,full_response 已经拼接完整。
        # 此时再将用户消息和拼接完成的 AI 消息一同持久化保存。
        self.repo.append_message(user_msg)
        assistant_msg = Message(role="assistant", content=full_response)
        self.repo.append_message(assistant_msg)
    
    def clear_conversation(self):
        """清空对话历史"""
        self.repo.clear_history()

utils下的config_loader.py
import configparser
import os

def load_config(config_path="config.ini"):
    config = configparser.ConfigParser()
    if not os.path.exists(config_path):
        raise FileNotFoundError(f"配置文件 {config_path} 不存在")
    config.read(config_path, encoding='utf-8')
    api_config = config["API"]
    return {
        "base_url": api_config.get("base_url"),
        "api_key": api_config.get("api_key"),
        "model": api_config.get("model"),
        "max_tokens": api_config.getint("max_tokens"),
        "temperature": api_config.getfloat("temperature"),
        "stream": api_config.getboolean("stream"),
        "save_history": api_config.getboolean("save_history"),
        "history_file": api_config.get("history_file")
    }

配置文件config.ini
# 配置组标识,说明接下来的配置项都属于 API 相关的参数
[API]

# 大模型 API 的基础请求路径(这里使用的是硅基流动 SiliconFlow 的 OpenAI 兼容接口)
base_url = https://api.siliconflow.cn/v1

# 你的 API 密钥/鉴权令牌(需要从服务商后台获取并填入,注意不要泄露给他人)
api_key = sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# 指定调用的具体大模型名称(这里使用的是 DeepSeek-V3 模型)
model = deepseek-ai/DeepSeek-V3

# 单次模型生成回复的最大 Token 数量限制(控制单次回答的长度,防止消耗过多额度)
max_tokens = 2000

# 采样温度,控制生成文本的随机性/创造性(值在 0 到 2 之间,0.7 属于日常聊天平衡严谨与创意的推荐值)
temperature = 0.7

# 是否开启流式传输开关(true 表示开启,模型会像打字机一样逐字返回结果,提升用户体验)
stream = true

# 是否保存对话历史记录的开关(true 表示开启持久化存储,下次启动可以加载记忆)
save_history = true

# 历史记录保存的文件路径和名称(这里采用 .jsonl 格式,即每行一条完整 JSON,非常适合按行追加对话数据)
history_file = conversation_history.jsonl

main.py
import sys
# 导入自定义的配置加载器、模型服务商、历史仓储以及核心对话服务
from utils.config_loader import load_config
from providers.llm_provider import LLMProvider
from providers.chat_repository import ChatRepository
from services.chat_service import ChatService

def main():
    # ----------------------------------------------------------------
    # 1. 初始化与配置校验阶段
    # ----------------------------------------------------------------
    try:
        # 读取 config.ini / config.json 等配置文件的参数
        config = load_config()
    except Exception as e:
        print(f"加载配置失败: {e}")
        return

    api_key = config["api_key"]
    # 安全检查:防止用户忘记修改占位符直接运行程序
    if not api_key or api_key == "YOUR_API_KEY_HERE":
        print("请先在 config.ini 中填写有效的 API Key")
        return

    # ----------------------------------------------------------------
    # 2. 依赖注入与组件组装
    # ----------------------------------------------------------------
    # 初始化底层的 API 调用器
    llm = LLMProvider(
        base_url=config["base_url"],
        api_key=api_key,
        model=config["model"],
        max_tokens=config["max_tokens"],
        temperature=config["temperature"]
    )
    # 初始化历史记录读写仓储(负责读写 JSONL 文件)
    repo = ChatRepository(config["history_file"])
    # 设定全局的系统提示词(人设)
    system_prompt = "你是智能对话机器人"
    # 将底层基础组件“注入”到核心业务层 ChatService 中
    chat_service = ChatService(llm, repo, system_prompt)

    # ----------------------------------------------------------------
    # 3. 终端交互循环 (REPL 保持程序不退出)
    # ----------------------------------------------------------------
    print("===== 智能对话终端 (DeepSeek-V3) =====")
    print("输入 'exit' 退出,输入 'clear' 清空对话历史\n")
    
    while True:
        try:
            # 获取用户输入并去除首尾空格
            user_input = input("你: ").strip()
            
            # 命令检查:退出程序
            if user_input.lower() == "exit":
                print("再见!")
                break
            # 命令检查:清空上下文缓存和本地历史文件
            elif user_input.lower() == "clear":
                chat_service.clear_conversation()
                print("对话历史已清空。\n")
                continue
            # 空输入拦截:防止把空字符串发给大模型浪费算力
            elif not user_input:
                continue

            # 从配置文件获取是否开启流式的布尔值(默认不开启)
            use_stream = config.get("stream", False)
            
            # ------------------------------------------------------------
            # 4. 对话路由分支(流式 VS 非流式)
            # ------------------------------------------------------------
            if use_stream:
                # end="" 使得“助手: ”打印后不换行;flush=True 强制刷新缓冲区使文字立即显示
                print("助手: ", end="", flush=True)
                
                # 遍历服务层产生的每一个增量文本块 (Token)
                for token in chat_service.send_message_stream(user_input):
                    # 逐个字打印出来。end="" 保证字与字紧密相连,flush=True 才能形成行云流水的打字机效果
                    print(token, end="", flush=True)
                # 当整个流式生成结束后,手动打印一个换行符,为下一次“你:”的输入留出空间
                print("\n")
            else:
                # 非流式分支:直接调用并同步等待获取完整的文本结果
                response = chat_service.send_message(user_input)
                print(f"助手: {response}\n")
                
        except KeyboardInterrupt:
            # 捕获用户在终端按下 Ctrl+C 的行为,优雅退出而不是抛出一堆乱七八糟的报错
            print("\n退出程序")
            break
        except Exception as e:
            # 捕获异常(如网络超时、API 报错等),保证当前这轮报错后,循环不中断,依然能继续下一次对话
            print(f"发生错误: {e}\n")

if __name__ == "__main__":
    main()

requirements.txt	
requests>=2.31.0

3.2运行结果

4.参考连接

硅基流动介绍:

https://blog.csdn.net/fyfugoyfa/article/details/145430651

deepseekV3介绍:

https://blog.csdn.net/weixin_50917576/article/details/145601149

Logo

汇聚全球AI编程工具,助力开发者即刻编程。

更多推荐