构建AI智能体:二十五、智能时代的知识库全链路优化:从构建、检索到生命周期健康管理

智能知识库全链路优化

王者杯·14天创作挑战营·第5期 10w+人浏览 569人参与

一、投石问路

        相信大家有没有过这样的经历,急需某个操作流程,比如要找“给客户开发票”的相关信息,结果发现自己要在电脑里翻箱倒柜,从一堆命名混乱的Word、Excel里寻找那份不知道有没有存档、也不知道更新没更新的“开票说明.docx”。找到了,还得像做阅读理解一样,从十几页的文字里抠出自己需要的那几条信息。这个我们习以为常、普通的不能再普通的过程,时时刻刻都在我们的工作中经历着,这种不仅效率低、体验差,而且极易出错。

        想象一下,如果有一天,我们再需要什么内容时,只需像现在的deepseek搜索引擎一样,自然地输入一句:“请问给客户开专票需要准备什么?”一秒之内,一个清晰、准确、最新的答案列表就直接弹到你眼前。如今的AI时代已经达到了这种效果,然而企业发展过程中,有很多散落各处的本地文档,日积月累的形成了企业的文档库,如果我们能整合这些手册、文档,形成一个真正意义上的本地知识库,可以快速、方便的对这些知识手册进行检索查阅将是一件更加大快人心的事情,今天,时代精进,人工智能飞速发展,我们可以实现这件大快人心的事情了,接下来就让我们一起聊聊,知识库如何从一个静态的档案柜,成长为我们身边最得力的智慧大脑,将企业的核心档案升级为一个会思考、能对话的智能数字知识库。

二、知识库的定义与重要性

        知识库是一个结构化的、经过组织的、可用于智能检索和推理的知识集合,它并非一个简单的文件仓库或问答列表,它旨在捕获、整理和存储企业内部的显性知识如规章制度、产品手册、流程指南、技术文档、常见问题解答等和部分隐性知识,如专家经验、解决方案案例,并提供一个集中化的平台供员工检索和使用。

        在当今信息爆炸的时代,知识库已成为企业不可或缺的核心战略资产,日积月累已经形成了运营管理过程中不可或缺的部分:

企业赋能提升员工效率:

  • 统一信息出口:确保员工获取的信息是唯一、最新、准确的版本,避免因信息源混乱导致的决策失误和操作错误。
  • 自助式解决问题:员工可以随时、随地快速找到解决方案,减少对专家同事的重复性打扰,实现自助服务,极大提升个人工作效率和体验。
  • 加速新人成长:新员工通过知识库可以快速学习业务流程、产品知识和公司制度,显著缩短培训周期和上岗时间。

企业运营降本增效:

  • 降低运营成本:减少客服、技术支持等岗位的重复性咨询压力,让人力资源聚焦于更复杂、高价值的问题。
  • 沉淀企业智慧:将分散在个人大脑、邮件、聊天记录中的知识系统化地沉淀下来,避免人才流失即知识流失的风险,形成企业的数字资产。
  • 保障合规与标准:确保业务流程(如财务报销、合规操作)的执行有据可依、标准统一,降低操作风险。

智能客服提升服务:

  • 一个强大的知识库是智能客服机器人的大脑,它能提供7x24小时即时、准确的自动应答,大幅提升客户满意度和忠诚度。

三、传统知识库的变革

        尽管知识库理念先进,但传统基于关键词匹配和手动维护的知识库系统在实践中饱受诟病,存在很多痛点:

  • 关键词匹配的局限:检索不准,形成答非所问的困境,传统搜索依赖纯粹的关键词匹配,如数据库LIKE查询或简单搜索引擎,它无法理解语义。
  • 完全依赖人工:知识的录入、分类、更新、过期清理全部需要领域专家手动完成,是一项极其繁琐、耗时的工作,导致心有余而力不足。
  • 更新滞后:业务流程一变,所有相关文档都需要人工找出并修改,稍有遗漏就会导致知识库内容过期,让人不敢信。
  • 投入产出比低:高昂的维护成本使得许多企业的知识库项目最终沦为无人问津、内容陈旧的数字废墟。
  • 被动而非主动:知识库是一个需要被维护知识的被动系统。它无法自动从企业日常运转的如客服对话记录、项目复盘文档、会议纪要中挖掘和提炼知识。
  • 形成孤岛:知识散落在各处,无法有效流入知识库,使得知识库与现实脱节,价值无法最大化。

        近年来,大语言模型的和向量数据库带来的变革,相关技术的成熟与应用,两者的协同效应为打造新一代智能知识库提供了革命性的解决方案,两者结合构成了现代智能知识库的双引擎。向量数据库充当海马体,负责快速、精准地记忆和召回知识片段;大模型则充当大脑皮层,负责理解、推理和组织语言,给出最终答案。二者的结合,使得知识库终于从一个“静态档案柜”进化成了一个能够“听懂人话、对答如流”的企业智慧大脑,真正成为了企业智能化的核心基石。

四、知识库问题生成与检索优化

1. 问题生成:解决语义鸿沟的理论基础

        传统知识库只有标准问题和答案,用户提问的方式和知识库中标准问题的表述之间存在着巨大的语义鸿沟。为了解决这一问题,自动化问题生成成为关键。利用Qwen大模型强大的文本理解与生成能力,我们可以从已有的“答案”反向生成多种可能的用户问题,极大地扩充知识库的入口,提高命中率。

  • 理论依据:基于答案感知的问题生成。大语言模型(如Qwen)通过理解答案的语义内容,学习生成与之对应的、多种表述形式的问题。
  • 生成策略:
    • 同义改写:生成与标准问题语义相同但表述不同的问题。(例如:“如何申请年假?” -> “年假的申请流程是怎样的?”)
    • 视角转换:从不同角度提问。(例如:从员工角度“我怎么请假?”到HR角度“请假制度是什么?”)
    • 难度分级:生成简单、中等、复杂不同层次的问题,以匹配不同用户的认知水平。
  • 价值:极大地扩展了知识库的入口,提升了召回率,确保用户各种千奇百怪的问法都能被正确匹配,导向正确的答案。

2. 检索优化:从关键词到语义理解

2.1 方法介绍

        检索是知识库的大门,其核心是从海量知识中快速、准确地找到最相关的内容。

传统方法:稀疏检索(如BM25)

  • 理论:基于词频统计(TF)和逆文档频率(IDF)。BM25通过计算查询词条与文档的加权匹配度来评分,擅长处理词汇匹配。
  • 优点:速度快、可解释性强、无需训练数据。
  • 缺点:无法解决词汇不匹配问题,即无法理解“电脑”和“计算机”是同一个意思。

现代方法:密集检索与混合检索

  • 密集检索理论:使用嵌入模型(如Sentence-BERT)将文本映射到高维向量空间。语义相似的文本,其向量在空间中的距离也更近。通过向量数据库(如Faiss) 进行高效的最近邻搜索(ANN)。
  • 优点:具备语义匹配 能力,克服了词汇不匹配的难题。
  • 混合检索理论:结合稀疏检索(BM25)和密集检索的优点。分别从两个索引中检索,然后使用重新排序(Re-ranking) 模型(如Cross-Encoder)对合并的结果进行精细打分,最终返回最优结果。这是一种“宽搜 + 精排”的策略,在保证召回率的同时极大提升了准确率。
  • RAG架构:将检索到的最相关知识片段作为上下文,与大语言模型的强大生成能力相结合,生成精准、可信且可追溯的答案,有效解决了大模型的幻觉问题。

2.2 案例演示

代码结构
"""
知识库问题生成与检索优化系统
基于BM25算法和Qwen大模型,实现知识库的智能化处理
主要功能:
1. 为知识内容自动生成多样化问题
2. 使用BM25算法实现高效检索
3. 比较原文检索与问题检索的性能差异
4. 支持多种知识主题的适配
"""

# 导入依赖库
import os  # 操作系统接口,用于环境变量和文件操作
import json  # JSON格式处理
import numpy as np  # 数值计算库
from openai import OpenAI  # OpenAI兼容API客户端
import pandas as pd  # 数据分析库
from datetime import datetime  # 日期时间处理
from rank_bm25 import BM25Okapi  # BM25算法实现
import jieba  # 中文分词库
import re  # 正则表达式库

# 从环境变量中获取 API Key
# 使用环境变量存储敏感信息,避免硬编码在代码中
DASHSCOPE_API_KEY = os.getenv('DASHSCOPE_API_KEY')

# 初始化百炼兼容的 OpenAI 客户端
# 配置API密钥和基础URL,使其兼容阿里云百炼平台
client = OpenAI(
    api_key=DASHSCOPE_API_KEY,  # 设置API密钥
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"  # 阿里云百炼兼容端点
)

# 预处理AI响应中的JSON格式
def preprocess_json_response(response):
    """
    预处理AI响应,移除markdown代码块格式
    确保从大模型获取的响应能够被正确解析为JSON格式
    
    参数:
        response (str): 从AI模型获取的原始响应文本
        
    返回:
        str: 清理后的JSON字符串
    """
    if not response:  # 检查响应是否为空
        return ""
    
    # 移除markdown代码块格式
    # 处理以```json或```开头的代码块标记
    if response.startswith('```json'):
        response = response[7:]  # 移除 ```json (7个字符)
    elif response.startswith('```'):
        response = response[3:]  # 移除 ``` (3个字符)
    
    # 处理结尾的代码块标记
    if response.endswith('```'):
        response = response[:-3]  # 移除结尾的 ```
    
    return response.strip()  # 移除首尾空白字符

# 基于 prompt 生成文本
def get_completion(prompt, model="qwen-turbo-latest"):
    """
    使用Qwen大模型生成文本完成
    
    参数:
        prompt (str): 输入提示文本
        model (str): 使用的模型名称,默认为"qwen-turbo-latest"
        
    返回:
        str: 模型生成的文本响应
    """
    # 构建消息格式,符合OpenAI API要求
    messages = [{"role": "user", "content": prompt}]
    
    # 调用API生成文本
    response = client.chat.completions.create(
        model=model,  # 指定模型
        messages=messages,  # 输入消息
        temperature=0.7,  # 控制生成随机性,0.7提供一定的创造性
    )
    
    # 返回生成的文本内容
    return response.choices[0].message.content

# 文本预处理和分词
def preprocess_text(text):
    """
    文本预处理和分词函数
    对输入文本进行清洗和分词,为BM25检索做准备
    
    参数:
        text (str): 待处理的文本
        
    返回:
        list: 分词后的词语列表
    """
    if not text:  # 检查文本是否为空
        return []
    
    # 移除标点符号和特殊字符,只保留文字、数字和空白字符
    text = re.sub(r'[^\w\s]', '', text)
    
    # 使用jieba进行中文分词
    words = jieba.lcut(text)
    
    # 定义停用词集合,过滤常见无意义词汇
    stop_words = {'的', '了', '在', '是', '我', '有', '和', '就', '不', '人', '都', '一', '一个', '上', '也', '很', '到', '说', '要', '去', '你', '会', '着', '没有', '看', '好', '自己', '这'}
    
    # 过滤停用词和短词(长度小于2的词)
    words = [word for word in words if len(word) > 1 and word not in stop_words]
    
    return words

