themblem/doc/ai-chat.md
2025-10-29 21:27:29 +00:00

34 KiB
Raw Blame History

AI聊天功能技术实现计划

1. 项目概述

基于现有徵象防伪验证系统扩展AI客服聊天功能继承Kimi K2大模型能力为每个品牌租户提供个性化的AI客服服务。

2. 需求分析

2.1 核心功能需求

  • 接入Kimi K2或其他AI大模型API
  • 品牌专属AI客服独立回答本品牌产品相关问题
  • 多模态回答:文字、图片、视频链接、微信小程序码等
  • 联网搜索,以品牌官方信息为主
  • 支持客户上传额外内容供AI学习
  • 验证失败时提供对话式结果展示
  • 支持品牌色调定制

2.2 技术约束

  • 保留原有传统查询页面
  • 通过序列码批次管理选择使用页面类型
  • 与现有防伪验证流程集成

3. 系统架构设计

3.1 整体架构

┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   小程序前端     │    │    Web管理端     │    │   AI服务层      │
│  (AI聊天界面)    │◄──►│  (内容管理)      │◄──►│  (Kimi K2 API) │
└─────────────────┘    └─────────────────┘    └─────────────────┘
         │                       │                       │
         ▼                       ▼                       ▼
┌─────────────────┐    ┌─────────────────┐    ┌─────────────────┐
│   验证服务      │    │   内容存储      │    │   知识库管理    │
│  (二维码识别)    │    │  (OSS/数据库)    │    │  (品牌知识)     │
└─────────────────┘    └─────────────────┘    └─────────────────┘

3.2 数据流设计

  1. 用户扫描二维码 → 验证服务
  2. 验证结果 → AI聊天界面
  3. 用户提问 → AI服务层处理
  4. AI回答 → 返回多模态内容
  5. 用户反馈 → 知识库更新

4. 技术实现方案

4.1 AI模型集成

4.1.1 模型选择

  • 主要模型: Kimi K2 API 已实现
  • 备选模型: 智谱AI (ChatGLM)、百度文心一言
  • 理由: Kimi K2在中文理解、多模态处理和联网搜索方面表现优秀API稳定可靠特别适合品牌客服场景

4.1.2 API集成架构 已实现

# api/products/aichat.py
class AIChatService:
    def __init__(self, api_key: str = None, base_url: str = None):
        self.api_key = api_key or getattr(settings, 'KIMI_API_KEY', None)
        self.base_url = base_url or getattr(settings, 'KIMI_API_URL', None)
        self.client = OpenAI(api_key=self.api_key, base_url=self.base_url)
    
    def chat(self, user_message: str) -> str:
        # 调用Moonshot API支持工具调用
        response = self.client.chat.completions.create(
            model=self.model,
            messages=self.conversation_history,
            tools=self.tools,
            tool_choice="auto"
        )
        return self._process_response(response)

4.1.3 工具调用系统 已实现

  • 工具定义: start_qr_scan 二维码扫描工具
  • 工具执行: 模拟5秒扫描过程返回验证结果
  • 工具集成: 完整的工具调用流程,支持多轮对话

4.1.4 智能能力调度系统

  • 架构选择: 直接以Tool形式接入Kimi K2无需复杂路由
  • 能力分类: 知识库检索工具、二维码扫描工具、一般问答
  • 调度策略: 依赖Kimi K2的智能判断自动选择合适的工具
  • 优势: 实现简单、维护成本低、Kimi K2原生支持
  • 扩展性: 后续可轻松添加更多工具,无需修改路由逻辑

4.1.5 本地知识库系统

  • 存储方案: 向量数据库 + 文件存储
  • 内容类型: 文字、图片、视频、文档
  • 检索策略: 语义搜索 + 关键词匹配
  • 更新机制: 支持实时更新和版本控制
  • 成本优化: 本地处理减少API调用

4.1.6 RAG架构设计

