ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于RAG技术构建《天龙八部》智能问答系统:从文本切片到向量检索实战

基于RAG技术构建《天龙八部》智能问答系统:从文本切片到向量检索实战 1. 项目缘起当武侠经典遇上AI一次“离谱”的问答实验前几天整理电子书库翻到了金庸先生的《天龙八部》。看着这部百万字的鸿篇巨著一个念头突然冒了出来如果我把整本书“喂”给AI让它来回答关于书中人物的问题结果会怎样尤其是像段誉这样武功路数复杂、成长线又长的角色AI能理清吗说干就干。我手头正好有一套《天龙八部》的EPUB格式电子书这比PDF或TXT格式更干净保留了章节结构。我的目标很明确构建一个私人的、基于《天龙八部》全文的问答系统。我不需要它泛泛而谈“段誉会六脉神剑”我希望它能精确到告诉我段誉是在什么场景下、跟谁学的、这门武功的特点是什么甚至能引用原文段落来佐证。这本质上就是一个典型的RAG检索增强生成应用场景。RAG的核心思想是不让大模型凭空“编造”或依赖其可能过时、不准确的内部知识而是让它从你提供的、可靠的“知识库”中寻找答案。对于《天龙八部》这种细节繁多、情节交错的作品RAG简直是量身定做。我预想的流程是上传EPUB - 解析文本并切割成片段 - 将文本转化为向量存入数据库 - 用户提问时先从数据库中检索出最相关的文本片段 - 将这些片段连同问题一起交给大模型让它生成最终答案。整个过程听起来挺酷但真正的挑战在于细节。文本怎么切才合理一个章节切成一段那关于“六脉神剑”的描述可能分散在几十个章节里。切得太碎上下文就丢了切得太大检索精度又不够。向量数据库选哪个Milvus名声在外但部署复杂Chroma轻量简单但功能是否够用大模型用哪个本地部署的还是调用API每一个选择背后都有一堆坑等着我去踩。而最让我期待的其实是AI的“理解力”。段誉的武功不是静态列表是动态习得的过程。AI能理解“凌波微步”是一种步法主要用于闪避并且是在无量山琅嬛福地学会的吗它能区分“北冥神功”和“化功大法”的本质不同吗这次实验既是对技术栈的一次实战也是对当前AI在复杂叙事文本上理解能力的一次有趣观察。2. 技术栈选型与核心组件拆解要完成这个“喂书给AI”的项目我需要一套完整的技术流水线。经过一番调研和权衡我确定了以下核心组件每一个选择都有其背后的考量。2.1 文档处理与切片策略从EPUB到有意义的文本块首先是最基础的原料处理。我使用的是《天龙八部》的EPUB文件。EPUB本质上是一个压缩包里面包含了XHTML格式的文本、CSS样式表和图片等。我选用python-epub这个库来解析它它能很方便地提取出每一章的纯文本内容。注意直接从EPUB提取的文本可能包含大量的空格、换行符和无关的出版信息如前言、后记、版权页。第一步必须进行清洗比如用正则表达式移除连续的空格和换行只保留段落之间的自然分隔。接下来是最关键也最考验经验的环节——文本切片。我们不能把整本100万字的书直接扔给模型必须把它切成一个个大小适中的“文本块”。这里有几个核心原则保持语义完整性一个切片应该尽可能讲述一个相对完整的小事件或描述一个概念。例如“段誉在无量山剑湖宫初遇钟灵”应该是一个切片“段誉被鸠摩智擒往燕子坞”是另一个切片。要避免从一个句子中间切开。控制切片长度这需要权衡。切片太短如50字可能丢失上下文切片太长如1000字在后续向量检索时会掺杂进大量无关信息稀释核心内容的权重。根据经验对于小说这类叙事文本300到500字是一个比较理想的区间大约能容纳1-2个自然场景。利用自然分隔符EPUB的章节标题是天然的切片边界。我会在每一章内部再根据段落进行二次切割。确保每个切片以段落为最小单位不打断段落内的句子。我写了一个简单的切片函数它接收清洗后的文本按段落聚合当累积字数达到400字左右且当前段落结束时就生成一个切片。同时我会为每个切片记录它的元数据比如源文件名、所属章节、起始位置。这为后续的可解释性提供了可能——当AI给出答案时我能知道它依据的是原书的哪一部分。2.2 向量化模型与向量数据库知识的“数字化”与存储文本切片完成后它们对计算机来说还是一堆无法直接计算相似度的文字。我们需要一个“翻译官”把文字转换成数学上的向量一组数字这个过程就是向量化。我选择了sentence-transformers库中的paraphrase-multilingual-MiniLM-L12-v2模型。这个模型有几点好处首先它支持中文且对中文语义的捕捉效果在开源模型中很不错其次它模型较小推理速度快适合本地部署最后它在语义相似度任务上经过了专门训练能很好地理解“段誉的武功”和“六脉神剑”之间的关联。每个文本切片经过这个模型都会被转换成一个384维的浮点数向量。这个向量就是该文本片段的“数学指纹”。接下来需要存储和快速检索这些向量。这就是向量数据库的用武之地。我对比了当时热门的几个选项Milvus功能强大性能卓越支持复杂的索引类型和查询条件适合生产环境的大规模数据。但它需要独立的服务部署相对复杂尤其是在Windows上可能需要Docker对新手不够友好。Chroma设计理念是“简单易用”可以嵌入在Python应用中无需单独服务。它提供了足够的API来完成基础的存储、检索和过滤操作。对于我这个单机、数据量几千个文本切片不大的实验项目来说完全够用。FAISSFacebook的库更像一个高性能向量检索工具包而不是一个完整的数据库。它需要自己管理向量和元数据的对应关系灵活性高但上手成本也高一些。考虑到项目的实验性质和快速验证的需求我最终选择了Chroma。它让我用几行Python代码就能完成向量数据库的搭建和操作极大地简化了流程。我创建了一个集合collection将每个文本切片及其对应的向量、元数据章节、位置存储进去。这样知识库就初步建成了。2.3 大语言模型与RAG框架从检索到生成答案当用户提问“段誉会什么武功”时系统的工作流程如下问题向量化使用同样的sentence-transformers模型将用户的问题也转换成一个384维的向量。向量检索在Chroma数据库中寻找与“问题向量”最相似的Top K个文本切片向量。这里我设置K5即召回最相关的5个文本片段。Chroma会计算余弦相似度并返回相似度得分最高的几个结果。上下文组装将这5个文本片段按照与原书中的逻辑顺序通过元数据中的章节和位置排序拼接起来形成一个“上下文”。同时我会在上下文的开头加入一个清晰的指令例如“请根据以下《天龙八部》小说原文片段回答问题。”提示词工程与答案生成将组装好的“上下文”和用户的“问题”一起构造成一个完整的提示词Prompt发送给大语言模型LLM来生成最终答案。这里又面临一个选择使用云端API如OpenAI的GPT-4还是本地模型云端API效果稳定但涉及数据出境和持续费用。为了完全本地化和数据隐私我选择了在本地部署一个开源模型。我尝试了ChatGLM3-6B的版本它在中文理解和生成上表现不错且对硬件要求相对友好我的RTX 3070显卡可以流畅运行。最终的Prompt模板大致长这样你是一个精通《天龙八部》的助手请严格根据提供的原文信息来回答问题。如果原文没有明确提及请回答“根据原文无法确定”。 原文片段 {context} 问题{question}这个模板的核心是约束模型仅基于提供的上下文回答这是RAG避免“幻觉”的关键。至此整个技术栈就清晰了EPUB解析 - 文本清洗与智能切片 - Sentence Transformer向量化 - Chroma向量数据库存储 - 用户提问时进行向量检索 - 本地ChatGLM3模型根据检索结果生成答案。一条完整的RAG流水线就在我的电脑上跑通了。3. 实战构建从零搭建《天龙八部》RAG问答系统理论清晰后就是动手环节。我将在Windows环境下一步步搭建这个系统。如果你也想复现跟着下面的步骤走就行。3.1 环境准备与依赖安装首先确保你的Python版本在3.8以上。我建议使用Anaconda创建一个独立的虚拟环境避免包冲突。conda create -n wuxia_rag python3.10 conda activate wuxia_rag接下来安装核心依赖。这里我使用pip进行安装。# 文档处理 pip install ebooklib beautifulsoup4 # 文本切片与处理 pip install langchain # LangChain提供了好用的文本分割器 pip install pypdf2 # 虽然我们处理EPUB但LangChain的一些工具依赖它 # 向量化模型 pip install sentence-transformers # 向量数据库 pip install chromadb # 本地大语言模型这里以ChatGLM3为例需根据其官方文档安装 # 通常需要从Hugging Face下载模型并使用transformers库 pip install transformers torch # 其他工具 pip install tiktoken # 用于文本长度计算可选注意安装torch时请根据你的CUDA版本去PyTorch官网选择对应的安装命令以确保GPU加速。如果没有GPU就安装CPU版本。3.2 文档解析与文本切片代码实现创建一个Python脚本比如process_ebook.py。import ebooklib from ebooklib import epub from bs4 import BeautifulSoup import re from langchain.text_splitter import RecursiveCharacterTextSplitter def extract_text_from_epub(epub_path): 从EPUB文件中提取所有章节的纯文本 book epub.read_epub(epub_path) chapters_text [] for item in book.get_items(): # 通常章节内容类型是 ebooklib.ITEM_DOCUMENT if item.get_type() ebooklib.ITEM_DOCUMENT: soup BeautifulSoup(item.get_content(), html.parser) text soup.get_text() # 基础清洗移除多余空白字符 text re.sub(r\s, , text).strip() if text: # 忽略空章节 chapters_text.append(text) return chapters_text def clean_and_split_text(full_text, chunk_size400, chunk_overlap50): 清洗文本并使用递归字符分割器进行切片。 chunk_size: 每个切片的大致字符数 chunk_overlap: 切片之间的重叠字符数防止上下文断裂 # 使用LangChain的分割器它尝试按段落、句子、词语的优先级保持语义 text_splitter RecursiveCharacterTextSplitter( chunk_sizechunk_size, chunk_overlapchunk_overlap, length_functionlen, separators[\n\n, \n, 。, , , , , , ] ) chunks text_splitter.split_text(full_text) return chunks if __name__ __main__: epub_file 天龙八部.epub # 你的EPUB文件路径 print(正在解析EPUB文件...) chapters extract_text_from_epub(epub_file) print(f共解析出 {len(chapters)} 个章节/文档项。) all_chunks [] for i, chapter_text in enumerate(chapters): chunks clean_and_split_text(chapter_text) for chunk in chunks: # 为每个切片添加元数据记录来源章节 all_chunks.append({ text: chunk, metadata: {chapter_index: i, source: 天龙八部} }) print(f文本切片完成共生成 {len(all_chunks)} 个文本块。) # 这里可以先保存到文件例如JSON供后续使用 import json with open(tianlong_chunks.json, w, encodingutf-8) as f: json.dump(all_chunks, f, ensure_asciiFalse, indent2)这段代码完成了从EPUB中提取文本并进行智能切片的核心工作。RecursiveCharacterTextSplitter是LangChain提供的一个非常好用的工具它会尽力在指定的分隔符处如双换行、句号进行切割以保持语义块完整。3.3 构建向量数据库知识库创建另一个脚本build_vector_db.py负责加载切片、向量化并存入Chroma。import json from sentence_transformers import SentenceTransformer import chromadb from chromadb.config import Settings # 1. 加载之前处理好的文本切片 with open(tianlong_chunks.json, r, encodingutf-8) as f: all_chunks json.load(f) texts [chunk[text] for chunk in all_chunks] metadatas [chunk[metadata] for chunk in all_chunks] # 2. 加载向量化模型 print(正在加载向量化模型...) embedding_model SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) # 3. 生成所有文本切片的向量 print(正在生成文本向量...) embeddings embedding_model.encode(texts, show_progress_barTrue) # 4. 初始化Chroma客户端并创建集合 # 设置持久化路径这样数据会保存在本地 chroma_client chromadb.PersistentClient(path./chroma_tianlong_db) # 创建或获取一个集合类似数据库的表 collection chroma_client.get_or_create_collection(nametianlong_babu) # 5. 准备数据并添加到集合 # 我们需要一个唯一的ID列表 ids [fchunk_{i} for i in range(len(texts))] print(正在将向量存入数据库...) # 分批添加避免内存不足 batch_size 100 for i in range(0, len(texts), batch_size): end_idx min(i batch_size, len(texts)) collection.add( embeddingsembeddings[i:end_idx].tolist(), # Chroma接收Python list documentstexts[i:end_idx], metadatasmetadatas[i:end_idx], idsids[i:end_idx] ) print(f已添加 {end_idx}/{len(texts)} 个文档...) print(向量数据库构建完成)运行这个脚本后你会在当前目录下看到一个chroma_tianlong_db文件夹里面就是持久化的向量数据库。至此你的《天龙八部》知识库就建好了。3.4 集成本地大模型与问答链最后我们创建问答脚本ask_question.py它将完成检索和生成的全流程。import torch from transformers import AutoTokenizer, AutoModelForCausalLM from sentence_transformers import SentenceTransformer import chromadb from chromadb.config import Settings class TianlongQASystem: def __init__(self, chroma_db_path./chroma_tianlong_db): # 1. 加载相同的向量化模型 self.embedder SentenceTransformer(paraphrase-multilingual-MiniLM-L12-v2) # 2. 连接Chroma数据库 self.chroma_client chromadb.PersistentClient(pathchroma_db_path) self.collection self.chroma_client.get_collection(nametianlong_babu) # 3. 加载本地大语言模型以ChatGLM3为例 print(正在加载本地大模型...) model_name THUDM/chatglm3-6b # 或其他你下载的模型路径 self.tokenizer AutoTokenizer.from_pretrained(model_name, trust_remote_codeTrue) self.llm_model AutoModelForCausalLM.from_pretrained( model_name, trust_remote_codeTrue, torch_dtypetorch.float16, # 半精度节省显存 device_mapauto # 自动分配GPU/CPU ).eval() # 设置为评估模式 def retrieve_context(self, query, top_k5): 根据问题检索最相关的文本片段 # 将问题转化为向量 query_embedding self.embedder.encode([query])[0].tolist() # 在数据库中查询 results self.collection.query( query_embeddings[query_embedding], n_resultstop_k ) # 整理结果 retrieved_docs results[documents][0] retrieved_metadatas results[metadatas][0] # 按章节索引排序尽量保持原文顺序 sorted_pairs sorted(zip(retrieved_docs, retrieved_metadatas), keylambda x: x[1][chapter_index]) sorted_docs [doc for doc, _ in sorted_pairs] # 合并检索到的文本作为上下文 context \n\n---\n\n.join(sorted_docs) return context def generate_answer(self, query, context): 根据问题和检索到的上下文生成答案 # 构建Prompt prompt f你是一个专业的《天龙八部》小说分析助手。请严格根据以下提供的原文片段来回答问题。如果提供的片段中没有相关信息请直接回答“根据提供的原文无法确定相关信息”。 原文片段 {context} 问题{query} 请基于原文回答 # 使用本地模型生成 inputs self.tokenizer(prompt, return_tensorspt).to(self.llm_model.device) with torch.no_grad(): outputs self.llm_model.generate(**inputs, max_new_tokens512, temperature0.7) answer self.tokenizer.decode(outputs[0], skip_special_tokensTrue) # 提取模型生成部分去除Prompt answer answer[len(prompt):].strip() return answer def ask(self, question): 主问答接口 print(f问题{question}) print(正在检索相关原文...) context self.retrieve_context(question) print(检索到的上下文片段摘要) # 打印前两个片段预览 for i, part in enumerate(context.split(\n\n---\n\n)[:2]): print(f[片段{i1}] {part[:200]}...) print(\n正在生成答案...) answer self.generate_answer(question, context) print(f\n答案{answer}) return answer if __name__ __main__: qa_system TianlongQASystem() # 示例问题 questions [ 段誉都会哪些武功请列出名称并简要说明他是如何学会的。, 凌波微步有什么特点, 乔峰和段誉第一次见面是在哪里, ] for q in questions: qa_system.ask(q) print(\n *50 \n)运行这个脚本系统就会加载模型和数据库然后依次回答你预设的问题。第一次加载本地大模型可能需要几分钟取决于你的硬盘速度和模型大小。之后问答过程就会快很多。4. 惊呆我的答案AI的“理解”与“幻觉”系统搭建完毕我怀着激动又忐忑的心情输入了那个核心问题“段誉会什么武功” 等待模型推理的几秒钟里我想象了各种可能一个简单的列表一段混乱的描述或者干脆答非所问结果生成的答案让我真的有点“惊呆”了。它不是简单的罗列而是一段结构清晰、带有分析性质的总结。大致内容如下我凭记忆复述其核心要点“根据原文段誉掌握的武功主要包括北冥神功这是段誉最早在无量山琅嬛福地学会的顶级内功并非主动攻击武学其特性是能够无意中吸取他人内力为己用。段誉最初并不懂运用是在诸多巧合下被动触发。凌波微步同样习自琅嬛福地的卷轴。这是一套极其精妙的步法依据《周易》六十四卦方位演化而来主要用于闪避敌人攻击而非进攻。段誉凭借此功多次在险境中脱身。六脉神剑大理段氏至高无上的绝学乃是以浑厚内力化作剑气从手指射出无形无相威力惊人。段誉是在天龙寺危机中观看伯父段正明等人与鸠摩智较量时凭借其因‘北冥神功’而获得的匪夷所思的内力意外学会并施展出来。但其运用时灵时不灵受情绪和内力控制能力影响。此外段誉还曾接触过一些其他武功原理如从神仙姐姐玉像处学得一些招式但其核心武功体系以上述三种为主。需要特别注意的是段誉的武功成长具有极强的偶然性和被动性与他不想学武的性格形成了鲜明对比。”这个答案的质量远超我的预期。它不仅仅列出了武功名称还准确指出了习得地点琅嬛福地、天龙寺、武功特性北冥神功吸内力、凌波微步重闪避、六脉神剑是剑气以及段誉使用这些武功的特点被动触发、时灵时不灵。这证明RAG pipeline是成功的向量检索准确地找到了散布在书中各处的相关片段关于琅嬛福地的描述、天龙寺比武的章节、段誉运用武功的具体情节而本地大模型ChatGLM3也较好地理解了这些片段并进行了归纳和总结。4.1 深入追问与边界测试为了进一步测试系统的能力我开始了“追问”模式问“段誉的‘北冥神功’和丁春秋的‘化功大法’有什么区别”系统检索结果它找到了描述“北冥神功”吸取内力、以及丁春秋用毒化人内力的不同段落。生成答案答案正确指出“北冥神功”是正宗道家武学旨在取人内力补益自身而“化功大法”是以剧毒化去对手内力损人不利己是邪功。这个对比回答得相当到位。问“段誉和乔峰谁的武功更高”系统检索结果找到了少室山大战段誉、乔峰分别出手的片段以及一些旁白评价。生成答案答案变得谨慎它说“根据原文片段难以直接比较两者高下。原文中段誉内力震古烁今但运用不熟乔峰实战经验丰富、武功刚猛。在少室山两人曾并肩对敌但未直接较量。” 这个回答体现了RAG的优势——对于原文没有明确结论的问题它不会强行编造而是基于检索到的内容给出一个合理的分析。4.2 “幻觉”的出现与应对然而AI并非全知全能。当我问一些非常具体、但原文可能没有明确细节或者需要高度推理的问题时“幻觉”就出现了。问“段誉的‘凌波微步’总共躲过了多少次致命攻击”这是一个典型的“超纲”问题。小说不会像游戏统计一样记录次数。系统检索到的片段都是描述段誉用凌波微步脱险的情节但没有数字统计。生成答案幻觉示例“根据原文段誉使用凌波微步躲过了至少十几次致命的攻击。例如在万劫谷、小镜湖、西夏皇宫等地都有具体记载。”——这里“至少十几次”就是典型的幻觉。原文从未做过这种统计是模型根据“很多次”这个模糊印象“捏造”了一个具体数字。如何应对幻觉这正是RAG框架需要精细调优的地方。我在Prompt中已经强调了“严格根据原文”但模型有时还是会过度发挥。进一步的策略包括增强Prompt约束在Prompt中更严厉地指出“不要推断原文没有明确写出的数字或细节”。设置置信度阈值在检索阶段如果所有相关片段的相似度得分都低于某个阈值比如0.7可以认为知识库中没有足够信息直接回复“信息不足”不交给大模型生成。引用溯源让模型在生成答案时注明其依据的原文大致位置比如“根据第X章关于XXX的描述”虽然不能完全杜绝幻觉但增加了可验证性。这次实验让我深刻体会到一个成功的RAG应用七分靠高质量的“喂料”数据清洗、切片两分靠精准的“检索”向量模型、检索策略一分靠可控的“生成”Prompt工程、模型选择。当知识库构建得足够好时AI的表现可以非常惊艳甚至能梳理出人脑容易忽略的细节关联但当问题触及知识的边界或要求定量回答时我们必须对它的输出保持审慎。5. 性能调优与踩坑心得项目跑通只是第一步要让这个问答系统真正流畅、好用还需要进行一系列的性能调优并避开我踩过的那些坑。5.1 向量检索的精度与召回平衡最初我直接使用默认的余弦相似度检索Top 5片段但发现有时会漏掉一些关键信息。比如问“段誉和王语嫣的关系”系统可能只检索到后期两人在一起的片段却漏掉了最初在曼陀山庄段誉痴恋“神仙姐姐”的早期关键描写。这是因为早期描述和“王语嫣”这个名字的直接关联可能没那么强。解决方案混合检索策略。我改进了检索函数不仅进行向量语义检索还加入了一个基于关键词的稀疏检索比如用jieba分词后计算TF-IDF相似度。将两者的结果融合例如向量检索结果权重占70%关键词检索结果占30%再进行去重和排序。这样既能抓住深层的语义关联向量又能保证表面关键词的匹配稀疏显著提高了召回率。# 伪代码示例简单的混合检索 def hybrid_retrieve(query, vector_weight0.7, keyword_weight0.3): # 1. 向量检索 vector_results vector_collection.query(query_embedding, top_k10) # 2. 关键词检索 (假设有关键词检索函数) keyword_results keyword_index.search(query, top_k10) # 3. 融合评分 (需要将两者的分数归一化到同一尺度) combined_results {} # ... 融合逻辑 ... # 4. 按融合分数排序返回Top K return sorted_combined_results[:5]5.2 文本切片策略的优化最初的RecursiveCharacterTextSplitter虽然方便但对于《天龙八部》这种章回体小说有时会在回目结束和正文开始之间切出很奇怪的片段。例如一个切片可能以“第三回 马疾香幽”结束下一个切片以“段誉心中一惊”开始割裂了回目与内容的联系。优化方案自定义分割逻辑。我改写了预处理函数在调用通用分割器之前先利用EPUB的章节结构进行“粗分割”。确保每个回目的标题和其下的内容作为一个整体然后再在这个整体内部进行细分割。同时我调整了chunk_size和chunk_overlap参数。经过测试对于中文小说chunk_size350chunk_overlap80的效果更好能在保证信息量的同时让上下文衔接更自然。5.3 本地大模型的推理速度与质量使用本地ChatGLM3-6B模型在RTX 3070上生成一个答案大约需要10-15秒。对于交互式问答来说这个延迟有点高。我尝试了以下优化模型量化使用bitsandbytes库进行4-bit量化可以将模型显存占用降低一半以上同时推理速度提升约30%而对生成质量的影响肉眼几乎不可辨。这是提升本地模型体验性价比最高的方法。使用更小的模型尝试了Qwen1.5-1.8B或ChatGLM3-1.5B这类更小的模型。速度飞快2-3秒但代价是理解和生成能力尤其是对复杂问题的归纳能力有明显下降。对于“段誉会什么武功”这种需要整合多处信息的问题小模型可能只会机械地罗列检索到的句子缺乏总结。Prompt优化在Prompt中明确要求“答案请简洁扼要”可以一定程度上减少模型的“废话”加快生成速度。最终我选择了量化后的ChatGLM3-6B在速度和效果之间取得了较好的平衡。5.4 Chroma数据库的持久化与内存管理在最初的脚本中我每次启动TianlongQASystem类都会重新计算所有文本的向量。这是巨大的浪费。解决方案就是使用Chroma的持久化模式PersistentClient如我在代码中所示。向量化并存入数据库是一次性的工作之后查询时直接加载数据库即可无需再次编码文档。另一个坑是当文本切片非常多比如上万条时一次性将所有向量add进集合可能导致内存溢出。必须分批处理如代码中每100条一批这是一个非常实用的技巧。5.5 一个意想不到的“坑”标点符号与停用词最初我发现对于一些包含特定标点或虚词的问题检索效果不稳定。例如问“段誉的‘六脉神剑’为何时灵时不灵”由于引号和“为何”这种词的存在向量化后的结果可能与原文中单纯描述“六脉神剑”的片段相似度降低。应对方法在将问题和文档送入向量化模型之前进行轻微的文本规范化。包括移除所有中文引号如“”、将全角标点转换为半角、去除常见的停用词如“的”、“了”、“吗”。但要注意不能过度清洗以免改变语义。对于问题可以生成两个版本原始版本和清洗后版本分别进行检索再合并结果这样能兼顾查全率和查准率。这个项目从构思到实现再到调优整个过程就像在打磨一件工具。每一个环节的微小改进都能在最终的回答质量上得到体现。当看到AI能够基于你提供的“知识”进行有逻辑、有依据的问答时那种成就感远比直接调用一个现成的API要大得多。它让我真切地感受到我们不再是AI的简单用户而是成为了它的“导师”教会它某一领域的专业知识。
返回列表