class KnowledgeBaseOptimizer:
    """
    知识库优化器类
    核心类,实现知识库的问题生成、索引构建和检索功能
    """
    
    def __init__(self, model="qwen-turbo-latest"):
        """
        初始化知识库优化器
        
        参数:
            model (str): 使用的大模型名称
        """
        self.model = model  # 大模型名称
        self.knowledge_base = []  # 存储知识库内容
        self.content_bm25 = None  # 原文内容的BM25索引
        self.question_bm25 = None  # 生成问题的BM25索引
        self.content_documents = []  # 原文分词后的文档集合
        self.question_documents = []  # 问题分词后的文档集合
        self.content_metadata = []  # 原文元数据
        self.question_metadata = []  # 问题元数据
        
    def generate_questions_for_chunk(self, knowledge_chunk, num_questions=5):
        """
        为单个知识切片生成多样化问题
        
        参数:
            knowledge_chunk (str): 知识内容文本
            num_questions (int): 要生成的问题数量,默认为5
            
        返回:
            list: 生成的问题字典列表
        """
        # 指令模板,指导大模型生成多样化问题
        instruction = """
你是一个专业的问答系统专家。给定的知识内容能回答哪些多样化的问题,这些问题可以:
1. 使用不同的问法(直接问、间接问、对比问等)
2. 避免重复和相似的问题
3. 确保问题不超出知识内容范围

请返回JSON格式:
{
    "questions": [
        {
            "question": "问题内容",
            "question_type": "问题类型(直接问/间接问/对比问/条件问等)",
            "difficulty": "难度等级(简单/中等/困难)"
        }
    ]
}
"""
        
        # 构建提示词,包含指令、知识内容和生成数量
        prompt = f"""
### 指令 ###
{instruction}

### 知识内容 ###
{knowledge_chunk}

### 生成问题数量 ###
{num_questions}

### 生成结果 ###
"""
        
        # 调用大模型生成问题
        response = get_completion(prompt, self.model)
        
        # 预处理响应,移除markdown代码块格式
        response = preprocess_json_response(response)
        
        try:
            # 解析JSON响应
            result = json.loads(response)
            # 返回问题列表
            return result.get('questions', [])
        except json.JSONDecodeError as e:
            # JSON解析失败时的错误处理
            print(f"JSON解析失败: {e}")
            print(f"AI返回内容: {response[:50]}...")
            # 如果JSON解析失败,返回简单的问题列表
            return [{"question": f"关于{knowledge_chunk[:50]}...的问题", "question_type": "直接问", "keywords": [], "difficulty": "中等"}]
    
    def build_knowledge_index(self, knowledge_base):
        """
        构建知识库的BM25索引(包括原文和问题)
        
        参数:
            knowledge_base (list): 知识库内容列表
        """
        print("正在构建知识库索引...")
        
        self.knowledge_base = knowledge_base  # 存储知识库
        content_documents = []  # 初始化原文文档列表
        question_documents = []  # 初始化问题文档列表
        content_metadata = []  # 初始化原文元数据列表
        question_metadata = []  # 初始化问题元数据列表
        
        # 遍历知识库中的每个知识片段
        for i, chunk in enumerate(knowledge_base):
            # 获取知识切片的内容
            text = chunk.get('content', '')
            if not text.strip():  # 跳过空内容
                continue
                
            # 处理原文文档
            content_words = preprocess_text(text)  # 对原文进行分词处理
            if content_words:  # 如果有有效分词结果
                content_documents.append(content_words)  # 添加到原文文档列表
                # 存储原文元数据
                content_metadata.append({
                    "id": chunk.get('id', f"chunk_{i}"),  # 文档ID
                    "content": text,  # 原文内容
                    "category": chunk.get('category', ''),  # 分类信息
                    "chunk": chunk,  # 原始知识片段
                    "type": "content"  # 类型标记
                })
            
            # 处理问题文档(如果存在生成的问题)
            if 'generated_questions' in chunk and chunk['generated_questions']:
                # 遍历每个生成的问题
                for j, question_data in enumerate(chunk['generated_questions']):
                    question = question_data.get('question', '')
                    if question.strip():  # 跳过空问题
                        # 拼接全文和问题,保持上下文
                        combined_text = f"内容:{text} 问题:{question}"
                        # 对组合文本进行分词
                        question_words = preprocess_text(combined_text)
                        
                        if question_words:  # 如果有有效分词结果
                            question_documents.append(question_words)  # 添加到问题文档列表
                            # 存储问题元数据
                            question_metadata.append({
                                "id": f"{chunk.get('id', f'chunk_{i}')}_q{j}",  # 问题ID
                                "content": question,  # 问题内容
                                "combined_content": combined_text,  # 组合内容
                                "category": chunk.get('category', ''),  # 分类信息
                                "chunk": chunk,  # 原始知识片段
                                "type": "question",  # 类型标记
                                "question_data": question_data  # 问题数据
                            })
        
        # 创建BM25索引 - 原文索引
        if content_documents:
            self.content_bm25 = BM25Okapi(content_documents)  # 创建BM25索引
            self.content_documents = content_documents  # 存储原文文档
            self.content_metadata = content_metadata  # 存储原文元数据
            print(f"原文索引构建完成,共索引 {len(content_documents)} 个知识切片")
        
        # 创建BM25索引 - 问题索引
        if question_documents:
            self.question_bm25 = BM25Okapi(question_documents)  # 创建BM25索引
            self.question_documents = question_documents  # 存储问题文档
            self.question_metadata = question_metadata  # 存储问题元数据
            print(f"问题索引构建完成,共索引 {len(question_documents)} 个问题")
        
        # 检查是否有有效内容
        if not content_documents and not question_documents:
            print("没有有效的内容可以索引")
    
    def search_similar_chunks(self, query, k=3, search_type="content"):
        """
        使用BM25搜索相似的内容(原文或问题)
        
        参数:
            query (str): 查询文本
            k (int): 返回结果数量,默认为3
            search_type (str): 搜索类型,"content"或"question"
            
        返回:
            list: 相似内容的结果列表
        """
        # 根据搜索类型选择相应的索引和元数据
        if search_type == "content":
            if not self.content_bm25:  # 检查索引是否存在
                return []
            bm25 = self.content_bm25  # 原文BM25索引
            metadata_store = self.content_metadata  # 原文元数据
        elif search_type == "question":
            if not self.question_bm25:  # 检查索引是否存在
                return []
            bm25 = self.question_bm25  # 问题BM25索引
            metadata_store = self.question_metadata  # 问题元数据
        else:
            return []  # 无效的搜索类型
        
        try:
            # 预处理查询文本
            query_words = preprocess_text(query)
            if not query_words:  # 检查是否有有效分词
                return []
            
            # 使用BM25计算相似度分数
            scores = bm25.get_scores(query_words)
            
            # 获取top-k结果的索引(按分数降序排列)
            top_indices = np.argsort(scores)[::-1][:k]
            
            results = []  # 初始化结果列表
            for idx in top_indices:
                if scores[idx] > 0:  # 只返回有相关性的结果(分数>0)
                    metadata = metadata_store[idx]  # 获取元数据
                    # 将BM25分数转换为0-1范围的相似度(归一化)
                    similarity = min(1.0, scores[idx] / 10.0)
                    # 添加结果到列表
                    results.append({
                        "metadata": metadata,  # 元数据
                        "score": scores[idx],  # 原始分数
                        "similarity": similarity  # 归一化相似度
                    })
            
            return results
            
        except Exception as e:
            # 异常处理
            print(f"搜索失败: {e}")
            return []
    
    def calculate_similarity(self, query, knowledge_chunk):
        """
        计算查询与知识切片的相似度(使用BM25)
        
        参数:
            query (str): 查询文本
            knowledge_chunk (str): 知识内容文本
            
        返回:
            float: 相似度分数(0-1范围)
        """
        try:
            # 预处理查询和知识内容
            query_words = preprocess_text(query)
            chunk_words = preprocess_text(knowledge_chunk)
            
            if not query_words or not chunk_words:  # 检查是否有有效分词
                return 0.0
            
            # 创建临时BM25索引(仅包含知识内容)
            temp_bm25 = BM25Okapi([chunk_words])
            # 计算查询与知识内容的相似度分数
            scores = temp_bm25.get_scores(query_words)
            
            # 返回最高分数并归一化
            max_score = max(scores) if scores else 0.0
            return min(1.0, max_score / 10.0)
            
        except Exception as e:
            # 异常处理
            print(f"相似度计算失败: {e}")
            return 0.0
    
    def calculate_question_similarity(self, user_query, generated_questions):
        """
        计算用户查询与生成问题的相似度
        
        参数:
            user_query (str): 用户查询文本
            generated_questions (list): 生成的问题列表
            
        返回:
            float: 最大相似度分数
        """
        similarities = []  # 初始化相似度列表
        # 计算用户查询与每个生成问题的相似度
        for question_data in generated_questions:
            question = question_data['question']  # 获取问题文本
            similarity = self.calculate_similarity(user_query, question)  # 计算相似度
            similarities.append(similarity)  # 添加到列表
        
        # 返回最大相似度
        return max(similarities) if similarities else 0.0
    
    def evaluate_retrieval_methods(self, knowledge_base, test_queries):
        """
        评估两种检索方法的准确度
        
        参数:
            knowledge_base (list): 知识库内容列表
            test_queries (list): 测试查询列表
            
        返回:
            dict: 评估结果字典
        """
        # 首先构建知识库索引(包括原文和问题)
        self.build_knowledge_index(knowledge_base)
        
        # 初始化结果字典
        results = {
            'content_similarity': [],  # 原文检索正确性
            'question_similarity': [],  # 问题检索正确性
            'improvement': [],  # 问题检索是否改进
            'content_scores': [],  # 原文检索分数
            'question_scores': [],  # 问题检索分数
            'query_details': []  # 详细查询信息
        }
        
        # 遍历测试查询
        for i, query_info in enumerate(test_queries):
            user_query = query_info['query']  # 获取查询文本
            correct_chunk = query_info['correct_chunk']  # 获取正确答案对应的知识片段
            
            # 方法1:BM25原文检索
            content_results = self.search_similar_chunks(user_query, k=1, search_type="content")
            content_correct = False  # 初始化正确性标志
            content_score = 0.0  # 初始化分数
            content_chunk_id = None  # 初始化知识片段ID
            
            if content_results:  # 如果有检索结果
                best_match = content_results[0]['metadata']['chunk']  # 获取最佳匹配
                # 检查是否匹配正确答案
                content_correct = best_match['content'] == correct_chunk
                content_score = content_results[0]['similarity']  # 获取相似度分数
                content_chunk_id = best_match['id']  # 获取知识片段ID
            
            # 方法2:BM25问题检索
            question_results = self.search_similar_chunks(user_query, k=1, search_type="question")
            question_correct = False  # 初始化正确性标志
            question_score = 0.0  # 初始化分数
            question_chunk_id = None  # 初始化知识片段ID
            
            if question_results:  # 如果有检索结果
                best_match = question_results[0]['metadata']['chunk']  # 获取最佳匹配
                # 检查是否匹配正确答案
                question_correct = best_match['content'] == correct_chunk
                question_score = question_results[0]['similarity']  # 获取相似度分数
                question_chunk_id = best_match['id']  # 获取知识片段ID
            
            # 记录结果
            results['content_similarity'].append(content_correct)
            results['question_similarity'].append(question_correct)
            results['improvement'].append(question_correct and not content_correct)  # 问题检索是否改进
            results['content_scores'].append(content_score)
            results['question_scores'].append(question_score)
            
            # 记录查询详情
            results['query_details'].append({
                'query': user_query,  # 查询文本
                'content_score': content_score,  # 原文检索分数
                'question_score': question_score,  # 问题检索分数
                'content_correct': content_correct,  # 原文检索是否正确
                'question_correct': question_correct,  # 问题检索是否正确
                'score_diff': question_score - content_score,  # 分数差异
                'content_chunk_id': content_chunk_id,  # 原文检索匹配的知识ID
                'question_chunk_id': question_chunk_id  # 问题检索匹配的知识ID
            })
        
        return results  # 返回评估结果
    
    def generate_diverse_questions(self, knowledge_chunk, num_questions=8):
        """
        生成更多样化的问题(更丰富)
        
        参数:
            knowledge_chunk (str): 知识内容文本
            num_questions (int): 要生成的问题数量,默认为8
            
        返回:
            list: 生成的问题字典列表
        """
        # 指令模板,指导大模型生成更多样化的问题
        instruction = """
你是一个专业的问答系统专家。请为给定的知识内容生成高度多样化的问题,确保:
1. 问题类型多样化:直接问、间接问、对比问、条件问、假设问、推理问等
2. 表达方式多样化:使用不同的句式、词汇、语气
3. 难度层次多样化:简单、中等、困难的问题都要有
4. 角度多样化:从不同角度和维度提问
5. 确保问题不超出知识内容范围

请返回JSON格式:
{
    "questions": [
        {
            "question": "问题内容",
            "question_type": "问题类型",
            "difficulty": "难度等级",
            "perspective": "提问角度",
            "is_answerable": "给出的知识能否回答该问题",
            "answer": "基于该知识的回答"
        }
    ]
}
"""
        
        # 构建提示词
        prompt = f"""
### 指令 ###
{instruction}

### 知识内容 ###
{knowledge_chunk}

### 生成问题数量 ###
{num_questions}

### 生成结果 ###
"""
        
        # 调用大模型生成问题
        response = get_completion(prompt, self.model)
        
        # 预处理响应,移除markdown代码块格式
        response = preprocess_json_response(response)
        
        try:
            # 解析JSON响应
            result = json.loads(response)
            # 返回问题列表
            return result.get('questions', [])
        except json.JSONDecodeError as e:
            # JSON解析失败时的错误处理
            print(f"多样化问题生成JSON解析失败: {e}")
            print(f"AI返回内容: {response[:200]}...")
            return []