class AIChatService:
    def __init__(self):
        self.client = OpenAI(api_key=KIMI_API_KEY, base_url=KIMI_API_URL)
        self.knowledge_base = LocalKnowledgeBase()  # 本地知识库
        self.tools = self._define_tools()
    
    def chat(self, message: str) -> str:
        # 步骤1从本地知识库检索相关信息
        relevant_docs = self.knowledge_base.search(message, k=3)
        
        # 步骤2构建增强的上下文
        enhanced_context = self._build_enhanced_context(message, relevant_docs)
        
        # 步骤3使用Kimi K2生成回答基于检索到的信息
        response = self.client.chat.completions.create(
            model=self.model,
            messages=[
                {"role": "system", "content": self.system_prompt + enhanced_context},
                {"role": "user", "content": message}
            ],
            tools=self.tools,
            tool_choice="auto"
        )
        
        # 步骤4处理工具调用如果需要
        if response.choices[0].message.tool_calls:
            # 执行工具调用逻辑...
            pass
        
        # 步骤5将问答对保存到知识库可选
        self.knowledge_base.add_qa_pair(message, response.choices[0].message.content)
        
        return response.choices[0].message.content
    
    def _build_enhanced_context(self, query: str, docs: List[Document]) -> str:
        """构建增强的上下文信息"""
        if not docs:
            return ""
        
        context = "\n\n相关参考信息:\n"
        for i, doc in enumerate(docs, 1):
            context += f"{i}. {doc.page_content}\n"
        
        context += f"\n请基于以上信息回答用户问题:{query}"
        return context

RAG流程

  • 检索(Retrieval):从本地知识库找到相关信息
  • 增强(Augmentation):将检索到的信息作为上下文
  • 生成(Generation)Kimi K2基于增强的上下文生成回答

4.1.7 本地知识库实现

class LocalKnowledgeBase:
    def __init__(self):
        # 使用轻量级向量数据库
        self.vector_store = Chroma(
            embedding_function=OpenAIEmbeddings(api_key=KIMI_API_KEY),
            persist_directory="./knowledge_base"
        )
        self.file_storage = FileStorage()  # 文件存储
    
    def search(self, query: str, k: int = 3, threshold: float = 0.5) -> List[Document]:
        """搜索本地知识库,返回相关文档列表"""
        # 语义搜索
        results = self.vector_store.similarity_search_with_score(query, k=k)
        
        # 过滤低置信度结果,但保留更多候选
        filtered_results = [r for r in results if r[1] > threshold]
        
        # 转换为Document对象列表
        documents = []
        for doc, score in filtered_results:
            documents.append(Document(
                page_content=doc.page_content,
                metadata={
                    **doc.metadata,
                    'similarity_score': score
                }
            ))
        
        return documents
    
    def add_content(self, content: str, content_type: str, metadata: dict):
        """添加内容到知识库"""
        # 文本内容直接向量化
        if content_type == 'text':
            self.vector_store.add_texts([content], [metadata])
        
        # 图片内容使用OCR提取文本
        elif content_type == 'image':
            text = self._extract_text_from_image(content)
            self.vector_store.add_texts([text], [metadata])
        
        # 视频内容提取关键帧和音频
        elif content_type == 'video':
            frames = self._extract_key_frames(content)
            audio_text = self._extract_audio_text(content)
            self.vector_store.add_texts([audio_text], [metadata])
    
    def add_qa_pair(self, question: str, answer: str):
        """添加问答对到知识库"""
        qa_text = f"问题:{question}\n答案:{answer}"
        metadata = {
            'type': 'qa_pair',
            'question': question,
            'answer': answer,
            'created_at': datetime.now().isoformat()
        }
        self.vector_store.add_texts([qa_text], [metadata])

技术特点

  • 轻量级使用Chroma向量数据库无需复杂部署
  • 多模态:支持文字、图片、视频内容
  • 实时更新:支持动态添加和更新内容
  • 成本优化本地处理减少API调用

4.1.8 完整RAG实现示例

from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.embeddings import OpenAIEmbeddings
from langchain.vectorstores import Chroma
from langchain.document_loaders import TextLoader, ImageLoader, VideoLoader

class RAGService:
    def __init__(self):
        self.embeddings = OpenAIEmbeddings(api_key=KIMI_API_KEY)
        self.text_splitter = RecursiveCharacterTextSplitter(
            chunk_size=1000,
            chunk_overlap=200
        )
        self.vector_store = Chroma(
            embedding_function=self.embeddings,
            persist_directory="./knowledge_base"
        )
    
    def add_document(self, file_path: str, content_type: str):
        """添加文档到知识库"""
        if content_type == 'text':
            loader = TextLoader(file_path)
        elif content_type == 'image':
            loader = ImageLoader(file_path)
        elif content_type == 'video':
            loader = VideoLoader(file_path)
        else:
            raise ValueError(f"不支持的内容类型: {content_type}")
        
        documents = loader.load()
        # 分块处理
        chunks = self.text_splitter.split_documents(documents)
        # 添加到向量数据库
        self.vector_store.add_documents(chunks)
    
    def retrieve_context(self, query: str, k: int = 3) -> str:
        """检索相关上下文"""
        docs = self.vector_store.similarity_search(query, k=k)
        context = "\n\n".join([doc.page_content for doc in docs])
        return context
    
    def generate_answer(self, query: str, context: str) -> str:
        """使用Kimi K2生成回答"""
        enhanced_prompt = f"""
基于以下参考信息回答用户问题:

参考信息:
{context}

用户问题:{query}

请基于参考信息提供准确、详细的回答。如果参考信息不足以回答问题,请明确说明。
"""
        
        response = self.client.chat.completions.create(
            model="kimi-k2-0711-preview",
            messages=[
                {"role": "system", "content": "你是徵象防伪验证平台的AI助手请基于提供的参考信息回答问题。"},
                {"role": "user", "content": enhanced_prompt}
            ],
            temperature=0.7,
            max_tokens=2000
        )
        
        return response.choices[0].message.content

# 使用示例
rag_service = RAGService()

# 添加文档
rag_service.add_document("产品说明.txt", "text")
rag_service.add_document("防伪标识.jpg", "image")
rag_service.add_document("操作演示.mp4", "video")

# 问答流程
query = "如何验证产品真伪?"
context = rag_service.retrieve_context(query)
answer = rag_service.generate_answer(query, context)

RAG优势

  • 信息可控:检索到的信息来自平台知识库
  • 回答质量Kimi K2基于准确信息生成高质量回答
  • 成本优化避免重复的API调用知识库一次构建多次使用
  • 专业性强:平台专业知识 + AI生成能力

4.1.9 架构选择说明

为什么选择直接以Tool形式接入Kimi K2

  1. 符合Kimi K2设计理念

    • Kimi K2本身就是为工具调用设计的
    • 原生支持Function Calling无需额外路由层
    • AI能根据上下文智能选择合适的工具
  2. 实现简单,维护成本低

    • 代码逻辑清晰,易于理解和维护
    • 避免复杂的if-else路由规则
    • 减少系统复杂度,降低出错概率
  3. 足够灵活,扩展性好

    • 可以轻松添加新的工具
    • 工具优先级通过描述和系统提示词控制
    • 支持复杂的工具组合调用
  4. 性能优势

    • 减少额外的路由判断逻辑
    • 直接利用Kimi K2的智能判断能力
    • 避免不必要的中间层处理

具体实现方式