def main():
    """
    主函数 - 演示知识库优化器的使用
    """
    # 初始化知识库优化器
    optimizer = KnowledgeBaseOptimizer()
    
    print("=== 知识库问题生成与检索优化示例(BM25版本)- 饮食与健康 ===\n")
    
    # 示例知识库 - 饮食与健康相关信息
    knowledge_base = [
        {
            "id": "kb_001",
            "content": "每天饮用足够的水对维持身体健康至关重要。成年人每天应饮用约2升水,相当于8杯水。充足的水分摄入有助于新陈代谢、排毒和保持皮肤健康。",
            "category": "健康饮水"
        },
        {
            "id": "kb_002", 
            "content": "均衡饮食应包含五大类食物:谷物、蔬菜、水果、蛋白质和乳制品。建议每天摄入5份不同颜色的蔬菜和水果,以确保获得各种维生素和矿物质。",
            "category": "营养饮食"
        },
        {
            "id": "kb_003",
            "content": "成年人每周应进行至少150分钟的中等强度有氧运动,如快走、游泳或骑自行车,或75分钟的高强度有氧运动。此外,每周还应进行2次肌肉强化活动。",
            "category": "运动健身"
        },
        {
            "id": "kb_004",
            "content": "成年人每天需要7-9小时的睡眠。良好的睡眠习惯包括保持固定的睡眠时间、创造舒适的睡眠环境、避免睡前使用电子设备以及限制咖啡因和酒精的摄入。",
            "category": "睡眠健康"
        }
    ]
    
    # 示例1: 为知识切片生成问题
    print("示例1: 为知识切片生成多样化问题")
    test_chunk = knowledge_base[0]['content']  # 获取第一个知识片段
    print(f"知识内容: {test_chunk}")
    
    # 生成5个问题
    questions = optimizer.generate_questions_for_chunk(test_chunk, num_questions=5)
    print(f"\n生成的5个问题:")
    for i, q in enumerate(questions, 1):
        print(f"  {i}. {q['question']} (类型: {q['question_type']}, 难度: {q['difficulty']})")
    
    print("\n" + "="*60 + "\n")
    
    # 示例2: 生成更多样化的问题
    print("示例2: 生成更多样化的问题(8个)")
    # 生成8个更多样化的问题
    diverse_questions = optimizer.generate_diverse_questions(test_chunk, num_questions=8)
    print(f"\n生成的8个多样化问题:")
    for i, q in enumerate(diverse_questions, 1):
        print(f"  {i}. {q['question']}")
        print(f"     类型: {q['question_type']}, 难度: {q['difficulty']}, 角度: {q['perspective']}, 能否回答: {q['is_answerable']}, 回答的答案:{q['answer']}")
    
    print("\n" + "="*60 + "\n")
    
    # 示例3: 评估检索方法
    print("示例3: 评估两种检索方法的准确度")
    
    # 测试查询 - 设计更有挑战性的问题
    test_queries = [
        {
            "query": "每天应该喝多少水?",
            "correct_chunk": knowledge_base[0]['content']
        },
        {
            "query": "什么是均衡饮食?",
            "correct_chunk": knowledge_base[1]['content']
        },
        {
            "query": "每周需要运动多久?",
            "correct_chunk": knowledge_base[2]['content']
        }
    ]
    
    # 为知识库生成问题
    print('正在为知识库生成问题...')
    for chunk in knowledge_base:
        # 为每个知识片段生成问题
        chunk['generated_questions'] = optimizer.generate_questions_for_chunk(chunk['content'])
    print('为知识库生成问题完毕')
    
    # 评估检索方法
    results = optimizer.evaluate_retrieval_methods(knowledge_base, test_queries)
    
    # 输出评估结果
    print(f"测试查询数量: {len(test_queries)}")
    print(f"BM25原文检索准确率: {sum(results['content_similarity'])/len(results['content_similarity'])*100:.1f}%")
    print(f"BM25问题检索准确率: {sum(results['question_similarity'])/len(results['question_similarity'])*100:.1f}%")
    print(f"问题检索改进的查询数量: {sum(results['improvement'])}")
    
    # 详细分析
    print(f"\n=== 详细分析 ===")
    
    # 按相似度分数差异排序
    sorted_details = sorted(results['query_details'], key=lambda x: x['score_diff'], reverse=True)
    
    print(f"\n问题检索方法表现更好的查询(按分数差异排序):")
    for i, detail in enumerate(sorted_details[:5], 1):
        if detail['score_diff'] > 0:
            print(f"  {i}. 查询: {detail['query']}")
            print(f"     原文检索分数: {detail['content_score']:.3f}")
            print(f"     问题检索分数: {detail['question_score']:.3f}")
            print(f"     分数差异: +{detail['score_diff']:.3f}")
            print(f"     原文检索: {'✓' if detail['content_correct'] else '✗'}")
            print(f"     问题检索: {'✓' if detail['question_correct'] else '✗'}")
    
    print(f"\n原文检索方法表现更好的查询:")
    for i, detail in enumerate(sorted_details[-5:], 1):
        if detail['score_diff'] < 0:
            print(f"  {i}. 查询: {detail['query']}")
            print(f"     原文检索分数: {detail['content_score']:.3f}")
            print(f"     问题检索分数: {detail['question_score']:.3f}")
            print(f"     分数差异: {detail['score_diff']:.3f}")
            print(f"     原文检索: {'✓' if detail['content_correct'] else '✗'}")
            print(f"     问题检索: {'✓' if detail['question_correct'] else '✗'}")

# 程序入口点
if __name__ == "__main__":
    main()  # 执行主函数
执行结果
=== 知识库问题生成与检索优化示例(BM25版本)- 饮食与健康 ===

示例1: 为知识切片生成多样化问题
知识内容: 每天饮用足够的水对维持身体健康至关重要。成年人每天应饮用约2升水,相当于8杯水。充足的水分摄入有助于新陈代谢
、排毒和保持皮肤健康。

生成的5个问题:
  1. 成年人每天应该喝多少水? (类型: 直接问, 难度: 简单)
  2. 为什么保持水分摄入对身体很重要? (类型: 间接问, 难度: 中等)
  3. 如果一个人每天只喝1升水,会对健康产生什么影响? (类型: 条件问, 难度: 中等) 
  4. 喝足够的水和皮肤健康之间有什么关系? (类型: 对比问, 难度: 简单)
  5. 除了排毒之外,充足饮水还能帮助身体实现哪些功能? (类型: 间接问, 难度: 中等)

============================================================

示例2: 生成更多样化的问题(8个)

生成的8个多样化问题:
  1. 成年人每天应该喝多少水?
     类型: 直接问, 难度: 简单, 角度: 事实确认, 能否回答: True, 回答的答案:成年人每天应饮用约2升水,相当于8杯水。    
  2. 如果一个人不喝够水,可能会出现什么健康问题?
     类型: 推理问, 难度: 中等, 角度: 后果分析, 能否回答: True, 回答的答案:缺乏足够水分可能导致新陈代谢减慢、排毒功能
下降和皮肤健康受损。
  3. 为什么说喝水对皮肤好?
     类型: 间接问, 难度: 简单, 角度: 机制解释, 能否回答: True, 回答的答案:充足的水分摄入有助于保持皮肤健康。        
  4. 假设一个人只喝1升水,是否还能维持正常的新陈代谢?
     类型: 假设问, 难度: 困难, 角度: 条件推演, 能否回答: True, 回答的答案:可能无法维持正常的新陈代谢,因为知识指出充
足水分对新陈代谢至关重要。
  5. 每天喝8杯水和喝2升水是同一个意思吗?
     类型: 对比问, 难度: 简单, 角度: 单位换算, 能否回答: True, 回答的答案:是的,2升水相当于8杯水。
  6. 有没有可能比2升更多水才更有利于健康?
     类型: 条件问, 难度: 中等, 角度: 优化建议, 能否回答: True, 回答的答案:知识未提及超过2升是否更有益,因此无法判断 
,但说明2升是推荐量。
  7. 从科学角度看,喝水对身体的哪些系统有帮助?
     类型: 推理问, 难度: 困难, 角度: 生理机制, 能否回答: True, 回答的答案:喝水有助于新陈代谢(消化/能量系统)、排毒 
(泌尿/肝脏系统)和皮肤健康(表皮系统)。
  8. 如果某人每天都喝足2升水,他是不是就一定健康?
     类型: 假设问, 难度: 中等, 角度: 因果关系辨析, 能否回答: True, 回答的答案:不一定,虽然饮水充足是健康的重要因素,
但身体健康还取决于其他多种因素如饮食、运动等。

============================================================

示例3: 评估两种检索方法的准确度
正在为知识库生成问题...
为知识库生成问题完毕
正在构建知识库索引...
Building prefix dict from the default dictionary ...
Loading model from cache C:\Users\du\AppData\Local\Temp\jieba.cache
Loading model cost 0.557 seconds.
Prefix dict has been built successfully.
原文索引构建完成,共索引 4 个知识切片
问题索引构建完成,共索引 20 个问题
测试查询数量: 3
BM25原文检索准确率: 100.0%
BM25问题检索准确率: 100.0%
问题检索改进的查询数量: 0

=== 详细分析 ===

问题检索方法表现更好的查询(按分数差异排序):
  1. 查询: 每天应该喝多少水?
     原文检索分数: 0.028
     问题检索分数: 0.410
     分数差异: +0.381
     原文检索: ✓
     问题检索: ✓
  2. 查询: 什么是均衡饮食?
     原文检索分数: 0.178
     问题检索分数: 0.450
     分数差异: +0.272
     原文检索: ✓
     问题检索: ✓
  3. 查询: 每周需要运动多久?
     原文检索分数: 0.237
     问题检索分数: 0.417
     分数差异: +0.179
     原文检索: ✓
     问题检索: ✓

原文检索方法表现更好的查询:
实现功能
  • 知识库问题生成:使用Qwen大模型为知识内容自动生成多样化的问题
  • BM25索引构建:为知识库的原文和生成的问题分别构建BM25索引
  • 检索功能:支持基于原文和基于问题的两种检索方式计算出检索分数
  • 性能评估:比较两种检索方法的准确度和效果差异
  • 多样化问题生成:生成更多样化、多角度的问题
扩展介绍:BM25检索方法
  • BM25原文检索:
  1. 检索对象:知识库中的原始内容片段,即 knowledge_base[i]['content']。
  2. 过程:使用BM25算法将用户的查询直接与这些原始内容进行关键词匹配和相似度计算,然后返回最相似的原始内容片段。
  3. 类比:像是在一整本书的正文里搜索与你问题相关的段落。
  4. 优点:直接,没有中间转换,直接匹配内容。覆盖全,可以匹配到答案中任何出现的关键词。
  5. 缺点:词汇不匹配,如果用户的问法和原文表述差异很大,就可能检索失败。由于关键词不匹配,BM25可能无法建立有效关联,导致检索不到或排名很低。
  • BM25问题检索:
  1. 检索对象:为每个知识块预先生成的一系列问题,即 knowledge_base[i]['generated_questions'][j]['question']。
  2. 过程:将用户的查询与这些预先生成的问题进行匹配。如果找到相似的问题,就返回该问题所对应的那个原始知识块。
  3. 类比:像是在一本书末尾的索引或常见问题清单里搜索。你先找到一个和你提问方式很像的标准问题,然后根据这个标准问题去翻到它对应的答案页码。
  4. 优点:解决词汇不匹配,极大地丰富了问法的多样性,用户的自然语言提问更容易与某个生成的问题匹配上。更符合用户习惯检索的是“问题”,匹配的是“问题”,更贴近用户的意图。
  5. 缺点:依赖生成问题的质量,如果AI生成的问题不好、不全面或不准确,会直接导致检索失败。增加预处理步骤,需要额外消耗资源(API调用、计算时间)来为所有知识块生成问题。
  • 准确率计算:
test_queries = [
    {
        "query": "可以带食物进去吗?", # 用户查询
        "correct_chunk": knowledge_base[5]['content'] # 唯一正确的知识块内容
    },
    # ... 其他测试用例
]

        在代码的评估部分 (evaluate_retrieval_methods函数),有一个测试集 test_queries。每个测试用例都明确指定了哪个知识块是正确答案。

原文检索准确率:系统用BM25原文检索返回的 top-1 结果,即它认为最相关的那个知识块,其内容是否等于 correct_chunk?如果是,则这个查询上原文检索“准确”,否则“不准确”。

        准确次数 / 总查询次数 = 原文检索准确率

问题检索准确率:系统用BM25问题检索返回的 top-1 结果所对应的那个知识块,其内容是否等于 correct_chunk?如果是,则这个查询上问题检索“准确”;否则“不准确”。

        准确次数 / 总查询次数 = 问题检索准确率

BM25原文检索准确率:衡量系统直接通过关键词匹配找到正确答案的能力。

BM25问题检索准确率:衡量系统通过“问题桥接”的方式找到正确答案的能力。这种方法的核心价值在于通过扩展问法来提升在词汇不匹配场景下的检索成功率。

五、对话知识沉淀:从交互中挖掘隐性知识

1. 基础介绍        

        用户与客服、助理的对话是未被开发的知识金矿。对话知识沉淀旨在自动化地完成“挖矿”和“提炼”过程。

  • 理论核心:持续学习和闭环反馈。
  • 技术流程:
    • 识别:利用模型自动识别对话中的“知识价值点”。例如:
      • 未命中:模型未能回答的新问题。
      • 新答案:针对已知问题,用户或专家提供了更优的答案。
      • 知识确认:用户对现有答案的正面/负面反馈。
    • 抽取:对于有价值的对话,使用大模型进行摘要总结和结构化抽取,将其转化为标准的Q-A对或其他知识形态。
    • 审核与入库:抽取的结果经过人工或自动化规则审核后,方可并入正式知识库,确保质量。    
  • 价值:使知识库成为一个能够从真实使用场景中学习并成长的有机体,实现了数据驱动的自我优化。

2. 案例演示

代码结构

# 对话知识提取与沉淀
# 导入依赖库
import dashscope
import os
import json
from datetime import datetime
from collections import Counter

# 从环境变量中获取 API Key
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')

# 预处理AI响应中的JSON格式
def preprocess_json_response(response):
    """预处理AI响应,移除markdown代码块格式"""
    if not response:
        return ""
    
    # 移除markdown代码块格式
    if response.startswith('```json'):
        response = response[7:]  # 移除 ```json
    elif response.startswith('```'):
        response = response[3:]  # 移除 ```
    
    if response.endswith('```'):
        response = response[:-3]  # 移除结尾的 ```
    
    return response.strip()  # 移除首尾空白

# 基于 prompt 生成文本
def get_completion(prompt, model="qwen-turbo-latest"):
    messages = [{"role": "user", "content": prompt}]
    response = dashscope.Generation.call(
        model=model,
        messages=messages,
        result_format='message',
        temperature=0.3,
    )
    return response.output.choices[0].message.content