def _define_tools(self):
    return [
        {
            "type": "function",
            "function": {
                "name": "search_knowledge_base",
                "description": "搜索徵象平台知识库,获取产品信息、防伪验证方法、技术文档等相关内容。当用户询问平台相关问题时,优先使用此工具。",
                "parameters": {
                    "type": "object",
                    "properties": {
                        "query": {
                            "type": "string", 
                            "description": "搜索查询,支持中文关键词"
                        },
                        "content_type": {
                            "type": "string",
                            "enum": ["all", "text", "image", "video"],
                            "description": "内容类型过滤"
                        }
                    },
                    "required": ["query"]
                }
            }
        },
        {
            "type": "function",
            "function": {
                "name": "start_qr_scan",
                "description": "启动二维码扫描功能,用于产品防伪验证。当用户需要验证产品真伪时使用。",
                "parameters": {
                    "type": "object",
                    "properties": {},
                    "required": []
                }
            }
        }
    ]

系统提示词优化

system_prompt = """你是一个专业的徵象防伪验证平台AI客服助手。

使用策略:
1. 当用户询问平台相关问题时优先使用search_knowledge_base工具搜索知识库
2. 当用户需要验证产品真伪时使用start_qr_scan工具启动扫描
3. 基于检索到的信息,结合你的知识,提供准确、详细的回答
4. 如果知识库信息不足,可以结合你的通用知识回答,但要明确说明信息来源

工具优先级:知识库搜索 > 二维码扫描 > 一般问答
"""

4.2 数据模型扩展

4.2.1 新增数据表

# api/products/models.py

class AIConfig(models.Model):
    """AI配置表"""
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
    model_provider = models.CharField(max_length=50, default='kimi')
    api_key = models.CharField(max_length=255)
    model_name = models.CharField(max_length=100, default='kimi-k2')
    
class BrandKnowledge(models.Model):
    """品牌知识库"""
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
    title = models.CharField(max_length=200)
    content = models.TextField()
    content_type = models.CharField(max_length=20)  # text, image, video, link
    file_url = models.URLField(null=True, blank=True)
    priority = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    
class PlatformKnowledge(models.Model):
    """平台知识库"""
    title = models.CharField(max_length=200)
    content = models.TextField()
    content_type = models.CharField(max_length=20, choices=[
        ('platform_intro', '平台介绍'),
        ('service_guide', '服务指南'),
        ('faq', '常见问题')
    ])
    ai_summary = models.TextField(null=True, blank=True, verbose_name="AI摘要版本")
    ai_segments = models.JSONField(default=dict, verbose_name="AI分段内容")
    ai_keywords = models.JSONField(default=list, verbose_name="AI关键词")
    is_platform_content = models.BooleanField(default=True)
    ai_priority = models.IntegerField(default=0)
    created_at = models.DateTimeField(auto_now_add=True)
    
class ChatSession(models.Model):
    """聊天会话"""
    session_id = models.CharField(max_length=100, unique=True)
    tenant = models.ForeignKey(Tenant, on_delete=models.CASCADE)
    user_openid = models.CharField(max_length=100, null=True)
    created_at = models.DateTimeField(auto_now_add=True)
    last_active = models.DateTimeField(auto_now=True)
    
class ChatMessage(models.Model):
    """聊天消息"""
    session = models.ForeignKey(ChatSession, on_delete=models.CASCADE)
    role = models.CharField(max_length=20)  # user, assistant, system
    content = models.TextField()
    content_type = models.CharField(max_length=20, default='text')
    metadata = models.JSONField(default=dict)
    created_at = models.DateTimeField(auto_now_add=True)

4.2.2 现有模型扩展

# 扩展CodeBatch模型
class CodeBatch(models.Model):
    # ... 现有字段 ...
    enable_ai_chat = models.BooleanField(default=False, verbose_name="启用AI聊天")
    ai_chat_config = models.JSONField(null=True, blank=True, verbose_name="AI聊天配置")
    
# 扩展Tenant模型  
class Tenant(models.Model):
    # ... 现有字段 ...
    ai_brand_name = models.CharField(max_length=100, null=True, blank=True, verbose_name="AI品牌名称")
    ai_welcome_message = models.TextField(null=True, blank=True, verbose_name="AI欢迎语")
    ai_theme_colors = models.JSONField(null=True, blank=True, verbose_name="AI主题色彩")

# TODO: 在MiniProgramContent模型中添加enable_ai_chat字段
# class MiniProgramContent(models.Model):
#     # ... 现有字段 ...
#     enable_ai_chat = models.BooleanField(default=False, verbose_name="启用AI客服")

4.3 后端API设计

4.3.1 AI聊天API

# api/products/views.py

class AIChatView(BaseView):
    name = 'ai-chat'
    auth_check = 'tenant'
    
    def post(self, request):
        """发送消息给AI"""
        session_id = request.data.get('session_id')
        message = request.data.get('message')
        context = request.data.get('context', {})
        
        # 获取或创建会话
        session = self._get_or_create_session(session_id, request.tenant)
        
        # 调用AI服务
        ai_service = AIService(request.tenant.id)
        response = ai_service.chat(message, context, self._get_tenant_context(request.tenant))
        
        # 保存消息记录
        self._save_message(session, 'user', message)
        self._save_message(session, 'assistant', response)
        
        return JsonResponse({
            'session_id': session.session_id,
            'response': response
        })
    
    def get(self, request):
        """获取聊天历史"""
        session_id = request.GET.get('session_id')
        if not session_id:
            return http400("session_id required")
            
        session = ChatSession.objects.filter(
            session_id=session_id,
            tenant=request.tenant
        ).first()
        
        if not session:
            return http404("Session not found")
            
        messages = ChatMessage.objects.filter(session=session).order_by('created_at')
        return JsonResponse({
            'messages': [self._serialize_message(m) for m in messages]
        })

class BrandKnowledgeView(BaseView):
    name = 'brand-knowledge'
    auth_check = 'tenant'
    
    def post(self, request):
        """上传品牌知识"""
        title = request.data.get('title')
        content = request.data.get('content')
        content_type = request.data.get('content_type', 'text')
        file_url = request.data.get('file_url')
        
        knowledge = BrandKnowledge.objects.create(
            tenant=request.tenant,
            title=title,
            content=content,
            content_type=content_type,
            file_url=file_url
        )
        
        return JsonResponse({'id': knowledge.id})

4.3.2 配置管理API

class AIConfigView(BaseView):
    name = 'ai-config'
    auth_check = 'tenant'
    
    def get(self, request):
        """获取AI配置"""
        config = AIConfig.objects.filter(tenant=request.tenant).first()
        if not config:
            config = AIConfig.objects.create(tenant=request.tenant)
        
        return JsonResponse({
            'model_provider': config.model_provider,
            'model_name': config.model_name,
            'temperature': config.temperature,
            'max_tokens': config.max_tokens,
            'is_active': config.is_active
        })
    
    def patch(self, request):
        """更新AI配置"""
        config = AIConfig.objects.filter(tenant=request.tenant).first()
        if not config:
            config = AIConfig.objects.create(tenant=request.tenant)
        
        for field in ['model_provider', 'model_name', 'temperature', 'max_tokens', 'is_active']:
            if field in request.data:
                setattr(config, field, request.data[field])
        
        config.save()
        return JsonResponse({'status': 'success'})

4.4 前端界面设计

4.4.1 小程序AI聊天界面