class ConversationKnowledgeExtractor:
    def __init__(self, model="qwen-turbo-latest"):
        self.model = model
        self.extracted_knowledge = []
        self.knowledge_frequency = Counter()
        
    def extract_knowledge_from_conversation(self, conversation):
        """从单次对话中提取知识"""
        instruction = """
你是一个专业的知识提取专家。请从给定的对话中提取有价值的知识点,包括:
1. 事实性信息(地点、时间、价格、规则等)
2. 用户需求和偏好
3. 常见问题和解答
4. 操作流程和步骤
5. 注意事项和提醒

请返回JSON格式:
{
    "extracted_knowledge": [
        {
            "knowledge_type": "知识类型(事实/需求/问题/流程/注意)",
            "content": "知识内容",
            "confidence": "置信度(0-1)",
            "source": "来源(用户/AI/对话)",
            "keywords": ["关键词1", "关键词2"],
            "category": "分类"
        }
    ],
    "conversation_summary": "对话摘要",
    "user_intent": "用户意图"
}
"""
        
        prompt = f"""
### 指令 ###
{instruction}

### 对话内容 ###
{conversation}

### 提取结果 ###
"""
        
        response = get_completion(prompt, self.model)
        
        # 预处理响应,移除markdown代码块格式
        response = preprocess_json_response(response)
        
        try:
            result = json.loads(response)
            return result
        except json.JSONDecodeError as e:
            print(f"对话知识提取JSON解析失败: {e}")
            print(f"AI返回内容: {response[:200]}...")
            return {
                "extracted_knowledge": [],
                "conversation_summary": "无法解析对话",
                "user_intent": "未知"
            }
    
    def batch_extract_knowledge(self, conversations):
        """批量提取知识"""
        all_knowledge = []
        
        for i, conversation in enumerate(conversations):
            print(f"正在处理对话 {i+1}/{len(conversations)}...")
            
            result = self.extract_knowledge_from_conversation(conversation)
            all_knowledge.extend(result.get('extracted_knowledge', []))
            
            # 更新频率统计
            for knowledge in result.get('extracted_knowledge', []):
                key = f"{knowledge['knowledge_type']}:{knowledge['content'][:50]}"
                self.knowledge_frequency[key] += 1
        
        return all_knowledge
    
    def merge_similar_knowledge(self, knowledge_list):
        """使用LLM合并相似的知识点,过滤掉需求和问题类型"""
        # 过滤掉需求和问题类型的知识,因为它们是临时的、个性化的
        filtered_knowledge = [
            knowledge for knowledge in knowledge_list 
            if knowledge.get('knowledge_type') not in ['需求', '问题']
        ]
        
        print(f"过滤前知识点数量: {len(knowledge_list)}")
        print(f"过滤后知识点数量: {len(filtered_knowledge)}")
        print(f"过滤掉的'需求'和'问题'类型知识点: {len(knowledge_list) - len(filtered_knowledge)}")
        
        # 按知识类型分组
        knowledge_by_type = {}
        for knowledge in filtered_knowledge:
            knowledge_type = knowledge.get('knowledge_type', '其他')
            if knowledge_type not in knowledge_by_type:
                knowledge_by_type[knowledge_type] = []
            knowledge_by_type[knowledge_type].append(knowledge)
        
        merged_knowledge = []
        
        # 对每个知识类型分别进行LLM合并
        for knowledge_type, knowledge_group in knowledge_by_type.items():
            if len(knowledge_group) == 1:
                # 只有一个知识点,直接添加
                merged_knowledge.append(knowledge_group[0])
            else:
                # 多个知识点,使用LLM合并
                merged = self.merge_knowledge_with_llm(knowledge_group, knowledge_type)
                merged_knowledge.append(merged)
        
        return merged_knowledge
    
    def merge_knowledge_with_llm(self, knowledge_group, knowledge_type):
        """使用LLM合并同类型的知识组"""
        # 准备知识内容列表
        knowledge_contents = []
        all_keywords = set()
        all_sources = []
        
        for i, knowledge in enumerate(knowledge_group, 1):
            content = knowledge.get('content', '')
            confidence = knowledge.get('confidence', 0.5)
            keywords = knowledge.get('keywords', [])
            source = knowledge.get('source', '')
            category = knowledge.get('category', '')
            
            knowledge_contents.append(f"{i}. 内容: {content}")
            knowledge_contents.append(f"   置信度: {confidence}")
            knowledge_contents.append(f"   分类: {category}")
            knowledge_contents.append(f"   来源: {source}")
            knowledge_contents.append(f"   关键词: {', '.join(keywords)}")
            knowledge_contents.append("")
            
            all_keywords.update(keywords)
            if source and source not in all_sources:
                all_sources.append(source)
        
        # 构建LLM合并提示
        prompt = f"""
你是一个专业的知识整理专家。请将以下{knowledge_type}类型的知识点进行智能合并,生成一个更完整、准确的知识点。

### 合并要求:
1. 保留所有重要信息,避免信息丢失
2. 消除重复内容,整合相似表述
3. 提高内容的准确性和完整性
4. 保持逻辑清晰,结构合理
5. 合并后的置信度取所有知识点中的最高值

### 待合并的知识点:
{chr(10).join(knowledge_contents)}

### 请返回JSON格式:
{{
    "knowledge_type": "{knowledge_type}",
    "content": "合并后的知识内容",
    "confidence": 最高置信度值,
    "keywords": ["合并后的关键词列表"],
    "category": "合并后的分类",
    "sources": ["所有来源"],
    "frequency": {len(knowledge_group)}
}}

### 合并结果:
"""
        
        response = get_completion(prompt, self.model)
        
        # 预处理响应
        response = preprocess_json_response(response)
        
        try:
            result = json.loads(response)
            return result
        except json.JSONDecodeError as e:
            print(f"知识合并JSON解析失败: {e}")
            print(f"AI返回内容: {response[:200]}...")
            
            # 解析失败时,使用简单的合并策略
            best_knowledge = max(knowledge_group, key=lambda x: x.get('confidence', 0))
            return {
                "knowledge_type": knowledge_type,
                "content": best_knowledge['content'],
                "confidence": best_knowledge.get('confidence', 0.5),
                "frequency": len(knowledge_group),
                "keywords": list(all_keywords),
                "category": best_knowledge['category'],
                "sources": all_sources
            }
def main():
    # 初始化对话知识提取器
    extractor = ConversationKnowledgeExtractor()
    
    print("=== 对话知识提取与沉淀示例(健康健身与营养咨询) ===\n")
    
    # 健康健身主题的示例对话数据
    sample_conversations = [
        # 对话1: 减脂咨询
        """
用户: "我想减脂,应该怎么安排运动和饮食?"
AI: "减脂需要创造热量赤字,建议每周进行3-5次有氧运动(如跑步、游泳、骑行)和2-3次力量训练。饮食上控制总热量摄入,增加蛋白质比例,减少精制碳水和添加糖。"
用户: "有氧运动做多久有效果?"
AI: "有氧运动建议每次30-60分钟,保持中等强度(心率在最大心率的60-70%)。最好结合高强度间歇训练(HIIT)和稳态有氧(LISS)交替进行,效果更佳。"
用户: "减脂期间蛋白质吃多少合适?"
AI: "减脂期间建议每日蛋白质摄入量为每公斤体重1.6-2.2克。优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉。"
""",
        # 对话2: 增肌咨询
        """
用户: "我想增加肌肉量,应该怎么训练和吃?"
AI: "增肌需要渐进式超负荷训练和热量盈余。建议每周进行3-5次力量训练,专注复合动作如深蹲、卧推、硬拉和引体向上。饮食上每日热量盈余300-500卡路里,蛋白质摄入每公斤体重1.6-2.2克。"
用户: "训练后需要立即补充蛋白质吗?"
AI: "训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,配合快速吸收的碳水化合物,有助于肌肉恢复和合成。乳清蛋白粉是方便的选择。"
用户: "增肌需要做有氧运动吗?"
AI: "增肌期间可以适量进行有氧运动,每周2-3次,每次20-30分钟低强度有氧,有助于保持心肺健康和代谢功能,但不要过量以免影响力量训练恢复。"
""",
        # 对话3: 健康饮食咨询
        """
用户: "什么样的饮食算健康均衡?"
AI: "健康均衡饮食应包含多样化的食物:大量蔬菜和水果、优质蛋白质来源、全谷物碳水化合物、健康脂肪以及充足的水分。遵循'盘子法则':一半盘子放蔬菜,1/4放蛋白质,1/4放全谷物。"
用户: "减脂期晚上可以吃碳水吗?"
AI: "减脂期晚上可以适量摄入复合碳水化合物,如糙米、燕麦、红薯等,但需控制总量并避免在临睡前大量摄入。个体差异较大,建议根据自身代谢情况和训练安排调整。"
用户: "健身补剂有必要吗?哪些比较推荐?"
AI: "健身补剂不是必需品,但可以辅助训练效果。基础补剂包括乳清蛋白粉、肌酸和Omega-3脂肪酸。维生素D和镁也可能对运动表现和恢复有益。选择补剂前最好咨询专业人士。"
""",
        # 对话4: 运动损伤预防
        """
用户: "如何预防健身时的运动损伤?"
AI: "预防运动损伤的关键包括:充分热身5-10分钟、循序渐进增加负荷、保持正确动作形式、合理安排训练和休息、以及运动后的拉伸和恢复。倾听身体信号,避免过度训练。"
用户: "肩膀疼痛还能继续训练吗?"
AI: "如果出现持续性肩膀疼痛,应停止加重疼痛的训练动作,并咨询医生或物理治疗师。可以暂时进行不引起疼痛的其他部位训练,但避免强行训练疼痛部位。"
用户: "运动后如何加速恢复?"
AI: "运动后恢复包括:适当营养补充(蛋白质和碳水)、充足水分、7-9小时高质量睡眠、主动恢复(如散步、瑜伽)、拉伸和泡沫轴放松,以及必要时使用冰敷或热敷。"
"""
    ]
    
    # 示例1: 从单次对话中提取知识
    print("示例1: 从单次对话中提取知识")
    conversation = sample_conversations[0]
    print(f"对话内容:\n{conversation}")
    
    extracted = extractor.extract_knowledge_from_conversation(conversation)
    print(f"\n提取的知识点:")
    for i, knowledge in enumerate(extracted['extracted_knowledge'], 1):
        print(f"  {i}. 类型: {knowledge['knowledge_type']}")
        print(f"     内容: {knowledge['content']}")
        print(f"     置信度: {knowledge['confidence']}")
        print(f"     分类: {knowledge['category']}")
    
    print(f"\n对话摘要: {extracted['conversation_summary']}")
    print(f"用户意图: {extracted['user_intent']}")
    
    print("\n" + "="*60 + "\n")
    
    # 示例2: 批量提取知识
    print("示例2: 批量提取知识")
    all_knowledge = extractor.batch_extract_knowledge(sample_conversations)
    print(f"总共提取了 {len(all_knowledge)} 个知识点")
    
    # 显示所有知识点
    print(f"\n所有知识点:")
    for key, count in extractor.knowledge_frequency.most_common():
        print(f"  {key}: {count}次")
    
    print("\n" + "="*60 + "\n")
    
    
    # 示例3: 合并相似知识
    print("示例3: 合并相似知识")
    merged_knowledge = extractor.merge_similar_knowledge(all_knowledge)
    print(f"合并后剩余 {len(merged_knowledge)} 个知识点")
    
    print(f"\n合并后的知识点:")
    for i, knowledge in enumerate(merged_knowledge, 1):
        print(f"  {i}. 类型: {knowledge.get('knowledge_type', '未知')}")
        print(f"     内容: {knowledge['content']}")
        print(f"     频率: {knowledge.get('frequency', 1)}次")
        print(f"     置信度: {knowledge.get('confidence', 0.5)}")
        print(f"     分类: {knowledge.get('category', '未知')}")
        print(f"     关键词: {knowledge.get('keywords', [])}")
        print(f"     来源: {knowledge.get('sources', [])}")
        print()
    
    print("\n" + "="*60 + "\n")    

if __name__ == "__main__":
    main() 

执行结果

=== 对话知识提取与沉淀示例(健康健身与营养咨询) ===

示例1: 从单次对话中提取知识
对话内容:

用户: "我想减脂,应该怎么安排运动和饮食?"
AI: "减脂需要创造热量赤字,建议每周进行3-5次有氧运动(如跑步、游泳、骑行)和2-3次力量训练。饮食上控制总热量摄入,增加
蛋白质比例,减少精制碳水和添加糖。"
用户: "有氧运动做多久有效果?"
AI: "有氧运动建议每次30-60分钟,保持中等强度(心率在最大心率的60-70%)。最好结合高强度间歇训练(HIIT)和稳态有氧(LISS) 
交替进行,效果更佳。"
用户: "减脂期间蛋白质吃多少合适?"
AI: "减脂期间建议每日蛋白质摄入量为每公斤体重1.6-2.2克。优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉。"      


提取的知识点:
  1. 类型: 流程
     内容: 减脂需结合运动与饮食:每周3-5次有氧运动(如跑步、游泳、骑行)和2-3次力量训练;饮食上控制总热量,增加蛋白质
比例,减少精制碳水和添加糖。
     置信度: 0.95
     分类: 健身营养
  2. 类型: 事实
     内容: 有氧运动建议每次持续30-60分钟,保持中等强度(心率在最大心率的60-70%),可结合HIIT和LISS交替进行以提升效果 
。
     置信度: 0.9
     分类: 运动科学
  3. 类型: 事实
     内容: 减脂期间每日蛋白质摄入推荐量为每公斤体重1.6-2.2克,优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉。 
     置信度: 0.95
     分类: 营养学
  4. 类型: 需求
     内容: 用户希望了解如何通过运动和饮食安排实现减脂目标,关注具体执行方案(如运动时长、蛋白质摄入量)。
     置信度: 0.9
     分类: 用户目标
  5. 类型: 问题
     内容: 用户询问有氧运动做多久才有效果,AI回答建议每次30-60分钟,中等强度下效果更佳。
     置信度: 0.9
     分类: 常见疑问