// scanner/pages/chat/chat.js
Page({
    data: {
        messages: [],
        inputValue: '',
        sessionId: null,
        tenant: null,
        loading: false
    },
    
    onLoad(options) {
        this.initChat(options);
    },
    
    async initChat(options) {
        // 获取租户信息
        const tenant = await this.getTenantInfo(options.tenant);
        this.setData({ tenant });
        
        // 创建或获取会话
        const sessionId = await this.createChatSession(tenant.id);
        this.setData({ sessionId });
        
        // 显示欢迎消息
        this.showWelcomeMessage(tenant);
        
        // 如果有验证结果,显示相关产品信息
        if (options.serial_code) {
            await this.showProductInfo(options.serial_code);
        }
    },
    
    async sendMessage() {
        if (!this.data.inputValue.trim()) return;
        
        const message = this.data.inputValue;
        this.addMessage('user', message);
        this.setData({ inputValue: '', loading: true });
        
        try {
            const response = await this.callAIChat(message);
            this.addMessage('assistant', response);
        } catch (error) {
            this.addMessage('system', '抱歉AI服务暂时不可用请稍后再试。');
        } finally {
            this.setData({ loading: false });
        }
    },
    
    async callAIChat(message) {
        const response = await wx.request({
            url: `${this.data.tenant.server_url}/api/v1/ai-chat/`,
            method: 'POST',
            data: {
                session_id: this.data.sessionId,
                message: message,
                context: this.getContext()
            },
            header: {
                'Authorization': `token ${this.data.tenant.token}`
            }
        });
        
        return response.data.response;
    }
});

4.4.2 Web管理端界面

<!-- web/src/views/ai-config.vue -->
<template>
  <div class="ai-config">
    <CCard>
      <CCardHeader>
        <h4>AI聊天配置</h4>
      </CCardHeader>
      <CCardBody>
        <CForm>
          <CFormGroup label="AI模型提供商">
            <CSelect v-model="config.model_provider">
              <option value="kimi">Kimi K2</option>
              <option value="zhipu">智谱AI</option>
              <option value="baidu">百度文心一言</option>
            </CSelect>
          </CFormGroup>
          
          <CFormGroup label="API密钥">
            <CInput v-model="config.api_key" type="password" />
          </CFormGroup>
          
          <CFormGroup label="模型名称">
            <CInput v-model="config.model_name" />
          </CFormGroup>
          
          <CFormGroup label="温度">
            <CInput v-model="config.temperature" type="number" step="0.1" min="0" max="2" />
          </CFormGroup>
          
          <CFormGroup label="最大Token数">
            <CInput v-model="config.max_tokens" type="number" />
          </CFormGroup>
          
          <CButton color="primary" @click="saveConfig">保存配置</CButton>
        </CForm>
      </CCardBody>
    </CCard>
    
    <CCard class="mt-4">
      <CCardHeader>
        <h4>品牌知识库</h4>
        <CButton color="success" @click="showAddKnowledge">添加知识</CButton>
      </CCardHeader>
      <CCardBody>
        <CTable :items="knowledgeList" :fields="knowledgeFields">
          <template #actions="{ item }">
            <CButton color="danger" size="sm" @click="deleteKnowledge(item.id)">删除</CButton>
          </template>
        </CTable>
      </CCardBody>
    </CCard>
  </div>
</template>

4.5 内容管理系统

4.5.1 知识库管理

  • 支持文本、图片、视频、链接等多种内容类型
  • 内容优先级设置
  • 内容分类标签
  • 版本控制

4.5.2 品牌定制

  • 品牌色调配置
  • 欢迎语定制
  • 头像和图标上传
  • 回答风格调整

4.5.3 首页AI客服开关

  • TODO: 在MiniProgramContent中添加enable_ai_chat字段
  • 后台管理简单的on/off开关
  • 小程序端判断bool值如果为true则跳转到chat页面
  • 实现方式:几行代码即可完成

4.5.3 平台知识库管理(简化版)

  • 平台介绍内容4000字的基础分块
  • 分层内容策略:摘要、完整两个层次
  • 基于关键词的简单内容选择
  • 基础内容压缩,避免信息过载

4.5.4 智能内容处理(简化版)

  • 基于LangChain的文档基础预处理
  • 简单分块策略:按段落和句子分割
  • 基础内容压缩:摘要和完整内容
  • 固定上下文长度简化Token管理