对话摘要: 用户咨询减脂期间的运动与饮食安排,AI提供了包含有氧运动频率与时长、力量训练建议、蛋白质摄入量及饮食结构优化 
的具体方案,并回应了关于运动时长的有效性问题。
用户意图: 获取科学有效的减脂方案,包括运动频率、时长、强度以及饮食中的蛋白质摄入建议。

============================================================

示例2: 批量提取知识
正在处理对话 1/4...
正在处理对话 2/4...
正在处理对话 3/4...
正在处理对话 4/4...
总共提取了 24 个知识点

所有知识点:
  流程:减脂需结合运动与饮食:每周3-5次有氧运动(如跑步、游泳、骑行)和2-3次力量训练;饮食上控制总热量: 1次  
  事实:有氧运动建议每次持续30-60分钟,保持中等强度(心率在最大心率的60-70%),可结合HIIT和L: 1次
  事实:减脂期间每日蛋白质摄入推荐量为每公斤体重1.6-2.2克,优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和: 1次   
  需求:用户希望了解如何通过运动和饮食安排实现减脂目标,关注具体执行方案(如运动时长、蛋白质摄入量)。: 1次  
  问题:用户询问有氧运动做多久有效果,AI回答建议每次30-60分钟,保持中等强度,并推荐结合HIIT和LI: 1次
  流程:增肌训练建议每周进行3-5次力量训练,专注复合动作如深蹲、卧推、硬拉和引体向上;饮食上每日热量盈余3: 1次
  事实:训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,配合快速吸收的碳水化合物: 1次      
  事实:增肌期间可以适量进行有氧运动,每周2-3次,每次20-30分钟低强度有氧,有助于保持心肺健康和代谢功: 1次    
  需求:用户希望了解如何通过训练和饮食增加肌肉量,并关注训练后的营养补充和有氧运动对增肌的影响。: 1次        
  问题:训练后是否需要立即补充蛋白质?: 1次
  问题:增肌期间是否需要做有氧运动?: 1次
  注意:有氧运动不宜过量,以免影响力量训练的恢复,应控制在每周2-3次、每次20-30分钟低强度。: 1次
  事实:健康均衡饮食应包含大量蔬菜和水果、优质蛋白质来源、全谷物碳水化合物、健康脂肪以及充足的水分。: 1次    
  事实:减脂期晚上可以适量摄入复合碳水化合物,如糙米、燕麦、红薯等,但需控制总量并避免在临睡前大量摄入。: 1次
  事实:健身补剂不是必需品,但可以辅助训练效果。基础补剂包括乳清蛋白粉、肌酸和Omega-3脂肪酸;维生素D: 1次    
  需求:用户希望了解如何实现健康均衡饮食,以及在减脂期和健身场景下如何科学安排饮食和补剂。: 1次
  问题:减脂期晚上是否可以吃碳水?: 1次
  流程:遵循'盘子法则':一半盘子放蔬菜,1/4放蛋白质,1/4放全谷物,以实现健康均衡饮食。: 1次
  注意:选择健身补剂前最好咨询专业人士,避免盲目使用。: 1次
  流程:预防运动损伤的步骤包括:充分热身5-10分钟、循序渐进增加负荷、保持正确动作形式、合理安排训练和休息: 1次
  问题:如果出现持续性肩膀疼痛,应停止加重疼痛的训练动作,并咨询医生或物理治疗师。可以暂时进行不引起疼痛的其: 1次     
  流程:运动后加速恢复的方法包括:适当营养补充(蛋白质和碳水)、充足水分、7-9小时高质量睡眠、主动恢复(如: 1次        
  事实:运动后建议保证7-9小时高质量睡眠以促进身体恢复。: 1次
  注意:倾听身体信号,避免过度训练,是预防运动损伤的重要提醒。: 1次

============================================================

示例3: 合并相似知识
过滤前知识点数量: 24
过滤后知识点数量: 16
过滤掉的'需求'和'问题'类型知识点: 8
合并后剩余 3 个知识点

合并后的知识点:
  1. 类型: 流程
     内容: 减脂与增肌均需科学结合运动与饮食:减脂时建议每周进行3-5次有氧运动(如跑步、游泳、骑行)和2-3次力量训练,通
过控制总热量摄入实现热量赤字,同时增加蛋白质比例、减少精制碳水和添加糖;增肌则应每周进行3-5次力量训练,专注深蹲、卧推
、硬拉、引体向上等复合动作,每日热量盈余300-500卡路里,并确保每公斤体重摄入1.6-2.2克蛋白质。无论目标是减脂还是增肌, 
都应遵循均衡饮食结构,例如使用‘盘子法则’——一半盘子放蔬菜,四分之一放蛋白质,四分之一放全谷物。为预防运动损伤,需充分 
热身5-10分钟、保持正确动作形式、循序渐进增加负荷、合理安排训练与休息;运动后应注重恢复,包括适当营养补充(蛋白质+碳水
)、充足水分、7-9小时高质量睡眠、主动恢复(如散步、瑜伽)、拉伸及泡沫轴放松,必要时可采用冰敷或热敷促进恢复。        
     频率: 5次
     置信度: 0.96
     分类: 健身营养与训练计划
     关键词: ['减脂', '增肌', '运动', '饮食', '热量赤字', '热量盈余', '蛋白质摄入', '复合动作', '盘子法则', '预防运动
损伤', '恢复', '热身', '动作形式', '拉伸', '泡沫轴', '睡眠']
     来源: ['AI', 'AI', 'AI', 'AI', 'AI']

  2. 类型: 事实
     内容: 在减脂或增肌过程中,应结合科学的营养策略与训练安排以实现最佳效果。减脂期间每日蛋白质摄入推荐量为每公斤体重
1.6-2.2克,优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉;训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,并配合快速吸收的碳水化合物,有助于肌肉恢复和合成。健康均衡饮食应包含大量蔬菜水果、优质蛋白质、全谷物碳 
水化合物、健康脂肪及充足水分,同时晚间可适量摄入复合碳水(如糙米、燕麦、红薯),但需控制总量并避免临睡前过量摄入。有 
氧运动方面,建议每次持续30-60分钟、保持中等强度(心率在最大心率的60-70%),可结合HIIT和LISS交替进行提升效果;增肌期间
  2. 类型: 事实
     内容: 在减脂或增肌过程中,应结合科学的营养策略与训练安排以实现最佳效果。减脂期间每日蛋白质摄入推荐量为每公斤体重
1.6-2.2克,优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉;训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,并配合快速吸收的碳水化合物,有助于肌肉恢复和合成。健康均衡饮食应包含大量蔬菜水果、优质蛋白质、全谷物碳 
水化合物、健康脂肪及充足水分,同时晚间可适量摄入复合碳水(如糙米、燕麦、红薯),但需控制总量并避免临睡前过量摄入。有 
氧运动方面,建议每次持续30-60分钟、保持中等强度(心率在最大心率的60-70%),可结合HIIT和LISS交替进行提升效果;增肌期间
克优质蛋白质,并配合快速吸收的碳水化合物,有助于肌肉恢复和合成。健康均衡饮食应包含大量蔬菜水果、优质蛋白质、全谷物碳 
水化合物、健康脂肪及充足水分,同时晚间可适量摄入复合碳水(如糙米、燕麦、红薯),但需控制总量并避免临睡前过量摄入。有 
氧运动方面,建议每次持续30-60分钟、保持中等强度(心率在最大心率的60-70%),可结合HIIT和LISS交替进行提升效果;增肌期间
氧运动方面,建议每次持续30-60分钟、保持中等强度(心率在最大心率的60-70%),可结合HIIT和LISS交替进行提升效果;增肌期间
每周可进行2-3次低强度有氧(每次20-30分钟),有助于维持心肺健康和代谢功能,但不宜过量以免影响力量训练恢复。此外,健身 
补剂并非必需,但乳清蛋白粉、肌酸、Omega-3脂肪酸等基础补剂可辅助训练效果,维生素D和镁也可能对运动表现和恢复有益。最后 
,保证每天7-9小时高质量睡眠是促进身体恢复的关键环节。
     频率: 8次
     置信度: 0.98
     分类: 综合运动与营养科学
     关键词: ['有氧运动', '蛋白质摄入', '减脂', '增肌', '训练后补蛋白', '肌肉恢复', '碳水化合物', '健康饮食', '睡眠', '健身补剂', '训练强度', '时间管理']
     来源: ['AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI']

  3. 类型: 注意
     内容: 进行健身训练时,应合理安排有氧运动频率与强度,避免其干扰力量训练的恢复,建议每周2-3次、每次20-30分钟低强度
;同时,倾听身体信号,识别疲劳或不适,防止过度训练导致损伤;此外,使用健身补剂前务必咨询专业人士,以确保安全并考虑个 
体差异,避免盲目使用。
     频率: 3次
     置信度: 0.95
,保证每天7-9小时高质量睡眠是促进身体恢复的关键环节。
     频率: 8次
     置信度: 0.98
     分类: 综合运动与营养科学
     关键词: ['有氧运动', '蛋白质摄入', '减脂', '增肌', '训练后补蛋白', '肌肉恢复', '碳水化合物', '健康饮食', '睡眠', '健身补剂', '训练强度', '时间管理']
     来源: ['AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI']

  3. 类型: 注意
     内容: 进行健身训练时,应合理安排有氧运动频率与强度,避免其干扰力量训练的恢复,建议每周2-3次、每次20-30分钟低强度
;同时,倾听身体信号,识别疲劳或不适,防止过度训练导致损伤;此外,使用健身补剂前务必咨询专业人士,以确保安全并考虑个 
体差异,避免盲目使用。
     频率: 3次
     置信度: 0.95
     分类: 综合运动与营养科学
     关键词: ['有氧运动', '蛋白质摄入', '减脂', '增肌', '训练后补蛋白', '肌肉恢复', '碳水化合物', '健康饮食', '睡眠', '健身补剂', '训练强度', '时间管理']
     来源: ['AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI', 'AI']

  3. 类型: 注意
     内容: 进行健身训练时,应合理安排有氧运动频率与强度,避免其干扰力量训练的恢复,建议每周2-3次、每次20-30分钟低强度
;同时,倾听身体信号,识别疲劳或不适,防止过度训练导致损伤;此外,使用健身补剂前务必咨询专业人士,以确保安全并考虑个 
体差异,避免盲目使用。
     频率: 3次
     置信度: 0.95
;同时,倾听身体信号,识别疲劳或不适,防止过度训练导致损伤;此外,使用健身补剂前务必咨询专业人士,以确保安全并考虑个 
体差异,避免盲目使用。
     频率: 3次
     置信度: 0.95
     置信度: 0.95
     分类: 训练注意事项
     关键词: ['有氧运动', '恢复干扰', '强度控制', '补剂安全', '专业建议', '个体差异', '身体信号', '过度训练', '预防', '健身安全']
     来源: ['AI', 'AI', 'AI']

核心函数

  • extract_knowledge_from_conversation() : 从单次对话中提取知识
  • batch_extract_knowledge() : 批量提取知识
  • merge_similar_knowledge():使用大模型合并相似知识点

六、知识库健康度检查:量化评估与科学治理

1. 基础介绍

        知识库不能只建不管,需要一套可量化的指标体系来持续监控其健康状况,需要定期评估知识库的质量,否则它会逐渐失效。可以通过自动化脚本计算关键指标。

  • 核心指标:
    • 覆盖度:知识库能回答的问题占所有可能问题的比例。可通过日志分析未命中查询来评估。
    • 准确率:返回的答案正确的比例。需通过人工抽检或用户反馈(如“是否解决”)来估算。
    • 解决率:用户在看到答案后,不再进一步追问或转人工的比例。是衡量知识有效性的黄金指标。
    • 时效性:知识的新旧程度。定期扫描并标记过期内容(如包含“去年”、“2022年”等时间敏感信息的条款)。
    • 使用度:各知识条目的被访问频率。低频知识可能价值低或难以查找,高频知识则需要重点保障其质量。
  • 理论支撑:数据驱动决策。通过dashboard监控这些指标,可以发现知识库的薄弱环节,从而有针对性地进行优化,分配有限的人力资源。

2. 案例演示

代码结构

# 知识库健康度检查
# 导入依赖库
import dashscope
import os
import json
import re
from datetime import datetime

# 从环境变量中获取 API Key
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')

# 基于 prompt 生成文本
def get_completion(prompt, model="qwen-turbo-latest"):
    messages = [{"role": "user", "content": prompt}]
    response = dashscope.Generation.call(
        model=model,
        messages=messages,
        result_format='message',
        temperature=0.3,
    )
    return response.output.choices[0].message.content

class KnowledgeBaseHealthChecker:
    def __init__(self, model="qwen-turbo-latest"):
        self.model = model
        self.health_report = {}
        
    def check_missing_knowledge(self, knowledge_base, test_queries):
        """使用LLM检查缺少的知识"""
        instruction = """
你是一个知识库完整性检查专家。请分析给定的测试查询和知识库内容,判断知识库中是否缺少相关的知识。

检查标准:
1. 查询是否能在知识库中找到相关答案
2. 知识是否完整、准确
3. 是否覆盖了用户的主要需求
4. 是否存在知识空白

请返回JSON格式:
{
    "missing_knowledge": [
        {
            "query": "测试查询",
            "missing_aspect": "缺少的知识方面",
            "importance": "重要性(高/中/低)",
            "suggested_content": "建议的知识内容",
            "category": "知识分类"
        }
    ],
    "coverage_score": "覆盖率评分(0-1)",
    "completeness_analysis": "完整性分析"
}
"""
        
        # 构建知识库内容摘要
        knowledge_summary = []
        for chunk in knowledge_base:
            knowledge_summary.append(f"ID: {chunk.get('id', 'unknown')} - {chunk.get('content', '')}")
        
        knowledge_text = "\n".join(knowledge_summary)
        
        # 构建测试查询列表
        queries_text = []
        for query_info in test_queries:
            query = query_info['query']
            expected = query_info.get('expected_answer', '')
            queries_text.append(f"查询: {query} | 期望答案: {expected}")
        
        queries_text = "\n".join(queries_text)
        
        prompt = f"""
### 指令 ###
{instruction}

### 知识库内容 ###
{knowledge_text}

### 测试查询 ###
{queries_text}

### 分析结果 ###
"""
        
        try:
            response = get_completion(prompt, self.model)
            
            # 预处理响应,移除markdown代码块格式
            if response.startswith('```json'):
                response = response[7:]
            elif response.startswith('```'):
                response = response[3:]
            if response.endswith('```'):
                response = response[:-3]
            
            result = json.loads(response.strip())
            return result
            
        except Exception as e:
            print(f"LLM检查缺少知识失败: {e}")
            return None
    
    def check_outdated_knowledge(self, knowledge_base):
        """使用LLM检查过期的知识"""
        instruction = """
你是一个知识时效性检查专家。请分析给定的知识内容,判断是否存在过期或需要更新的信息。

检查标准:
1. 时间相关信息是否过期(年份、日期、时间范围)
2. 价格信息是否最新(价格、费用、票价等)
3. 政策规则是否更新(政策、规定、规则等)
4. 活动信息是否有效(活动、节日、特殊安排等)
5. 联系方式是否准确(电话、地址、网址等)
6. 技术信息是否过时(版本、技术标准等)

请返回JSON格式:
{
    "outdated_knowledge": [
        {
            "chunk_id": "知识切片ID",
            "content": "知识内容",
            "outdated_aspect": "过期方面",
            "severity": "严重程度(高/中/低)",
            "suggested_update": "建议更新内容",
            "last_verified": "最后验证时间"
        }
    ],
    "freshness_score": "新鲜度评分(0-1)",
    "update_recommendations": "更新建议"
}
"""
        
        # 构建知识库内容
        knowledge_text = []
        for chunk in knowledge_base:
            content = chunk.get('content', '')
            chunk_id = chunk.get('id', 'unknown')
            last_updated = chunk.get('last_updated', 'unknown')
            knowledge_text.append(f"ID: {chunk_id} | 更新时间: {last_updated} | 内容: {content}")
        
        knowledge_text = "\n".join(knowledge_text)
        
        prompt = f"""
### 指令 ###
{instruction}

### 知识库内容 ###
{knowledge_text}

### 当前时间 ###
{datetime.now().strftime('%Y年%m月%d日')}

### 分析结果 ###
"""
        
        try:
            response = get_completion(prompt, self.model)
            
            # 预处理响应,移除markdown代码块格式
            if response.startswith('```json'):
                response = response[7:]
            elif response.startswith('```'):
                response = response[3:]
            if response.endswith('```'):
                response = response[:-3]
            
            result = json.loads(response.strip())
            return result
            
        except Exception as e:
            print(f"LLM检查过期知识失败: {e}")
            return None
    def check_conflicting_knowledge(self, knowledge_base):
        """使用LLM检查冲突的知识"""
        instruction = """
你是一个知识一致性检查专家。请分析给定的知识库,找出可能存在冲突或矛盾的信息。

检查标准:
1. 同一主题的不同说法(地点、名称、描述等)
2. 价格信息的差异(价格、费用、收费标准等)
3. 时间信息的不一致(营业时间、开放时间、活动时间等)
4. 规则政策的冲突(规定、政策、要求等)
5. 操作流程的差异(步骤、方法、流程等)
6. 联系方式的差异(地址、电话、网址等)

请返回JSON格式:
{
    "conflicting_knowledge": [
        {
            "conflict_type": "冲突类型",
            "chunk_ids": ["相关切片ID"],
            "conflicting_content": ["冲突内容"],
            "severity": "严重程度(高/中/低)",
            "resolution_suggestion": "解决建议"
        }
    ],
    "consistency_score": "一致性评分(0-1)",
    "conflict_analysis": "冲突分析"
}
"""
        
        # 构建知识库内容
        knowledge_text = []
        for chunk in knowledge_base:
            content = chunk.get('content', '')
            chunk_id = chunk.get('id', 'unknown')
            knowledge_text.append(f"ID: {chunk_id} | 内容: {content}")
        
        knowledge_text = "\n".join(knowledge_text)
        
        prompt = f"""
### 指令 ###
{instruction}

### 知识库内容 ###
{knowledge_text}

### 分析结果 ###
"""
        
        try:
            response = get_completion(prompt, self.model)
            
            # 预处理响应,移除markdown代码块格式
            if response.startswith('```json'):
                response = response[7:]
            elif response.startswith('```'):
                response = response[3:]
            if response.endswith('```'):
                response = response[:-3]
            
            result = json.loads(response.strip())
            return result
            
        except Exception as e:
            print(f"LLM检查冲突知识失败: {e}")
            return None
    
    def calculate_overall_health_score(self, missing_result, outdated_result, conflicting_result):
        """计算整体健康度评分"""
        coverage_score = missing_result.get('coverage_score', 0)
        freshness_score = outdated_result.get('freshness_score', 0)
        consistency_score = conflicting_result.get('consistency_score', 0)
        
        # 加权计算
        overall_score = (
            coverage_score * 0.4 +      # 覆盖率权重40%
            freshness_score * 0.3 +     # 新鲜度权重30%
            consistency_score * 0.3      # 一致性权重30%
        )
        
        return overall_score
    
    def generate_health_report(self, knowledge_base, test_queries):
        """生成完整的健康度报告"""
        print("正在检查知识库健康度...")
        
        # 1. 检查缺少的知识
        print("1. 检查缺少的知识...")
        missing_result = self.check_missing_knowledge(knowledge_base, test_queries)
        
        # 2. 检查过期的知识
        print("2. 检查过期的知识...")
        outdated_result = self.check_outdated_knowledge(knowledge_base)
        
        # 3. 检查冲突的知识
        print("3. 检查冲突的知识...")
        conflicting_result = self.check_conflicting_knowledge(knowledge_base)
        
        # 4. 计算整体健康度
        overall_score = self.calculate_overall_health_score(missing_result, outdated_result, conflicting_result)
        
        # 5. 生成报告
        report = {
            "overall_health_score": overall_score,
            "health_level": self.get_health_level(overall_score),
            "missing_knowledge": missing_result,
            "outdated_knowledge": outdated_result,
            "conflicting_knowledge": conflicting_result,
            "recommendations": self.generate_recommendations(missing_result, outdated_result, conflicting_result),
            "check_date": datetime.now().isoformat()
        }
        
        return report
    
    def get_health_level(self, score):
        """根据评分确定健康等级"""
        if score >= 0.8:
            return "优秀"
        elif score >= 0.6:
            return "良好"
        elif score >= 0.4:
            return "一般"
        else:
            return "需要改进"
    
    def generate_recommendations(self, missing_result, outdated_result, conflicting_result):
        """生成改进建议"""
        recommendations = []
        
        # 基于缺少知识的建议
        missing_count = len(missing_result.get('missing_knowledge', []))
        if missing_count > 0:
            recommendations.append(f"补充{missing_count}个缺少的知识点,提高覆盖率")
        
        # 基于过期知识的建议
        outdated_count = len(outdated_result.get('outdated_knowledge', []))
        if outdated_count > 0:
            recommendations.append(f"更新{outdated_count}个过期知识点,确保信息时效性")
        
        # 基于冲突知识的建议
        conflicting_count = len(conflicting_result.get('conflicting_knowledge', []))
        if conflicting_count > 0:
            recommendations.append(f"解决{conflicting_count}个知识冲突,提高一致性")
        
        if not recommendations:
            recommendations.append("知识库状态良好,建议定期维护")
        
        return recommendations

def main():
    # 初始化知识库健康度检查器
    checker = KnowledgeBaseHealthChecker()
    
    print("=== 知识库健康度检查示例(健康健身主题) ===\n")
    
    # 示例知识库(包含一些故意的问题)
    knowledge_base = [
        {
        "id": "kb_001",
        "content": "减脂需要创造热量赤字,建议每周进行3-5次有氧运动和2-3次力量训练。饮食上控制总热量摄入,增加蛋白质比例。",
        "last_updated": "2024-01-15"
    },
    {
        "id": "kb_002",
        "content": "增肌需要渐进式超负荷训练和热量盈余。建议每周进行3-5次力量训练,专注复合动作如深蹲、卧推、硬拉。",
        "last_updated": "2024-01-10"
    },
    {
        "id": "kb_003",
        "content": "蛋白质摄入建议:减脂期每公斤体重1.6-2.2克,增肌期每公斤体重1.6-2.2克。",  # 故意设置相同数值,可能存在问题
        "last_updated": "2023-06-01"  # 故意设置为较旧的时间
    },
    {
        "id": "kb_004",
        "content": "训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质。",
        "last_updated": "2024-01-20"
    },
    {
        "id": "kb_005",
        "content": "有氧运动建议每次30-60分钟,保持中等强度(心率在最大心率的60-70%)。",
        "last_updated": "2024-01-10"
    },
    {
        "id": "kb_006",
        "content": "健康均衡饮食应包含大量蔬菜和水果、优质蛋白质、全谷物碳水化合物和健康脂肪。",
        "last_updated": "2024-02-01"
    },
    {
        "id": "kb_007",
        "content": "乳清蛋白粉是方便的训练后补充选择,但并非必需品。基础补剂还包括肌酸和Omega-3脂肪酸。",
        "last_updated": "2023-11-01"  # 较旧的时间
    },
    {
        "id": "kb_008",
        "content": "预防运动损伤的关键包括:充分热身、循序渐进增加负荷、保持正确动作形式、合理安排训练和休息。",
        "last_updated": "2024-01-05"
    },
    {
        "id": "kb_009",
        "content": "减脂期间晚上不应摄入碳水化合物,以免转化为脂肪储存。",  # 故意设置可能过时或不准确的观点
        "last_updated": "2024-01-15"
    }
    ]
    
    # 测试查询
    test_queries = [
        {
            "query": "如何有效减脂?",
            "expected_answer": "热量赤字、有氧和力量训练结合"
        },
        {
            "query": "增肌需要怎么做?",
            "expected_answer": "渐进超负荷、热量盈余、足够蛋白质"
        },
        {
            "query": "蛋白质应该吃多少?",
            "expected_answer": "根据目标每公斤体重1.6-2.2克"
        },
        {
            "query": "训练后应该补充什么?",
            "expected_answer": "蛋白质和快速吸收碳水"
        },
        {
            "query": "有氧运动做多久?",
            "expected_answer": "30-60分钟中等强度"
        },
        {
            "query": "什么是健康饮食?",  # 知识库中有相关信息
            "expected_answer": "多样化、蔬菜水果、优质蛋白、全谷物"
        },
        {
            "query": "健身补剂有必要吗?",  # 知识库中有相关信息
            "expected_answer": "不是必需品但可以辅助"
        },
        {
            "query": "如何预防运动损伤?",  # 知识库中有相关信息
            "expected_answer": "热身、正确形式、循序渐进"
        },
        {
            "query": "运动后肌肉酸痛怎么办?",  # 知识库中没有相关信息
            "expected_answer": "恢复方法"
        },
        {
            "query": "生酮饮食适合减脂吗?",  # 知识库中没有相关信息
            "expected_answer": "生酮饮食评价"
        },
        {
            "query": "瑜伽对健身有什么好处?",  # 知识库中没有相关信息
            "expected_answer": "瑜伽益处"
        }
    ]
    
    # 生成健康度报告
    health_report = checker.generate_health_report(knowledge_base, test_queries)
    
    # 显示报告
    print("=== 知识库健康度报告 ===\n")
    
    print(f"整体健康度评分: {health_report['overall_health_score']:.2f}")
    print(f"健康等级: {health_report['health_level']}")
    print(f"检查时间: {health_report['check_date']}")
    
    print("\n" + "="*60 + "\n")
    
    # 详细分析
    print("=== 详细分析 ===\n")
    
    # 1. 缺少的知识
    print("1. 缺少的知识分析:")
    missing = health_report['missing_knowledge']
    print(f"   覆盖率: {health_report['missing_knowledge']['coverage_score']*100:.1f}%")
    print(f"   缺少知识点数量: {len(missing['missing_knowledge'])}")
    for i, item in enumerate(missing['missing_knowledge'][:3], 1):
        print(f"   {i}. 查询: {item['query']}")
        print(f"      缺少方面: {item['missing_aspect']}")
        print(f"      重要性: {item['importance']}")
    
    print("\n" + "-"*40 + "\n")
    
    # 2. 过期的知识
    print("2. 过期的知识分析:")
    outdated = health_report['outdated_knowledge']
    print(f"   新鲜度评分: {outdated['freshness_score']:.2f}")
    print(f"   过期知识点数量: {len(outdated['outdated_knowledge'])}")
    for i, item in enumerate(outdated['outdated_knowledge'][:3], 1):
        print(f"   {i}. 切片ID: {item['chunk_id']}")
        print(f"      过期方面: {item['outdated_aspect']}")
        print(f"      严重程度: {item['severity']}")
    
    print("\n" + "-"*40 + "\n")
    
    # 3. 冲突的知识
    print("3. 冲突的知识分析:")
    conflicting = health_report['conflicting_knowledge']
    print(f"   一致性评分: {conflicting['consistency_score']:.2f}")
    print(f"   冲突数量: {len(conflicting['conflicting_knowledge'])}")
    for i, item in enumerate(conflicting['conflicting_knowledge'][:3], 1):
        print(f"   {i}. 冲突类型: {item['conflict_type']}")
        print(f"      相关切片: {item['chunk_ids']}")
        print(f"      严重程度: {item['severity']}")
    
    print("\n" + "="*60 + "\n")
    
    # 改进建议
    print("=== 改进建议 ===\n")
    for i, recommendation in enumerate(health_report['recommendations'], 1):
        print(f"{i}. {recommendation}")

if __name__ == "__main__":
    main() 

输出结果

=== 知识库健康度检查示例(健康健身主题) ===

正在检查知识库健康度...
1. 检查缺少的知识...
2. 检查过期的知识...
3. 检查冲突的知识...
=== 知识库健康度报告 ===

整体健康度评分: 0.78
健康等级: 良好
检查时间: 2025-09-06T00:54:31.765164

============================================================

=== 详细分析 ===

1. 缺少的知识分析:
   覆盖率: 70.0%
   缺少知识点数量: 3
   1. 查询: 运动后肌肉酸痛怎么办?
      缺少方面: 恢复方法(如休息、拉伸、冷热交替、营养补充等)
      重要性: 高
   2. 查询: 生酮饮食适合减脂吗?
      缺少方面: 生酮饮食对减脂的科学评价(机制、适用人群、潜在风险)
      重要性: 中
   3. 查询: 瑜伽对健身有什么好处?
      缺少方面: 瑜伽对健身的具体益处(柔韧性、核心稳定性、心理放松、损伤预防等)
      重要性: 中

----------------------------------------

2. 过期的知识分析:
   新鲜度评分: 0.87
   过期知识点数量: 1
   1. 切片ID: kb_009
      过期方面: 饮食建议
      严重程度: 高

----------------------------------------

3. 冲突的知识分析:
   一致性评分: 0.80
   冲突数量: 1
   1. 冲突类型: 规则政策的冲突
      相关切片: ['kb_001', 'kb_009']
      严重程度: 中

============================================================

=== 改进建议 ===

1. 补充3个缺少的知识点,提高覆盖率
2. 更新1个过期知识点,确保信息时效性
3. 解决1个知识冲突,提高一致性

七、知识库版本管理与性能比较

1. 基础介绍

        知识库的迭代和优化需要像管理代码一样科学,避免改错无法回溯、效果无法衡量。

版本管理理论:

  • 每一次更改(增、删、改) 都对应一个提交,记录更改人、时间和原因。
  • 建立分支(Branch) 进行重大修改或实验,稳定后再合并(Merge)到主分支(Master)。
  • 允许回滚(Rollback) 到任何一个历史版本。

性能比较(A/B Testing):

  • 理论:将用户流量随机分为两组(A组和B组)。A组使用旧版本知识库(对照组),B组使用新版本知识库(实验组)。
  • 对比指标:在实验期间,统计并比较两组的关键指标,如解决率、用户满意度、平均会话时长等。
  • 统计显著性:使用统计检验方法(如t-test)确认指标差异不是由随机波动引起的,从而科学地判断新版本是否真正带来了提升。

价值:实现了知识库优化的可度量、可比较、可回溯,使知识库的演进过程从“艺术”变为“科学”。

2.  案例演示

代码结构

# 知识库版本管理与性能比较
# 导入依赖库
import dashscope
import os
import json
import re
from datetime import datetime, timedelta
from collections import defaultdict, Counter
import pandas as pd
import numpy as np
import faiss
from openai import OpenAI

# 从环境变量中获取 API Key
dashscope.api_key = os.getenv('DASHSCOPE_API_KEY')

# 初始化百炼兼容的 OpenAI 客户端
client = OpenAI(
    api_key=dashscope.api_key,
    base_url="https://dashscope.aliyuncs.com/compatible-mode/v1"
)

# 全局配置
TEXT_EMBEDDING_MODEL = "text-embedding-v4"
TEXT_EMBEDDING_DIM = 1024

# 基于 prompt 生成文本
def get_completion(prompt, model="qwen-turbo-latest"):
    messages = [{"role": "user", "content": prompt}]
    response = dashscope.Generation.call(
        model=model,
        messages=messages,
        result_format='message',
        temperature=0.3,
    )
    return response.output.choices[0].message.content

def get_text_embedding(text):
    """获取文本的 Embedding"""
    response = client.embeddings.create(
        model=TEXT_EMBEDDING_MODEL,
        input=text,
        dimensions=TEXT_EMBEDDING_DIM
    )
    return response.data[0].embedding

class KnowledgeBaseVersionManager:
    def __init__(self, model="qwen-turbo-latest"):
        self.model = model
        self.versions = {}
        
    def create_version(self, knowledge_base, version_name, description=""):
        """创建知识库版本"""
        # 构建向量索引
        metadata_store, text_index = self.build_vector_index(knowledge_base)
        
        version_info = {
            "version_name": version_name,
            "description": description,
            "created_date": datetime.now().isoformat(),
            "knowledge_base": knowledge_base,
            "metadata_store": metadata_store,
            "text_index": text_index,
            "statistics": self.calculate_version_statistics(knowledge_base)
        }
        
        self.versions[version_name] = version_info
        return version_info
    
    def build_vector_index(self, knowledge_base):
        """构建向量索引"""
        metadata_store = []
        text_vectors = []
        
        for i, chunk in enumerate(knowledge_base):
            content = chunk.get('content', '')
            if not content.strip():
                continue
                
            metadata = {
                "id": i,
                "content": content,
                "chunk_id": chunk.get('id', f'chunk_{i}')
            }
            
            # 获取文本embedding
            vector = get_text_embedding(content)
            text_vectors.append(vector)
            metadata_store.append(metadata)
        
        # 创建FAISS索引
        text_index = faiss.IndexFlatL2(TEXT_EMBEDDING_DIM)
        text_index_map = faiss.IndexIDMap(text_index)
        
        if text_vectors:
            text_ids = [m["id"] for m in metadata_store]
            text_index_map.add_with_ids(np.array(text_vectors).astype('float32'), np.array(text_ids))
        
        return metadata_store, text_index_map
    
    def calculate_version_statistics(self, knowledge_base):
        """计算版本统计信息"""
        total_chunks = len(knowledge_base)
        total_content_length = sum(len(chunk.get('content', '')) for chunk in knowledge_base)
        
        return {
            "total_chunks": total_chunks,
            "total_content_length": total_content_length,
            "average_chunk_length": total_content_length / total_chunks if total_chunks > 0 else 0
        }
    
    def compare_versions(self, version1_name, version2_name):
        """比较两个版本的差异"""
        if version1_name not in self.versions or version2_name not in self.versions:
            return {"error": "版本不存在"}
        
        v1 = self.versions[version1_name]
        v2 = self.versions[version2_name]
        
        kb1 = v1['knowledge_base']
        kb2 = v2['knowledge_base']
        
        comparison = {
            "version1": version1_name,
            "version2": version2_name,
            "comparison_date": datetime.now().isoformat(),
            "changes": self.detect_changes(kb1, kb2),
            "statistics_comparison": self.compare_statistics(v1['statistics'], v2['statistics'])
        }
        
        return comparison
    
    def detect_changes(self, kb1, kb2):
        """检测知识库变化"""
        changes = {
            "added_chunks": [],
            "removed_chunks": [],
            "modified_chunks": [],
            "unchanged_chunks": []
        }
        
        # 创建ID映射
        kb1_dict = {chunk.get('id'): chunk for chunk in kb1}
        kb2_dict = {chunk.get('id'): chunk for chunk in kb2}
        
        # 检测新增和删除
        kb1_ids = set(kb1_dict.keys())
        kb2_ids = set(kb2_dict.keys())
        
        added_ids = kb2_ids - kb1_ids
        removed_ids = kb1_ids - kb2_ids
        common_ids = kb1_ids & kb2_ids
        
        # 记录新增的知识切片
        for chunk_id in added_ids:
            changes["added_chunks"].append({
                "id": chunk_id,
                "content": kb2_dict[chunk_id].get('content', '')
            })
        
        # 记录删除的知识切片
        for chunk_id in removed_ids:
            changes["removed_chunks"].append({
                "id": chunk_id,
                "content": kb1_dict[chunk_id].get('content', '')
            })
        
        # 检测修改的知识切片
        for chunk_id in common_ids:
            chunk1 = kb1_dict[chunk_id]
            chunk2 = kb2_dict[chunk_id]
            
            if chunk1.get('content') != chunk2.get('content'):
                changes["modified_chunks"].append({
                    "id": chunk_id,
                    "old_content": chunk1.get('content', ''),
                    "new_content": chunk2.get('content', '')
                })
            else:
                changes["unchanged_chunks"].append(chunk_id)
        
        return changes
    
    def compare_statistics(self, stats1, stats2):
        """比较统计信息"""
        comparison = {}
        
        for key in stats1.keys():
            if key in stats2:
                if isinstance(stats1[key], (int, float)):
                    comparison[key] = {
                        "version1": stats1[key],
                        "version2": stats2[key],
                        "difference": stats2[key] - stats1[key],
                        "percentage_change": ((stats2[key] - stats1[key]) / stats1[key] * 100) if stats1[key] != 0 else 0
                    }
                elif isinstance(stats1[key], dict):
                    comparison[key] = self.compare_dict_statistics(stats1[key], stats2[key])
        
        return comparison
    
    def compare_dict_statistics(self, dict1, dict2):
        """比较字典类型的统计信息"""
        comparison = {}
        all_keys = set(dict1.keys()) | set(dict2.keys())
        
        for key in all_keys:
            val1 = dict1.get(key, 0)
            val2 = dict2.get(key, 0)
            comparison[key] = {
                "version1": val1,
                "version2": val2,
                "difference": val2 - val1
            }
        
        return comparison
    
    def evaluate_version_performance(self, version_name, test_queries):
        """评估版本性能"""
        if version_name not in self.versions:
            return {"error": "版本不存在"}
        
        performance_metrics = {
            "version_name": version_name,
            "evaluation_date": datetime.now().isoformat(),
            "query_results": [],
            "overall_metrics": {}
        }
        
        total_queries = len(test_queries)
        correct_answers = 0
        response_times = []
        
        for query_info in test_queries:
            query = query_info['query']
            expected_answer = query_info.get('expected_answer', '')
            
            # 使用embedding检索
            start_time = datetime.now()
            retrieved_chunks = self.retrieve_relevant_chunks(query, version_name)
            end_time = datetime.now()
            
            response_time = (end_time - start_time).total_seconds()
            response_times.append(response_time)
            
            # 评估检索质量
            is_correct = self.evaluate_retrieval_quality(query, retrieved_chunks, expected_answer)
            if is_correct:
                correct_answers += 1
            
            performance_metrics["query_results"].append({
                "query": query,
                "retrieved_chunks": len(retrieved_chunks),
                "response_time": response_time,
                "is_correct": is_correct
            })
        
        # 计算整体指标
        accuracy = correct_answers / total_queries if total_queries > 0 else 0
        avg_response_time = sum(response_times) / len(response_times) if response_times else 0
        
        performance_metrics["overall_metrics"] = {
            "accuracy": accuracy,
            "avg_response_time": avg_response_time,
            "total_queries": total_queries,
            "correct_answers": correct_answers
        }
        
        return performance_metrics
    
    def retrieve_relevant_chunks(self, query, version_name, k=3):
        """使用embedding和faiss检索相关知识切片"""
        if version_name not in self.versions:
            return []
        
        version_info = self.versions[version_name]
        metadata_store = version_info['metadata_store']
        text_index = version_info['text_index']
        
        # 获取查询的embedding
        query_vector = np.array([get_text_embedding(query)]).astype('float32')
        
        # 使用faiss进行检索
        distances, indices = text_index.search(query_vector, k)
        
        relevant_chunks = []
        for i, doc_id in enumerate(indices[0]):
            if doc_id != -1:  # faiss返回-1表示没有找到匹配
                # 通过ID在元数据中查找
                match = next((item for item in metadata_store if item["id"] == doc_id), None)
                if match:
                    # 构造返回的知识切片格式
                    chunk = {
                        "id": match["chunk_id"],
                        "content": match["content"],
                        "similarity_score": 1.0 / (1.0 + distances[0][i])  # 将距离转换为相似度
                    }
                    relevant_chunks.append(chunk)
        
        return relevant_chunks
    
    def evaluate_retrieval_quality(self, query, retrieved_chunks, expected_answer):
        """评估检索质量"""
        if not retrieved_chunks:
            return False
        
        # 简化的质量评估
        for chunk in retrieved_chunks:
            content = chunk.get('content', '').lower()
            if expected_answer.lower() in content:
                return True
        
        return False
    
    def compare_version_performance(self, version1_name, version2_name, test_queries):
        """比较两个版本的性能"""
        perf1 = self.evaluate_version_performance(version1_name, test_queries)
        perf2 = self.evaluate_version_performance(version2_name, test_queries)
        
        if "error" in perf1 or "error" in perf2:
            return {"error": "版本评估失败"}
        
        comparison = {
            "version1": version1_name,
            "version2": version2_name,
            "comparison_date": datetime.now().isoformat(),
            "performance_comparison": {
                "accuracy": {
                    "version1": perf1["overall_metrics"]["accuracy"],
                    "version2": perf2["overall_metrics"]["accuracy"],
                    "improvement": perf2["overall_metrics"]["accuracy"] - perf1["overall_metrics"]["accuracy"]
                },
                "response_time": {
                    "version1": perf1["overall_metrics"]["avg_response_time"],
                    "version2": perf2["overall_metrics"]["avg_response_time"],
                    "improvement": perf1["overall_metrics"]["avg_response_time"] - perf2["overall_metrics"]["avg_response_time"]
                }
            },
            "recommendation": self.generate_performance_recommendation(perf1, perf2)
        }
        
        return comparison
    
    def generate_performance_recommendation(self, perf1, perf2):
        """生成性能建议"""
        acc1 = perf1["overall_metrics"]["accuracy"]
        acc2 = perf2["overall_metrics"]["accuracy"]
        time1 = perf1["overall_metrics"]["avg_response_time"]
        time2 = perf2["overall_metrics"]["avg_response_time"]
        
        if acc2 > acc1 and time2 <= time1:
            return f"推荐使用版本2,准确率提升{(acc2-acc1)*100:.1f}%,响应时间{'提升' if time2 < time1 else '相当'}"
        elif acc2 > acc1 and time2 > time1:
            return f"版本2准确率更高但响应时间较长,需要权衡"
        elif acc2 < acc1 and time2 < time1:
            return f"版本2响应更快但准确率较低,需要权衡"
        else:
            return f"推荐使用版本1,性能更优"
    
    def generate_regression_test(self, version_name, test_queries):
        """生成回归测试"""
        if version_name not in self.versions:
            return {"error": "版本不存在"}
        
        regression_results = {
            "version_name": version_name,
            "test_date": datetime.now().isoformat(),
            "test_results": [],
            "pass_rate": 0
        }
        
        passed_tests = 0
        total_tests = len(test_queries)
        
        for query_info in test_queries:
            query = query_info['query']
            expected_answer = query_info.get('expected_answer', '')
            
            # 执行测试
            retrieved_chunks = self.retrieve_relevant_chunks(query, version_name)
            is_passed = self.evaluate_retrieval_quality(query, retrieved_chunks, expected_answer)
            
            if is_passed:
                passed_tests += 1
            
            regression_results["test_results"].append({
                "query": query,
                "expected": expected_answer,
                "retrieved": len(retrieved_chunks),
                "passed": is_passed
            })
        
        regression_results["pass_rate"] = passed_tests / total_tests if total_tests > 0 else 0
        
        return regression_results

def main():
    # 初始化版本管理器
    version_manager = KnowledgeBaseVersionManager()
    
    print("=== 知识库版本管理与性能比较示例(健康健身知识) ===\n")
    
    # 创建版本1(基础版本)
    knowledge_base_v1 = [
        {
            "id": "kb_001",
            "content": "减脂需要创造热量赤字,建议每周进行3-5次有氧运动和2-3次力量训练。",
            "category": "减脂"
        },
        {
            "id": "kb_002",
            "content": "增肌需要渐进式超负荷训练和热量盈余,建议每周进行3-5次力量训练。",
            "category": "增肌"
        },
        {
            "id": "kb_003",
            "content": "蛋白质摄入建议:减脂期每公斤体重1.6-2.2克,增肌期每公斤体重1.6-2.2克。",
            "category": "营养"
        }
    ]
    
    # 创建版本2(增强版本)
    knowledge_base_v2 = [
        {
            "id": "kb_001",
            "content": "减脂需要创造热量赤字,建议每周进行3-5次有氧运动(如跑步、游泳)和2-3次力量训练。饮食上控制总热量摄入,增加蛋白质比例,减少精制碳水和添加糖。",
            "category": "减脂"
        },
        {
            "id": "kb_002",
            "content": "增肌需要渐进式超负荷训练和热量盈余。建议每周进行3-5次力量训练,专注复合动作如深蹲、卧推、硬拉和引体向上。饮食上每日热量盈余300-500卡路里。",
            "category": "增肌"
        },
        {
            "id": "kb_003",
            "content": "蛋白质摄入建议:减脂期每公斤体重1.6-2.2克,增肌期每公斤体重1.6-2.2克。优质蛋白来源包括鸡胸肉、鱼、鸡蛋、豆制品和乳清蛋白粉。",
            "category": "营养"
        },
        {
            "id": "kb_004",
            "content": "训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,配合快速吸收的碳水化合物,有助于肌肉恢复和合成。",
            "category": "训练"
        },
        {
            "id": "kb_005",
            "content": "有氧运动建议每次30-60分钟,保持中等强度(心率在最大心率的60-70%)。最好结合高强度间歇训练(HIIT)和稳态有氧(LISS)交替进行。",
            "category": "训练"
        },
        {
            "id": "kb_006",
            "content": "健康均衡饮食应包含多样化的食物:大量蔬菜和水果、优质蛋白质来源、全谷物碳水化合物、健康脂肪以及充足的水分。",
            "category": "营养"
        }
    ]
    
    # 功能1: 创建版本
    print("功能1: 创建知识库版本")
    v1_info = version_manager.create_version(knowledge_base_v1, "v1.0", "基础版本")
    v2_info = version_manager.create_version(knowledge_base_v2, "v2.0", "增强版本")
    
    print(f"版本1信息:")
    print(f"  版本名: {v1_info['version_name']}")
    print(f"  描述: {v1_info['description']}")
    print(f"  知识切片数量: {v1_info['statistics']['total_chunks']}")
    print(f"  平均切片长度: {v1_info['statistics']['average_chunk_length']:.0f}字符")
    
    print(f"\n版本2信息:")
    print(f"  版本名: {v2_info['version_name']}")
    print(f"  描述: {v2_info['description']}")
    print(f"  知识切片数量: {v2_info['statistics']['total_chunks']}")
    print(f"  平均切片长度: {v2_info['statistics']['average_chunk_length']:.0f}字符")
    
    print("\n" + "="*60 + "\n")
    
    # 功能示例2: 版本比较
    print("功能2: 版本差异比较")
    comparison = version_manager.compare_versions("v1.0", "v2.0")
    
    print(f"版本比较结果:")
    changes = comparison['changes']
    print(f"  新增知识切片: {len(changes['added_chunks'])}个")
    print(f"  删除知识切片: {len(changes['removed_chunks'])}个")
    print(f"  修改知识切片: {len(changes['modified_chunks'])}个")
    
    print(f"\n新增的知识切片:")
    for i, chunk in enumerate(changes['added_chunks'], 1):
        print(f"  {i}. ID: {chunk['id']}")
        print(f"     内容: {chunk['content']}")
    
    print(f"\n修改的知识切片:")
    for i, chunk in enumerate(changes['modified_chunks'], 1):
        print(f"  {i}. ID: {chunk['id']}")
        print(f"     旧内容: {chunk['old_content']}")
        print(f"     新内容: {chunk['new_content']}")
    
    print("\n" + "="*60 + "\n")
    
    # 功能3: 性能评估
    print("功能3: 版本性能评估")
    
    test_queries = [
        {"query": "如何有效减脂?", "expected_answer": "热量赤字"},
        {"query": "增肌需要怎么做?", "expected_answer": "渐进超负荷"},
        {"query": "蛋白质应该吃多少?", "expected_answer": "每公斤体重"},
        {"query": "训练后应该补充什么?", "expected_answer": "蛋白质"},
        {"query": "有氧运动做多久?", "expected_answer": "30-60分钟"},
        {"query": "什么是健康饮食?", "expected_answer": "多样化"},
        {"query": "如何预防运动损伤?", "expected_answer": "热身"}
    ]
    
    perf_v1 = version_manager.evaluate_version_performance("v1.0", test_queries)
    perf_v2 = version_manager.evaluate_version_performance("v2.0", test_queries)
    
    print(f"版本1性能:")
    print(f"  准确率: {perf_v1['overall_metrics']['accuracy']*100:.1f}%")
    print(f"  平均响应时间: {perf_v1['overall_metrics']['avg_response_time']*1000:.1f}ms")
    
    print(f"\n版本2性能:")
    print(f"  准确率: {perf_v2['overall_metrics']['accuracy']*100:.1f}%")
    print(f"  平均响应时间: {perf_v2['overall_metrics']['avg_response_time']*1000:.1f}ms")
    
    print("\n" + "="*60 + "\n")
    
    # 功能4: 性能比较
    print("功能4: 性能比较与建议")
    perf_comparison = version_manager.compare_version_performance("v1.0", "v2.0", test_queries)
    
    print(f"性能比较结果:")
    comp = perf_comparison['performance_comparison']
    print(f"  准确率提升: {comp['accuracy']['improvement']*100:.1f}%")
    print(f"  响应时间变化: {comp['response_time']['improvement']*1000:.1f}ms")
    print(f"  建议: {perf_comparison['recommendation']}")
    
    print("\n" + "="*60 + "\n")
    
    # 功能5: 回归测试
    print("功能5: 回归测试")
    regression_v2 = version_manager.generate_regression_test("v2.0", test_queries)
    
    print(f"回归测试结果:")
    print(f"  测试通过率: {regression_v2['pass_rate']*100:.1f}%")
    print(f"  测试用例数量: {len(regression_v2['test_results'])}")
    
    print(f"\n详细测试结果:")
    for i, result in enumerate(regression_v2['test_results'], 1):
        status = "✓" if result['passed'] else "✗"
        print(f"  {i}. {result['query']} {status}")

if __name__ == "__main__":
    main() 

输出结果

=== 知识库版本管理与性能比较示例(健康健身知识) ===

功能1: 创建知识库版本
版本1信息:
  版本名: v1.0
  描述: 基础版本
  知识切片数量: 3
  平均切片长度: 37字符

版本2信息:
  版本名: v2.0
  描述: 增强版本
  知识切片数量: 6
  平均切片长度: 67字符

============================================================

功能2: 版本差异比较
版本比较结果:
  新增知识切片: 3个
  删除知识切片: 0个
  修改知识切片: 3个

新增的知识切片:
  1. ID: kb_004
     内容: 训练后30-90分钟内是补充蛋白质的窗口期,建议摄入20-40克优质蛋白质,配合快速吸收的碳水化合物,有助于肌肉恢复
和合成。
  2. ID: kb_005
     内容: 有氧运动建议每次30-60分钟,保持中等强度(心率在最大心率的60-70%)。最好结合高强度间歇训练(HIIT)和稳态有氧(LISS)交替进行。
  3. ID: kb_006
     内容: 健康均衡饮食应包含多样化的食物:大量蔬菜和水果、优质蛋白质来源、全谷物碳水化合物、健康脂肪以及充足的水分。

修改的知识切片:
  1. ID: kb_002
     旧内容: 增肌需要渐进式超负荷训练和热量盈余,建议每周进行3-5次力量训练。
     新内容: 增肌需要渐进式超负荷训练和热量盈余。建议每周进行3-5次力量训练,专注复合动作如深蹲、卧推、硬拉和引体向上 
。饮食上每日热量盈余300-500卡路里。
  2. ID: kb_001
     旧内容: 减脂需要创造热量赤字,建议每周进行3-5次有氧运动和2-3次力量训练。
     新内容: 减脂需要创造热量赤字,建议每周进行3-5次有氧运动(如跑步、游泳)和2-3次力量训练。饮食上控制总热量摄入,增
加蛋白质比例,减少精制碳水和添加糖。
  3. ID: kb_003
     旧内容: 蛋白质摄入建议:减脂期每公斤体重1.6-2.2克,增肌期每公斤体重1.6-2.2克。
     新内容: 蛋白质摄入建议:减脂期每公斤体重1.6-2.2克,增肌期每公斤体重1.6-2.2克。优质蛋白来源包括鸡胸肉、鱼、鸡蛋、
豆制品和乳清蛋白粉。

============================================================

功能3: 版本性能评估
版本1性能:
  准确率: 42.9%
  平均响应时间: 134.8ms

版本2性能:
  准确率: 71.4%
  平均响应时间: 128.3ms

============================================================

功能4: 性能比较与建议
性能比较结果:
  准确率提升: 28.6%
  响应时间变化: -4.9ms
  建议: 版本2准确率更高但响应时间较长,需要权衡

============================================================

功能5: 回归测试
回归测试结果:
  测试通过率: 71.4%
  测试用例数量: 7

详细测试结果:
  1. 如何有效减脂? ✓
  2. 增肌需要怎么做? ✗
  3. 蛋白质应该吃多少? ✓
  4. 训练后应该补充什么? ✓
  5. 有氧运动做多久? ✓
  6. 什么是健康饮食? ✓
  7. 如何预防运动损伤? ✗

八、总结

        现代知识库处理是一个融合了信息检索、自然语言处理、机器学习和大数据技术的综合性工程。它不再是后台的静态数据,而是走向前台的、驱动企业智能化的核心生产力工具。

未来的知识库将向着更智能的方向演进:

  1. 多模态知识库:融合文本、图片、表格、视频等多种形式的知识,并提供统一的多模态检索与生成能力。
  2. 个性化知识推荐:根据用户的身份、历史行为、当前上下文,提供动态组合和定制的个性化答案。
  3. 自动化与自主进化:进一步减少人工干预,实现从知识挖掘、质量评估到优化入库的更高程度的自动化,最终形成一个能够自主演进的“知识大脑”。

        通过系统性地应用上述理论与技术,企业可以构建出不仅能说会道,更善解人意、并能持续成长的下一代知识基础设施,最终在激烈的竞争中赢得智能化的优势。

        简单来说,智能时代的知识库管理,就是利用AI技术,让知识库变成一个能听、会说、善思考、会学习的活的系统。它的管理重心从“维护内容”转向了“设计流程和优化体验”,最终目的是让知识这个核心资产,真正高效地流动起来,赋能企业的每一个员工和每一次客户交互。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值