5. 技术实现细节

5.1.3 智能能力路由(简化版)

def route_capability(self, query, context):
    # 基于规则的快速路由
    capability = self._rule_based_routing(query)
    
    # 根据能力类型构建相应的Prompt
    if capability == "rag_knowledge":
        return self._build_rag_prompt(query, context)
    elif capability == "platform_service":
        return self._build_platform_prompt(query, context)
    else:
        return self._build_general_prompt(query, context)

5.2 多模态内容处理

5.2.1 内容类型支持

  • 文本: 直接返回
  • 图片: 上传到OSS返回URL
  • 视频: 支持微信视频号链接
  • 链接: 小程序码、商城链接等
  • 富文本: Markdown格式支持

5.2.2 内容渲染

// 内容渲染组件
function renderContent(content, type) {
    switch (type) {
        case 'text':
            return <Text>{content}</Text>;
        case 'image':
            return <Image src={content} mode="widthFix" />;
        case 'video':
            return <Video src={content} />;
        case 'link':
            return <Link href={content.url} text={content.text} />;
        case 'rich_text':
            return <RichText content={content} />;
        default:
            return <Text>{content}</Text>;
    }
}

5.3 会话管理

5.3.1 会话状态

  • 会话创建和销毁
  • 消息历史记录
  • 上下文保持
  • 会话超时处理

5.3.2 用户身份识别

  • 微信OpenID绑定
  • 匿名会话支持
  • 用户偏好记录

5.4 智能调度系统(简化版)

5.4.1 能力处理器架构

  • 基础能力处理器注册机制
  • 简单的能力降级策略
  • 固定路由规则

5.4.2 调度策略

  • 基于关键词的能力选择
  • 基础异常处理和回退
  • 简单性能监控
  • 后续版本支持高级功能

5.5 上下文长度管理

5.5.1 当前问题

  • 无限累积:对话历史无限制增长
  • Token超限可能超出API的token限制
  • 内存占用:长时间对话占用大量内存
  • API失败超长历史可能导致API调用失败

5.5.2 优化策略

class AIChatService:
    def __init__(self, api_key: str = None, base_url: str = None):
        # ... 现有代码 ...
        self.max_history_length = 20  # 最大历史记录数
        self.max_tokens_per_message = 1000  # 每条消息最大token数
    
    def _truncate_history(self):
        """截断对话历史,保持上下文长度"""
        if len(self.conversation_history) > self.max_history_length:
            # 保留系统提示词和最近的对话
            system_message = self.conversation_history[0]  # 系统提示词
            recent_messages = self.conversation_history[-self.max_history_length+1:]
            self.conversation_history = [system_message] + recent_messages
    
    def _estimate_tokens(self, text: str) -> int:
        """估算文本的token数量简化版"""
        # 中文约1.5字符=1token英文约4字符=1token
        chinese_chars = len([c for c in text if '\u4e00' <= c <= '\u9fff'])
        english_chars = len(text) - chinese_chars
        return int(chinese_chars / 1.5 + english_chars / 4)
    
    def _smart_truncate(self):
        """智能截断基于token数量而非消息数量"""
        total_tokens = sum(self._estimate_tokens(msg['content']) for msg in self.conversation_history)
        max_total_tokens = 4000  # 预留1000token给AI回复
        
        if total_tokens > max_total_tokens:
            # 保留系统提示词和最近的对话直到token数合适
            system_message = self.conversation_history[0]
            truncated_history = [system_message]
            
            for msg in reversed(self.conversation_history[1:]):
                truncated_history.insert(1, msg)
                current_tokens = sum(self._estimate_tokens(m['content']) for m in truncated_history)
                if current_tokens > max_total_tokens:
                    truncated_history.pop(1)  # 移除刚添加的消息
                    break
            
            self.conversation_history = truncated_history

5.5.3 分层历史策略

def _build_context_aware_history(self, user_message: str) -> List[Dict]:
    """构建上下文感知的对话历史"""
    # 策略1保留最近的N轮对话
    recent_messages = self.conversation_history[-10:]  # 最近10轮
    
    # 策略2保留关键信息如工具调用结果
    important_messages = [msg for msg in self.conversation_history 
                         if msg.get('role') == 'tool' or '重要' in msg.get('content', '')]
    
    # 策略3动态调整根据用户问题复杂度决定保留多少历史
    if '刚才' in user_message or '之前' in user_message:
        # 用户引用之前内容,保留更多历史
        context_messages = self.conversation_history[-15:]
    else:
        # 新话题,保留较少历史
        context_messages = self.conversation_history[-5:]
    
    return [self.conversation_history[0]] + context_messages  # 系统提示词 + 上下文

5.5.4 错误处理和降级

def chat(self, user_message: str) -> str:
    try:
        # 智能截断历史
        self._smart_truncate()
        
        # 调用API
        response = self.client.chat.completions.create(
            model=self.model,
            messages=self.conversation_history,
            tools=self.tools,
            tool_choice="auto",
            temperature=0.7,
            max_tokens=2000
        )
        
        # ... 处理响应 ...
        
    except Exception as e:
        if "context_length_exceeded" in str(e) or "token_limit" in str(e):
            # Token超限截断历史重试
            self._truncate_history()
            return self.chat(user_message)  # 递归重试
        else:
            return f"AI服务调用失败: {str(e)}"

7. 安全考虑

7.1 数据安全

  • API密钥加密存储
  • 用户隐私保护
  • 内容审核机制
  • 访问权限控制

7.2 系统安全

  • 请求频率限制
  • 异常监控告警

9. 项目计划

9.1 开发阶段

  1. 第一阶段 (1周): 核心架构和基础功能 已完成
    • 数据模型扩展(最小化)
    • Kimi K2 API基础集成
    • 基础AI聊天功能
    • 工具调用系统
    • Django管理命令
  2. 第二阶段 (1周): AI能力扩展
    • 知识库检索工具集成
    • 平台知识库(简化版)
    • 工具调用优化和扩展
  3. 第三阶段 (1周): 小程序集成和内容管理
    • 小程序AI聊天界面核心功能
    • 小程序与AI服务的集成
    • 内容管理基础功能
  4. 第四阶段 (1周): 集成测试和部署
    • 功能测试和bug修复
    • 性能优化
    • 生产环境部署

9.2 里程碑

  • Week 1: 完成核心架构和基础AI聊天功能 已完成
  • Week 2: 完成知识库检索工具和RAG系统基础功能
  • Week 3: 完成小程序AI聊天集成和内容管理
  • Week 4: 完成测试、优化和上线

10.3 Backup

  • 多AI服务商备选方案

11.2 开发周期

  • 总周期: 4周压缩版
  • 核心功能: AI聊天、RAG知识检索、工具调用、小程序集成、基础内容管理
  • 技术栈: Django + Kimi K2 + LangChain知识库管理+ 微信小程序 + 基础向量存储
  • 开发策略: MVP优先核心功能先行小程序集成优先后续迭代优化

11.3 架构设计总结

核心架构选择直接以Tool形式接入Kimi K2

  1. 简化设计:避免复杂的能力调度和路由逻辑
  2. 原生支持充分利用Kimi K2的Function Calling能力
  3. 易于维护:代码结构清晰,逻辑简单
  4. 扩展性好:后续可以轻松添加更多工具

RAG实现方式

  • 知识库检索作为工具提供给Kimi K2
  • AI根据用户问题自动选择是否使用知识库
  • 基于检索结果生成高质量回答
  • 无需手动路由完全依赖AI智能判断

技术优势

  • 减少系统复杂度
  • 降低维护成本
  • 提高系统稳定性
  • 保持架构简洁性