当前位置: 首页 > news >正文

做网站是三网合一有什么优势网站建设公司名称

做网站是三网合一有什么优势,网站建设公司名称,网站搭建完手机访问,如何做静态网站首先叠甲#xff0c;本文只是用于学习目的#xff0c;不用于其他用途 前言 项目目标 学会 RAG 项目的构建流程#xff1a; 从数据获取到最终部署的完整端到端流程。学习影响 RAG 项目性能的因素#xff1a; 深入理解数据质量、嵌入模型、检索策略、重排序以及 Prompt 工程… 首先叠甲本文只是用于学习目的不用于其他用途 前言 项目目标 学会 RAG 项目的构建流程 从数据获取到最终部署的完整端到端流程。学习影响 RAG 项目性能的因素 深入理解数据质量、嵌入模型、检索策略、重排序以及 Prompt 工程等关键因素。学习 RAG 和 LoRA 微调的结合场景 理解何时以及如何将这两种技术结合以实现最佳效果。 技术栈 RAG 框架 LlamaIndex向量数据库 ChromaDB知识库数据 网上爬取的劳动合同法相关数据大语言模型 (LLM) Qwen/Qwen1.5-1.8B-Chat嵌入模型 sungw111/text2vec-base-chinese-sentence重排序模型 BAAI/bge-reranker-large 如果对于第 RAG 和微调不太清晰我们已经在另一篇文章 RAG 和 微调如何抉择进行了介绍如果对于 RAG 流程不太清晰我们已经在RAG 流程进行了介绍我们使用LlamaIndex进行构建 RAG 项目并已经将LlamaIndex学习笔记分享了出来对于向量数据库我们已经在Chroma 向量数据库学习笔记分享了出来 方案设计 项目阶段 1: 知识库构建 此阶段目标是将原始、非结构化的法律文本转化为可供向量检索的结构化数据并进行持久化存储。 1.1 数据爬取 目标 获取劳动合同法相关法律条文、司法解释、典型案例、权威解读等文本。方法对比 方法优点缺点手动收集/下载精度高数据质量可控。效率极低数据量受限难以更新。通用爬虫工具灵活性强可定制化能处理复杂网站结构。需要编程技能维护成本较高。无代码/低代码平台入门简单操作直观。灵活性有限难以处理反爬机制或复杂数据提取。 最适合的方法及理由 推荐 通用爬虫工具 (如 Python 的 Scrapy 或 BeautifulSoup)。理由 劳动合同法资料多分布在政府官网、法院判例库、法律网站等这些网站结构相对固定但可能存在反爬机制。通用爬虫工具能提供足够的灵活性和效率来批量获取数据同时满足开源免费的要求。对于无法通过爬虫获取的少量权威资料可少量手动下载。 本文爬取地址 1.2 数据处理 (清洗与预处理) 本小节为可选 目标 清除爬取数据中的噪音统一格式提取必要信息。方法对比 方法优点缺点正则表达式/字符串操作直观效率高适合简单、规则化清洗。难以处理复杂、不规则文本。基于规则的解析器专门用于解析结构化数据 (如 HTML/XML)。仅限于结构化数据对纯文本无效。开源 NLP 库能进行深层次语义理解和结构化。复杂性高需要 NLP 知识。 最适合的方法及理由 推荐 使用正则表达式进行数据处理。理由 法律文本往往具有一定的结构如下表示他总是由第 N 条来表示一条法律条文因此采用正则表达式高效且有效处理即可。 p  第一条 为了保护劳动者的合法权益调整劳动关系建立和维护适应社会主义市场经济的劳动制度促进经济发展和社会进步根据宪法制定本法。/p p  第二条 在中华人民共和国境内的企业、个体经济组织以下统称用人单位和与之形成劳动关系的劳动者适用本法。/p1.3 数据向量化并持久化 目标 将处理后的文本转化为嵌入向量并可靠地存储在向量数据库中。 采用嵌入模型进行词嵌入然后调用向量数据库存储即可对于嵌入模型和向量数据库的选择见后文此处暂时不做过多分析 项目阶段 2: 知识库处理分块策略对比 此阶段目标是优化文本分块以提高检索时的语义准确性和 LLM 处理效率。 目标 确定最适合劳动合同法文本的分块策略。方法对比 分块策略优点缺点适用场景固定大小分块实现简单可预测。易切断语义影响上下文连贯性。快速原型文本无强结构。按句子/段落分块保持基本语义单位。段落仍可能长句子过于碎片化。通用文本语义单元明确。递归分块尝试保留语义结构灵活。仍可能切断复杂逻辑需精心选择分隔符。结构化与非结构化混杂文本。基于结构化信息分块最能保持法律文本的逻辑完整性。需要复杂的前期数据结构识别。强结构化法律法规、判例。小块-大上下文策略 (SWR/AMR)索引小块精准传递大上下文给 LLM。实现稍复杂需要额外处理逻辑。兼顾检索效率与生成质量。 最适合的方法及理由 推荐 基于结构化信息分块真正使用 利用法律文本的明确结构如“第X条”、“第Y款”进行分块确保每个块都是一个完整的法律概念。这是法律文本特有的优势。 递归分块对于结构不明确的解读性文本或长段落使用 LlamaIndex 的 RecursiveCharacterTextSplitter 进行二次分割以确保块大小适中。 小块-大上下文策略 (高级优化)索引时使用较小的语义单位如句子或短条款但在检索到这些小单位后动态地扩展到包含更多上下文的大块提供给 LLM。这能平衡检索效率小块嵌入更精准和生成质量大上下文信息更丰富。 理由 法律文本的特点是严谨的逻辑结构。简单分块容易破坏这种结构导致 LLM 无法获取完整的法律背景。 对于2 和 3 在该项目中不再使用理由法律条文每条都比较短因此只需要使用结构化信息分块保证条文的完整性即可 项目阶段 3: 模型选择 此阶段目标是选择并配置 RAG 流程中的核心开源 AI 模型 注意这里我们采用的都是开源免费大模型并且不会选择很大的模型实操会做更详细的说明 3.1 嵌入模型选择 目标 获得高质量的文本嵌入准确捕捉法律文本的语义相似性。方法对比 嵌入模型系列优点缺点推荐模型示例BGE (BAAI General Embeddings)MTEB 排行榜领先性能优异支持多种语言有专门针对中英文的模型开源免费可本地部署。需要一定的硬件资源GPU进行推理。BAAI/bge-large-zh-v1.5 (中文)BAAI/bge-large-en-v1.5 (英文)E5 (Embed Everything)性能优秀通用性强有多语言版本开源免费可本地部署。性能略低于 BGE但在某些任务上表现出色。intfloat/multilingual-e5-largeMiniLM (Sentence Transformers)模型体积小推理速度快内存占用低适合资源有限的环境。性能上可能略逊于 BGE 和 E5 的大模型。sentence-transformers/all-MiniLM-L6-v2Cosine Sentence专门针对中文句子训练模型相较于前面模型较为轻量长度限制最大序列长度为 256sungw111/text2vec-base-chinese-sentence 最适合的方法及理由 推荐 sungw111/text2vec-base-chinese-sentence理由 通常嵌入模型对项目的影响较小主要因素是由于语言的限制该项目法律条文为中文因此采用该模型最为合适。 3.2 问答模型选择 (LLM) 目标 选择一个能理解法律上下文、遵守指令并生成准确、专业答案的开源 LLM。方法对比 开源 LLM 系列优点缺点推荐模型示例Llama 3 (Meta)强大的通用推理能力指令遵循能力好社区活跃模型版本多样。需要较高的硬件资源GPU在某些特定领域可能需微调。meta-llama/Llama-3-8B-Instruct (8B版本)brmeta-llama/Llama-3-70B-Instruct (性能更强资源要求更高)Qwen (阿里)强大的中文能力在中文法律语料上有较好表现模型版本丰富。英文能力可能略逊于 Llama 系列资源要求较高。Qwen/Qwen2-7B-Instruct 或Qwen/Qwen1.5-1.8B-ChatMistral (Mistral AI)轻量级但高性能推理速度快在英文任务上表现出色。中文能力相对较弱有微调版本资源要求中等。mistralai/Mistral-7B-Instruct-v0.2Baichuan2 (百川智能)优秀的中文能力在中文通用领域表现好。更新迭代不如 Llama 3 频繁在英文能力上相对弱势。baichuan-inc/Baichuan2-7B-Chat 最适合的方法及理由 推荐 Qwen/Qwen2-7B-Instruct 或Qwen/Qwen1.5-1.8B-Chat (取决于硬件条件)。理由 Qwen2 是目前开源 LLM 中性能最顶尖的系列之一它们在通用推理、指令遵循和多轮对话方面表现出色是构建 RAG 助手的坚实基础。Qwen2 在中文处理上优势明显。选择7B或 1.5-1.8B-Chat版本取决于显存条件。 3.3 重排序模型选择 (Re-ranker) 目标 对初步检索结果进行二次精细排序提高相关性。方法对比 重排序模型类型优点缺点推荐模型示例开源交叉编码器性能显著优于仅向量相似度免费可本地部署能捕捉查询和文档之间更复杂的交互。计算成本较高需要为每个查询-文档对单独推理推理速度相对较慢。cross-encoder/ms-marco-MiniLM-L-6-v2brBAAI/bge-reranker-base无重排序实现简单计算成本最低。精度相对较低可能将不那么相关的文档排在前面。N/A 最适合的方法及理由 推荐 cross-encoder/ms-marco-MiniLM-L-6-v2 或 BAAI/bge-reranker-base。理由 对于学习项目免费且高性能的开源交叉编码器是理想选择。它们能够显著提升检索结果的准确性帮助理解重排序的价值。MiniLM 模型相对轻量适合初步实验。BGE Re-ranker 则提供更强大的性能。 项目阶段 4: 项目其他技术选择 此阶段巩固 RAG 框架和向量数据库的选择。 4.1 RAG 框架选择 目标 选择一个功能全面、易于使用且适合 RAG 流程开发的开源框架。方法对比 RAG 框架优点缺点LlamaIndex专注于数据摄取、索引和检索提供丰富的 Data Loaders、Node Parser、各种索引类型、Retriever 和 Response Synthesizer社区活跃文档丰富。相对 LangChain在 Agent 和 Chain 方面的抽象可能稍弱但持续改进。LangChain功能非常全面不仅包括 RAG还涵盖 Agent、Chain、Memory 等生态系统庞大Agent 方面的能力更强。抽象层级较多学习曲线可能稍陡峭早期版本稳定性问题较多。 最适合的方法及理由 推荐 LlamaIndex。理由 LlamaIndex 的设计理念更侧重于数据与 LLM 的连接其在数据索引、检索和上下文管理方面的抽象非常清晰和强大这正是 RAG 项目的核心。对于“学会 RAG 项目的构建流程”这一目标LlamaIndex 能提供更直接和聚焦的学习体验且完全开源免费。 对于LlamaIndex和LangChain更详细的对比请参见 4.2 向量数据库选择 目标 选择一个可靠、易于使用的开源向量数据库进行知识库存储。方法对比 向量数据库优点缺点适用场景ChromaDB嵌入式极易上手轻量级支持持久化社区活跃与 LlamaIndex/LangChain 集成良好。不适合大规模分布式部署和高并发场景性能不如专业分布式数据库。学习项目原型开发小规模应用。FAISS免费高性能纯 C 实现绑定了 Python适合内存内高性能检索。不支持持久化需手动保存/加载索引仅支持向量存储无元数据过滤等功能。内存内高性能检索不关注持久化和元数据。Milvus/Zilliz开源高可用弹性伸缩支持大规模向量检索和分布式部署功能丰富过滤、标量字段索引。部署和运维复杂资源消耗大对学习项目来说初期投入较大。大规模、生产级 RAG 系统高并发、高可用。Weaviate开源原生支持向量存储和元数据索引语义搜索能力强提供 GraphQL API。部署相对复杂资源消耗较高。需要复杂元数据过滤关注语义搜索能力的生产级应用。 最适合的方法及理由 推荐 ChromaDB。理由 ChromaDB 的嵌入式特性使其成为学习和原型开发的最佳选择。它无需复杂部署和管理直接作为 Python 库即可使用能够大幅降低项目初期门槛完全符合“学习 RAG 项目构建流程”的需求。同时它支持数据持久化保证了知识库的可靠存储且完全免费开源。 项目阶段 5: 项目评估 目标 量化 RAG 系统的性能并为持续优化提供依据。评估指标 检索准确性 (Retrieval Precision/Recall) 召回的文档是否与查询相关最相关的文档是否被召回。答案忠实度 (Faithfulness) LLM 生成的答案是否完全基于检索到的上下文没有编造信息幻觉。答案相关性 (Answer Relevance) LLM 生成的答案是否直接、完整且流畅地回答了用户问题。效率指标 延迟 (Latency)token 消耗量。 评估工具 (开源免费) RAGAS 专门用于 RAG 系统评估的开源框架可评估答案忠实度、答案相关性、上下文精度、上下文召回率等。LlamaIndex 内置评估工具 提供 ResponseEvaluator, FaithfulnessEvaluator 等可配合自定义评估数据进行使用。 评估流程 构建测试集 收集一组具有代表性的劳动合同法问题并人工标注其预期答案和/或相关文档。自动化评估 使用 RAGAS 或 LlamaIndex 评估工具进行自动化评估。人工审核 对于关键指标如幻觉率、答案准确性进行严格的人工抽样审核尤其是在法律领域这至关重要。反馈循环 根据评估结果识别性能瓶颈并反馈到数据处理、分块策略、模型选择等阶段进行优化。 整体结构图 (Mermaid) #mermaid-svg-8tKTx5EXzPPIS8A6 {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .error-icon{fill:#552222;}#mermaid-svg-8tKTx5EXzPPIS8A6 .error-text{fill:#552222;stroke:#552222;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edge-thickness-normal{stroke-width:2px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edge-thickness-thick{stroke-width:3.5px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edge-pattern-solid{stroke-dasharray:0;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edge-pattern-dashed{stroke-dasharray:3;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edge-pattern-dotted{stroke-dasharray:2;}#mermaid-svg-8tKTx5EXzPPIS8A6 .marker{fill:#333333;stroke:#333333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .marker.cross{stroke:#333333;}#mermaid-svg-8tKTx5EXzPPIS8A6 svg{font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .label{font-family:"trebuchet ms",verdana,arial,sans-serif;color:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .cluster-label text{fill:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .cluster-label span{color:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .label text,#mermaid-svg-8tKTx5EXzPPIS8A6 span{fill:#333;color:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .node rect,#mermaid-svg-8tKTx5EXzPPIS8A6 .node circle,#mermaid-svg-8tKTx5EXzPPIS8A6 .node ellipse,#mermaid-svg-8tKTx5EXzPPIS8A6 .node polygon,#mermaid-svg-8tKTx5EXzPPIS8A6 .node path{fill:#ECECFF;stroke:#9370DB;stroke-width:1px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .node .label{text-align:center;}#mermaid-svg-8tKTx5EXzPPIS8A6 .node.clickable{cursor:pointer;}#mermaid-svg-8tKTx5EXzPPIS8A6 .arrowheadPath{fill:#333333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edgePath .path{stroke:#333333;stroke-width:2.0px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .flowchart-link{stroke:#333333;fill:none;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edgeLabel{background-color:#e8e8e8;text-align:center;}#mermaid-svg-8tKTx5EXzPPIS8A6 .edgeLabel rect{opacity:0.5;background-color:#e8e8e8;fill:#e8e8e8;}#mermaid-svg-8tKTx5EXzPPIS8A6 .cluster rect{fill:#ffffde;stroke:#aaaa33;stroke-width:1px;}#mermaid-svg-8tKTx5EXzPPIS8A6 .cluster text{fill:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 .cluster span{color:#333;}#mermaid-svg-8tKTx5EXzPPIS8A6 div.mermaidTooltip{position:absolute;text-align:center;max-width:200px;padding:2px;font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:12px;background:hsl(80, 100%, 96.2745098039%);border:1px solid #aaaa33;border-radius:2px;pointer-events:none;z-index:100;}#mermaid-svg-8tKTx5EXzPPIS8A6 :root{--mermaid-font-family:"trebuchet ms",verdana,arial,sans-serif;}#mermaid-svg-8tKTx5EXzPPIS8A6 .tech*{fill:#4cc9f0!important;stroke:#1a1a2e!important;color:#1a1a2e!important;font-weight:bold!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .tech span{fill:#4cc9f0!important;stroke:#1a1a2e!important;color:#1a1a2e!important;font-weight:bold!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .data*{fill:#e94560!important;stroke:#fff!important;color:#fff!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .data span{fill:#e94560!important;stroke:#fff!important;color:#fff!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .eval*{fill:#3a86ff!important;stroke:#fff!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .eval span{fill:#3a86ff!important;stroke:#fff!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .deploy*{fill:#2ec4b6!important;stroke:#1a1a2e!important;stroke-width:2px!important;}#mermaid-svg-8tKTx5EXzPPIS8A6 .deploy span{fill:#2ec4b6!important;stroke:#1a1a2e!important;stroke-width:2px!important;} 是 反馈 否 项目启动 知识库构建 模型选择 RAG系统搭建 项目评估 LoRA微调 数据爬取 数据清洗 结构化分块 向量化 ChromaDB存储 嵌入模型text2vec-base-chinese Qwen1.5-1.8B-Chat bge-reranker LlamaIndex框架 检索模块 重排序模块 生成模块 RAGAS评估 人工审核 性能优化 需微调? 法律QA数据集 PEFT微调 部署上线 LoRA 微调的介入时机 当发现使用开源 LLM 结合 RAG其在 法律领域的专业术语、回答风格、特定任务如案例总结、法条解释的结构化输出方面 仍有欠缺时可以考虑对问答模型 (LLM) 进行 LoRA 微调。 注意真实项目中我们首先应该考虑的是模型是不是使用更好的模型 通过这种方式RAG 负责提供最新的事实知识而 LoRA 微调则使 LLM 能够以更专业的“法律助手”身份来消化和呈现这些知识达到协同增效的效果。 项目实现 1. 知识库构建 爬虫并保存数据为json文件 def fetch_and_parse(url):# 请求网页response requests.get(url)# 设置网页编码格式response.encoding utf-8# 解析网页内容soup BeautifulSoup(response.text, html.parser)# 提取正文内容content soup.find_all(p)# 初始化存储数据data []# 提取文本并格式化for para in content:text para.get_text(stripTrue)if text: # 只处理非空文本# 根据需求格式化内容data.append(text)# 将data列表转换为字符串data_str \n.join(data)return data_strdef extract_law_articles(data_str):# 正则表达式匹配每个条款号及其内容pattern re.compile(r第([一二三四五六七八九十零百])条.*?(?\n第|$), re.DOTALL)# 初始化字典来存储条款号和内容lawarticles {}# 搜索所有匹配项for match in pattern.finditer(data_str):articlenumber match.group(1)articlecontent match.group(0).replace(第 articlenumber 条, ).strip()lawarticles[f中华人民共和国劳动法 第{articlenumber}条] articlecontent# 转换字典为JSON字符串jsonstr json.dumps(lawarticles, ensure_asciiFalse, indent4)return jsonstrif __name__ __main__:# 请求页面url https://www.gov.cn/banshi/2005-05/25/content_905.htmdata_str fetch_and_parse(url)json_str extract_law_articles(data_str)print(json_str) 保存的json数据结果为 [{中华人民共和国劳动合同法 第一条: 为了完善劳动合同制度...,},{中华人民共和国劳动法 第一条: 为了...,}]加载json数据 def load_and_validate_json_files(data_dir: str) - List[Dict]:加载并验证JSON法律文件json_files list(Path(data_dir).glob(*.json))assert json_files, f未找到JSON文件于 {data_dir}all_data []for json_file in json_files:with open(json_file, r, encodingutf-8) as f:try:data json.load(f)# 验证数据结构if not isinstance(data, list):raise ValueError(f文件 {json_file.name} 根元素应为列表)for item in data:if not isinstance(item, dict):raise ValueError(f文件 {json_file.name} 包含非字典元素)for k, v in item.items():if not isinstance(v, str):raise ValueError(f文件 {json_file.name} 中键 {k} 的值不是字符串)all_data.extend({content: item,metadata: {source: json_file.name}} for item in data)except Exception as e:raise RuntimeError(f加载文件 {json_file} 失败: {str(e)})print(f成功加载 {len(all_data)} 个法律文件条目)return all_data 数据向量化并持久化 def init_vector_store(nodes: List[TextNode]) - VectorStoreIndex:chroma_client chromadb.PersistentClient(pathConfig.VECTOR_DB_DIR)chroma_collection chroma_client.get_or_create_collection(nameConfig.COLLECTION_NAME,metadata{hnsw:space: cosine})# 确保存储上下文正确初始化storage_context StorageContext.from_defaults(vector_storeChromaVectorStore(chroma_collectionchroma_collection))# 判断是否需要新建索引if chroma_collection.count() 0 and nodes is not None:print(f创建新索引{len(nodes)}个节点...)# 显式将节点添加到存储上下文storage_context.docstore.add_documents(nodes)index VectorStoreIndex(nodes,storage_contextstorage_context,show_progressTrue)# 双重持久化保障storage_context.persist(persist_dirConfig.PERSIST_DIR)index.storage_context.persist(persist_dirConfig.PERSIST_DIR) # -- 新增else:print(加载已有索引...)storage_context StorageContext.from_defaults(persist_dirConfig.PERSIST_DIR,vector_storeChromaVectorStore(chroma_collectionchroma_collection))index VectorStoreIndex.from_vector_store(storage_context.vector_store,storage_contextstorage_context,embed_modelSettings.embed_model)# 安全验证print(\n存储验证结果)doc_count len(storage_context.docstore.docs)print(fDocStore记录数{doc_count})if doc_count 0:sample_key next(iter(storage_context.docstore.docs.keys()))print(f示例节点ID{sample_key})else:print(警告文档存储为空请检查节点添加逻辑)return index 2. LamaIndex设置 创建LlamaIndex的文档Node def create_nodes(raw_data: List[Dict]) - List[TextNode]:添加ID稳定性保障nodes []for entry in raw_data:law_dict entry[content]source_file entry[metadata][source]for full_title, content in law_dict.items():# 生成稳定ID避免重复node_id f{source_file}::{full_title}parts full_title.split( , 1)law_name parts[0] if len(parts) 0 else 未知法律article parts[1] if len(parts) 1 else 未知条款node TextNode(textcontent,id_node_id, # 显式设置稳定IDmetadata{law_name: law_name,article: article,full_title: full_title,source_file: source_file,content_type: legal_article})nodes.append(node)print(f生成 {len(nodes)} 个文本节点ID示例{nodes[0].id_})return nodes 模型基础信息定义 class Config:EMBED_MODEL_PATH r../embedding_model/sungw111/text2vec-base-chinese-sentenceRERANK_MODEL_PATH r../rerank_model/BAAI/bge-reranker-large # 新增重排序模型路径LLM_MODEL_PATH r../Qwen/Qwen1___5-1___8B-Chat# 数据路径DATA_DIR ./dataVECTOR_DB_DIR ./chroma_dbPERSIST_DIR ./storage# chromadb的集合名COLLECTION_NAME labor_lawsTOP_K 10 # 扩大初始检索数量RERANK_TOP_K 3 # 重排序后保留数量MIN_RERANK_SCORE 0.4TOP_K设置的稍微大一些类似粗处理然后重排序的RERANK_TOP_K设置稍微小一些以防过于不相关的影响大模型判断 模型初始化 def init_models():初始化模型并验证# Embedding模型embed_model HuggingFaceEmbedding(model_nameConfig.EMBED_MODEL_PATH,)# LLMllm HuggingFaceLLM(model_nameConfig.LLM_MODEL_PATH,tokenizer_nameConfig.LLM_MODEL_PATH,model_kwargs{trust_remote_code: True,},tokenizer_kwargs{trust_remote_code: True},generate_kwargs{temperature: 0.3})# 初始化重排序器reranker SentenceTransformerRerank(modelConfig.RERANK_MODEL_PATH,top_nConfig.RERANK_TOP_K)Settings.embed_model embed_modelSettings.llm llmreturn embed_model, llm, reranker # 返回重排序器其中问答模型使用HuggingFaceLLM推理引擎表现稍微慢一些并且在实际测试的时候确实存在一些奇怪的bug比如模型回复总是说一半就中断因此在实际使用的时候应该优先考虑LMDeploy作为推理引擎或者使用Vllm使用方法如下 llm OpenAILike(model../Qwen/Qwen1.5-1.8B-Chat-law,api_basehttp://localhost:23333/v1,api_keyfake,context_window4096,is_chat_modelTrue,is_function_calling_modelFalse,)3. 主程序逻辑 准备工作即下面的 1、2、3 # 1.获取三个模型 embed_model, llm, reranker init_models()# 2. 创建 Node并获取可查询的索引inde # 仅当需要更新数据时执行 if not Path(Config.VECTOR_DB_DIR).exists():print(\n初始化数据...)raw_data load_and_validate_json_files(Config.DATA_DIR)nodes create_nodes(raw_data) else:nodes Noneprint(\n初始化向量存储...) start_time time.time() index init_vector_store(nodes) print(f索引加载耗时{time.time()-start_time:.2f}s)# 3. 创建检索器和响应合成器 retriever index.as_retriever(similarity_top_kConfig.TOP_K # 扩大初始检索数量 ) response_synthesizer get_response_synthesizer(# text_qa_templateresponse_template,verboseTrue )用户输入检索 为了可以运行之后反复询问大模型下面的逻辑在while(true)逻辑中在用户输入q时退出循环 question input(\n请输入劳动法相关问题输入q退出: )if question.lower() q:breakstart_time time.time()# 初始检索initial_nodes retriever.retrieve(question)retrieval_time time.time() - start_time检索之后进行重排序 reranked_nodes reranker.postprocess_nodes(initial_nodes, query_strquestion) rerank_time time.time() - start_time - retrieval_time# 执行过滤 filtered_nodes [node for node in reranked_nodes if node.score Config.MIN_RERANK_SCORE ] # for node in reranked_nodes: # print(node.score) #一般对模型的回复做限制就从filtered_nodes的返回值下手 print(原始分数样例,[node.score for node in reranked_nodes[:3]]) print(重排序过滤后的结果,filtered_nodes) # 空结果处理 if not filtered_nodes:print(你的问题未匹配到相关资料)continue设置阈值MIN_RERANK_SCORE在重排序后节点的相似度分数小于该值则丢掉该节点 回复生成 response response_synthesizer.synthesize(question, nodesfiltered_nodes # 使用过滤后的节点) synthesis_time time.time() - start_time - retrieval_time - rerank_time通过用户的问题输入和过滤后的节点(即检索到的知识库)合并交给大模型进行生成回复 结果打印 # 显示结果修改显示逻辑 print(f\n智能助手回答\n{response.response}) print(\n支持依据) for idx, node in enumerate(reranked_nodes, 1):# 兼容新版API的分数获取方式initial_score node.metadata.get(initial_score, node.score) # 获取初始分数rerank_score node.score # 重排序后的分数meta node.node.metadataprint(f\n[{idx}] {meta[full_title]})print(f 来源文件{meta[source_file]})print(f 法律名称{meta[law_name]})print(f 初始相关度{node.node.metadata.get(initial_score, 0):.4f}) # 安全访问print(f 重排序得分{getattr(node, score, 0):.4f}) # 兼容属性访问print(f 条款内容{node.node.text[:100]}...)print(f\n[性能分析] 检索: {retrieval_time:.2f}s | 重排序: {rerank_time:.2f}s | 合成: {synthesis_time:.2f}s) 4. 项目评估 4.1 评估数据准备 召回率评估 RETRIEVAL_BENCHMARK [# 劳动合同解除类{question: 劳动者可以立即解除劳动合同的情形有哪些,relevant_ids: [中华人民共和国劳动合同法 第三十八条],confusing_ids: [中华人民共和国劳动合同法 第三十九条, 中华人民共和国劳动法 第三十二条]},{question: 用人单位单方解除劳动合同需要提前多久通知,relevant_ids: [中华人民共和国劳动合同法 第四十条],confusing_ids: [中华人民共和国劳动合同法 第三十七条, 中华人民共和国劳动法 第二十六条]},# 工资与补偿类{question: 经济补偿金的计算标准是什么,relevant_ids: [中华人民共和国劳动合同法 第四十七条],confusing_ids: [中华人民共和国劳动合同法 第八十七条, 中华人民共和国劳动法 第二十八条]},{question: 试用期工资最低标准是多少,relevant_ids: [中华人民共和国劳动合同法 第二十条],confusing_ids: [中华人民共和国劳动合同法 第十九条, 中华人民共和国劳动法 第四十八条]},# 工伤与福利类{question: 工伤认定需要哪些材料,relevant_ids: [中华人民共和国劳动合同法 第三十条],confusing_ids: [中华人民共和国劳动法 第七十三条, 中华人民共和国劳动合同法 第十七条]},{question: 女职工产假有多少天,relevant_ids: [中华人民共和国劳动法 第六十二条],confusing_ids: [中华人民共和国劳动合同法 第四十二条, 中华人民共和国劳动法 第六十一条]},# 劳动合同订立类{question: 无固定期限劳动合同的订立条件是什么,relevant_ids: [中华人民共和国劳动合同法 第十四条],confusing_ids: [中华人民共和国劳动合同法 第十三条, 中华人民共和国劳动法 第二十条]},{question: 劳动合同必须包含哪些条款,relevant_ids: [中华人民共和国劳动合同法 第十七条],confusing_ids: [中华人民共和国劳动法 第十九条, 中华人民共和国劳动合同法 第十条]},# 特殊用工类{question: 劳务派遣岗位的限制条件是什么,relevant_ids: [中华人民共和国劳动合同法 第六十六条],confusing_ids: [中华人民共和国劳动合同法 第五十八条, 中华人民共和国劳动法 第二十条]},{question: 非全日制用工的每日工作时间上限,relevant_ids: [中华人民共和国劳动合同法 第六十八条],confusing_ids: [中华人民共和国劳动法 第三十六条, 中华人民共和国劳动合同法 第三十八条]},# 劳动合同终止类{question: 劳动合同终止的法定情形有哪些,relevant_ids: [中华人民共和国劳动合同法 第四十四条],confusing_ids: [中华人民共和国劳动合同法 第四十六条, 中华人民共和国劳动法 第二十三条]},{question: 劳动合同期满后必须续签的情形,relevant_ids: [中华人民共和国劳动合同法 第四十五条],confusing_ids: [中华人民共和国劳动合同法 第十四条, 中华人民共和国劳动法 第二十条]},# 劳动保护类{question: 女职工哺乳期工作时间限制,relevant_ids: [中华人民共和国劳动法 第六十三条],confusing_ids: [中华人民共和国劳动合同法 第四十二条, 中华人民共和国劳动法 第六十一条]},{question: 未成年工禁止从事的劳动类型,relevant_ids: [中华人民共和国劳动法 第六十四条],confusing_ids: [中华人民共和国劳动法 第五十九条, 中华人民共和国劳动合同法 第六十六条]},{question: 工伤保险待遇包含哪些项目,relevant_ids: [中华人民共和国劳动法 第七十三条],confusing_ids: [中华人民共和国劳动合同法 第三十条, 中华人民共和国劳动法 第四十四条]},# 劳动争议类{question: 劳动争议仲裁时效是多久,relevant_ids: [中华人民共和国劳动法 第八十二条],confusing_ids: [中华人民共和国劳动合同法 第六十条, 中华人民共和国劳动法 第七十九条]},{question: 集体合同的法律效力如何,relevant_ids: [中华人民共和国劳动法 第三十五条],confusing_ids: [中华人民共和国劳动合同法 第五十五条, 中华人民共和国劳动法 第三十三条]},# 特殊条款类{question: 服务期违约金的上限规定,relevant_ids: [中华人民共和国劳动合同法 第二十二条],confusing_ids: [中华人民共和国劳动合同法 第二十三条, 中华人民共和国劳动法 第一百零二条]},{question: 无效劳动合同的认定标准,relevant_ids: [中华人民共和国劳动合同法 第二十六条],confusing_ids: [中华人民共和国劳动法 第十八条, 中华人民共和国劳动合同法 第三十九条]} ] 端到端评估 E2E_BENCHMARK [# 案例1劳动合同解除{question: 用人单位在哪些情况下不得解除劳动合同,standard_answer: {条款: [中华人民共和国劳动合同法 第四十二条],标准答案: 根据《劳动合同法》第四十二条用人单位不得解除劳动合同的情形包括\n1. 从事接触职业病危害作业的劳动者未进行离岗前职业健康检查\n2. 在本单位患职业病或者因工负伤并被确认丧失/部分丧失劳动能力\n3. 患病或非因工负伤在规定的医疗期内\n4. 女职工在孕期、产期、哺乳期\n5. 连续工作满15年且距退休不足5年\n6. 法律、行政法规规定的其他情形\n违法解除需按第八十七条支付二倍经济补偿金,必备条件: [职业病危害作业未检查, 孕期女职工, 连续工作满15年]}},# 案例2工资支付{question: 拖欠工资劳动者可以采取哪些措施,standard_answer: {条款: [中华人民共和国劳动合同法 第三十条, 中华人民共和国劳动法 第五十条],标准答案: 劳动者可采取以下救济措施\n1. 根据劳动合同法第三十条向法院申请支付令\n2. 依据劳动合同法第三十八条解除合同并要求经济补偿\n3. 向劳动行政部门投诉\n逾期未支付的用人单位需按应付金额50%-100%加付赔偿金劳动合同法第八十五条,必备条件: [支付令申请, 解除劳动合同, 行政投诉]}},# 案例3竞业限制{question: 竞业限制的最长期限是多久,standard_answer: {条款: [中华人民共和国劳动合同法 第二十四条],标准答案: 根据劳动合同法第二十四条\n- 竞业限制期限不得超过二年\n- 适用人员限于高管/高级技术人员/其他保密人员\n- 需按月支付经济补偿\n注意区分服务期约定第二十二条,限制条件: [期限≤2年, 按月支付补偿]}},# 案例4劳务派遣{question: 劳务派遣用工的比例限制是多少,standard_answer: {条款: [中华人民共和国劳动合同法 第六十六条],标准答案: 劳务派遣用工限制\n- 临时性岗位不超过6个月\n- 辅助性岗位≤用工总量10%\n- 违法派遣按每人1000-5000元罚款第九十二条\n派遣协议需包含岗位/期限/报酬等条款第五十九条,限制条件: [临时性≤6月, 辅助性≤10%]}},# 案例5非全日制用工{question: 非全日制用工的工资支付周期要求,standard_answer: {条款: [中华人民共和国劳动合同法 第七十二条],标准答案: 非全日制用工支付规则\n- 工资结算周期≤15日\n- 小时工资≥当地最低标准\n- 终止用工不支付经济补偿第七十一条\n区别于全日制月薪制第三十条,支付规则: [周期≤15天, 小时工资≥最低标准]}},# 案例6劳动合同无效{question: 劳动合同被确认无效后的工资支付标准,standard_answer: {条款: [中华人民共和国劳动合同法 第二十八条],标准答案: 无效劳动合同的工资支付\n1. 参照本单位相同岗位工资支付\n2. 无相同岗位的按市场价\n3. 已付报酬不足的需补差\n过错方需承担赔偿责任第八十六条,支付规则: [参照同岗位, 市场价补差]}} ]4.2 评估代码实现 召回率评估器 class RecallEvaluator:def __init__(self, retriever, reranker):self.retriever retrieverself.reranker rerankerdef calculate_recall(self, retrieved_nodes, relevant_ids):retrieved_ids [n.node.metadata[full_title] for n in retrieved_nodes]hit len(set(retrieved_ids) set(relevant_ids))return hit / len(relevant_ids) if relevant_ids else 0.0def evaluate(self, benchmark):results []for case in benchmark:# 初始检索initial_nodes self.retriever.retrieve(case[question])# 重排序reranked_nodes self.reranker.postprocess_nodes(initial_nodes, query_strcase[question])# 计算召回率recall self.calculate_recall(reranked_nodes, case[relevant_ids])results.append(recall)print(f问题{case[question]})print(f初始检索结果{[n.node.metadata[full_title] for n in initial_nodes]})print(f重排序后结果{[n.node.metadata[full_title] for n in reranked_nodes]})print(f召回条款{[n.node.metadata[full_title] for n in reranked_nodes[:3]]})print(f目标条款{case[relevant_ids]})print(f召回率{recall:.1%}\n)avg_recall np.mean(results)print(f平均召回率{avg_recall:.1%})return avg_recallcalculate_recall该方法计算给定检索结果的召回率Recall。 输入retrieved_nodes检索到的节点通常是一个文档列表和 relevant_ids目标相关条款的 ID 列表。retrieved_ids 提取检索结果中每个节点的 full_title 元数据。hit 计算检索结果中的相关条款数量即在检索结果中存在于目标相关条款中的数量。最后返回召回率计算公式是召回率 找到的相关条款数量 / 目标条款总数。如果没有目标条款relevant_ids为空返回 0。 benchmark 是一个包含若干查询和其相关条款的字典列表每个字典通常包含查询的问题 (question)、相关条款的 ID 列表 (relevant_ids) 等信息。 evaluate 方法是该类的核心评估逻辑接受一个基准数据集benchmark作为输入执行评估任务。 在每次循环中 初始检索 调用 retriever.retrieve(case[question]) 执行检索操作根据问题获取初步检索结果 initial_nodes。重排序 使用 reranker.postprocess_nodes() 对初步结果进行重排序获得优化后的检索结果 reranked_nodes。此时会传入查询字符串query_str以指导重排序。召回率计算 调用 calculate_recall() 方法计算基于重排序结果与目标条款的召回率。 端到端评估器 评估给定查询的返回结果判断它们是否命中了预期的条款并计算命中率 class E2EEvaluator:def __init__(self, query_engine):self.query_engine query_enginedef evaluate_case(self, response, standard):try:# 获取实际命中的条款retrieved_clauses [node.node.metadata[full_title] for node in response.source_nodes]# 获取标准答案要求的条款required_clauses standard[standard_answer][条款]# 计算命中情况hit_clauses list(set(retrieved_clauses) set(required_clauses))missed_clauses list(set(required_clauses) - set(retrieved_clauses))# 计算命中率clause_hit len(hit_clauses) / len(required_clauses) if required_clauses else 0.0return {clause_score: clause_hit,hit_clauses: hit_clauses,missed_clauses: missed_clauses}except Exception as e:print(f评估失败{str(e)})return None功能 该方法负责评估单个查询的结果。 输入 response: 查询引擎返回的结果通常包含了与查询相关的条款。standard: 该查询对应的标准答案包含期望的条款。 处理流程 retrieved_clauses: 从 response.source_nodes 提取实际检索到的条款假设 source_nodes 是一个包含节点文档的对象其中每个节点都有一个 metadata 属性其中包含条款的详细信息。required_clauses: 从标准答案中提取期望的条款。计算实际命中的条款 hit_clauses 和缺失的条款 missed_clauses分别通过集合的交集和差集来实现。计算条款命中率 clause_hit即命中的条款数除以期望条款的总数。如果没有期望条款返回 0.0。 输出 返回一个字典包含 clause_score: 条款命中率命中条款数除以标准条款数。hit_clauses: 命中的条款列表。missed_clauses: 缺失的条款列表。 如果在评估过程中发生错误如无法访问 response 或 standard 中的某些属性会打印错误信息并返回 None。 def evaluate(self, benchmark):results []for case in benchmark:try:response self.query_engine.query(case[question])case_result self.evaluate_case(response, case)if case_result:print(f\n问题{case[question]})print(f命中条款{case_result[hit_clauses]})print(f缺失条款{case_result[missed_clauses]})print(f条款命中率{case_result[clause_score]:.1%})results.append(case_result)else:results.append(None)except Exception as e:print(f查询失败{str(e)})results.append(None)# 计算统计数据valid_results [r for r in results if r is not None]avg_hit np.mean([r[clause_score] for r in valid_results]) if valid_results else 0print(\n 最终评估报告 )print(f有效评估案例{len(valid_results)}/{len(benchmark)})print(f平均条款命中率{avg_hit:.1%})# 输出详细错误分析for i, result in enumerate(results):if result is None:print(f案例{i1}{benchmark[i][question]} 评估失败)return results 功能 该方法负责对整个基准数据集benchmark进行评估计算所有查询的整体效果。 输入 benchmark 是一个包含多个查询案例的列表。每个案例包括查询问题question和标准答案standard_answer。 处理流程 循环遍历 benchmark 中的每个查询案例case。对每个查询调用 query_engine.query() 执行查询获取响应。使用 evaluate_case() 方法评估查询的结果得到命中条款、缺失条款和条款命中率。如果评估成功打印查询、命中条款、缺失条款以及命中率等信息并将结果添加到 results 列表中。如果评估失败记录 None。 统计部分 计算所有有效结果的平均命中率avg_hit。输出最终的评估报告包括 有效评估案例的数量。平均条款命中率。 输出详细的错误分析标记哪些案例的评估失败。 输出 返回 results 列表包含每个查询的评估结果包含命中条款、缺失条款、命中率等信息。如果查询失败结果为 None。 主程序逻辑 print(\n 开始评估 )# 召回率评估 recall_evaluator RecallEvaluator(retriever, reranker) recall_result recall_evaluator.evaluate(RETRIEVAL_BENCHMARK)# 端到端评估 e2e_evaluator E2EEvaluator(query_engine) e2e_results e2e_evaluator.evaluate(E2E_BENCHMARK)# 生成报告 print(\n 最终评估报告 ) print(f重排序召回率{recall_result:.1%}) print(f端到端条款命中率{np.mean([r[clause_score] for r in e2e_results]):.1%})5. 可视化页面可选 我们采用StreamlitStreamlit 是一个开源的 Python 库用于快速构建和共享数据应用程序。它可以让开发者用简洁的代码将机器学习模型、数据可视化、分析工具等快速构建为交互式的 Web 应用 页面设置 st.set_page_config(page_title智能劳动法咨询助手,page_icon⚖️,layoutcentered,initial_sidebar_stateauto )def disable_streamlit_watcher():Patch Streamlit to disable file watcherdef _on_script_changed(_):returnfrom streamlit import runtimeruntime.get_instance()._on_script_changed _on_script_changed为了让页面变化更顺畅用户体验好一些在上述代码中修改如下 st.cache_resource(show_spinner初始化模型中...) def init_models(): ...st.cache_resource(show_spinner加载知识库中...) def init_vector_store(_nodes): ...页面组件设置 def init_chat_interface():if messages not in st.session_state:st.session_state.messages []for msg in st.session_state.messages:role msg[role]content msg.get(cleaned, msg[content]) # 优先使用清理后的内容with st.chat_message(role):st.markdown(content)# 如果是助手消息且包含思维链if role assistant and msg.get(think):with st.expander( 模型思考过程历史对话):for think_content in msg[think]:st.markdown(fspan stylecolor: #808080{think_content.strip()}/span,unsafe_allow_htmlTrue)# 如果是助手消息且有参考依据需要保持原有参考依据逻辑if role assistant and reference_nodes in msg:show_reference_details(msg[reference_nodes])def show_reference_details(nodes):with st.expander(查看支持依据):for idx, node in enumerate(nodes, 1):meta node.node.metadatast.markdown(f**[{idx}] {meta[full_title]}**)st.caption(f来源文件{meta[source_file]} | 法律名称{meta[law_name]})st.markdown(f相关度{node.score:.4f})# st.info(f{node.node.text[:300]}...)st.info(f{node.node.text}) 重新修改后的主程序 def main():# 禁用 Streamlit 文件热重载disable_streamlit_watcher()st.title(⚖️ 智能劳动法咨询助手)st.markdown(欢迎使用劳动法智能咨询系统请输入您的问题我们将基于最新劳动法律法规为您解答。)# 初始化会话状态if history not in st.session_state:st.session_state.history []# 加载模型和索引embed_model, llm, reranker init_models()# 初始化数据if not Path(Config.VECTOR_DB_DIR).exists():with st.spinner(正在构建知识库...):raw_data load_and_validate_json_files(Config.DATA_DIR)nodes create_nodes(raw_data)else:nodes Noneindex init_vector_store(nodes)retriever index.as_retriever(similarity_top_kConfig.TOP_K,vector_store_query_modehybrid,alpha0.5)response_synthesizer get_response_synthesizer(verboseTrue)# 聊天界面init_chat_interface()if prompt : st.chat_input(请输入劳动法相关问题):# 添加用户消息到历史st.session_state.messages.append({role: user, content: prompt})with st.chat_message(user):st.markdown(prompt)# 处理查询with st.spinner(正在分析问题...):start_time time.time()# 检索流程initial_nodes retriever.retrieve(prompt)reranked_nodes reranker.postprocess_nodes(initial_nodes, query_strprompt)# 过滤节点MIN_RERANK_SCORE 0.4filtered_nodes [node for node in reranked_nodes if node.score MIN_RERANK_SCORE]if not filtered_nodes:response_text ⚠️ 未找到相关法律条文请尝试调整问题描述或咨询专业律师。else:# 生成回答response response_synthesizer.synthesize(prompt, nodesfiltered_nodes)response_text response.response# 显示回答with st.chat_message(assistant):# 提取思维链内容并清理响应文本think_contents re.findall(rthink(.*?)/think, response_text, re.DOTALL)cleaned_response re.sub(rthink.*?/think, , response_text, flagsre.DOTALL).strip()# 显示清理后的回答st.markdown(cleaned_response)# 如果有思维链内容则显示if think_contents:with st.expander( 模型思考过程点击展开):for content in think_contents:st.markdown(fspan stylecolor: #808080{content.strip()}/span, unsafe_allow_htmlTrue)# 显示参考依据保持原有逻辑show_reference_details(filtered_nodes[:3])# 添加助手消息到历史需要存储原始响应st.session_state.messages.append({role: assistant,content: response_text, # 保留原始响应cleaned: cleaned_response, # 存储清理后的文本think: think_contents # 存储思维链内容})运行的页面大致如下 总结收尾 到这里其实就已经完成整个 RAG 项目了我们做一下总结 通过这个项目我们不仅构建了一个基于开源技术栈的劳动合同法法律助手更重要的是它为我们深入理解 RAG 系统的原理、构建流程以及性能优化提供了宝贵的实践经验。 1. 项目成果回顾 我们成功地从零开始搭建了一个具备以下核心功能的 RAG 法律助手 数据驱动的知识库 通过网络爬取和数据清洗构建了劳动合同法相关的专属知识库。高效的向量检索 利用嵌入模型和向量数据库实现了对法律条文的快速语义检索。精准的检索增强 通过结合结构化分块、递归分块及小块-大上下文策略优化了知识库的组织并利用 BGE Re-ranker 对检索结果进行精细重排序确保提供给 LLM 的上下文高度相关。智能的问答能力 集成Qwen2 开源 LLM使助手能够根据检索到的法律依据生成专业、准确的答案。可评估的性能 明确了评估指标检索准确性、答案忠实度、答案相关性等并计划使用 RAGAS 等工具进行量化评估为持续优化奠定基础。未来可扩展性 方案中预留了 LoRA 微调的路径当面临需要个性化的需求提供可能。 2. 核心技术选择的思考 LlamaIndex 与 ChromaDB 的组合 这种选择在学习和原型开发阶段表现出极高的效率。LlamaIndex 专注于 RAG 核心流程的清晰抽象使得数据摄取、索引、查询引擎的构建变得直观。ChromaDB 的嵌入式特性则极大降低了部署和管理门槛让开发者能将更多精力放在 RAG 逻辑本身而非基础设施。这种组合特别适合个人项目或资源有限的团队进行快速迭代。BGE 嵌入与重排序模型 BGE 系列模型在开源社区中表现出色。实践中我们会深刻体会到高质量的嵌入是 RAG 的基石当然嵌入模型主要是对语言的考量而重排序则是提升用户体验的关键一步。Qwen2 等开源 LLM我们选择模型都是选择的开源免费且参数量较小的模型但是这会带来一些问题因此该项目实现只用于学习。 3. 影响 RAG 性能的关键因素再思考 “垃圾进垃圾出”法则 数据质量是压倒一切的。法律领域的严谨性使得数据清洗、去重和标准化变得尤为重要。不准确、过时或有偏见的数据将直接导致助手提供错误或误导性的法律建议这在法律场景下是绝对不能接受的。分块艺术 分块不仅仅是技术细节更是对“上下文”的深刻理解。根据数据特征选择合适的分块策略至关重要。嵌入模型的能力 虽然该模型对性能影响一般不大但是也是需要关注是否是他影响到知识库的检索从而影响后续问答模型的生成回复质量。检索与生成的平衡 RAG 的核心是检索增强生成。检索的“召回率”和“准确率”与生成的“忠实度”和“相关性”是相互影响的。重排序模型就是在召回和准确率之间寻求平衡的关键工具。**模型能力的优先考虑**在用户输入一些问题回复不佳时优先考虑换一下更好的模型而不是优先考虑微调例如可以考虑换一下32B 以上的模型就可以 4. RAG 与 LoRA 微调的协同效应思考 这个项目设计中包含了 LoRA 微调的探索这揭示了 RAG 并非 LLM 微调的替代品而是互补的策略 RAG 解决“知识鲜度”和“事实准确性” 法律法规更新频繁RAG 能够动态加载最新知识避免模型“知识滞后”的问题。LoRA 解决“领域专业性”和“行为约束” RAG 很难教会通用 LLM 以律师的思维方式、法律的严谨措辞来表达。LoRA 微调则能让 LLM 学习到法律领域的特定风格、术语使用、推理模式以及在特定场景下的输出格式要求。例如如何规范地引用法条、如何分析案例等。效率与效果的平衡 RAG 避免了全量微调的巨大成本而 LoRA 则在不牺牲过多效率的前提下提升了 LLM 在特定领域的“软技能”。这种结合使得我们既能拥有最新的法律知识又能确保助手回答的专业性和可信度。
http://www.w-s-a.com/news/225779/

相关文章:

  • 新网站建设运营年计划书仓山区建设局招标网站
  • 网站开发天津网站建设项目组织图
  • 网站开发认证考试石家庄高端网站开发
  • 网站建设第一步怎么弄站酷网页
  • 设备网站模板江西的赣州网站建设
  • 邯郸营销型网站国际招聘人才网
  • hexo wordpress 主题织梦网站优化教程
  • 网站建设方案及上海市建设协会网站
  • 轴承外贸网站怎么做南宁网站排名优化公司哪家好
  • 沈阳企业网站建站郴州优化公司
  • cctv5+手机在线直播观看seo关键词排名优化方法
  • 网站建设公司怎么谈单怎么开通微信小程序商店
  • 深圳做网站案例一个服务器可以备案几个网站
  • 网络营销策划名词解释泉州百度推广排名优化
  • 一键生成网站的软件互联网营销师是干什么
  • 网站后台管理水印怎么做手机优化设置
  • 哪个网站做图文素材多wordpress++优化
  • 建设网站就选用什么样的公司网站类型分类有哪些
  • 找平面设计师网站网站建设须知
  • 建设联结是不是正规网站wordpress 微博同步
  • 瑞安微网站建设广州推广
  • 做旅游宣传网站的流程图中国企业集成网电子商务
  • 开发商城网站开发成交功能网站
  • 网站建设公司专业公司排名搭建网站的企业
  • 网站建设难吗海南智能网站建设报价
  • 企业网站建设选题的依据及意义校园网站建设的论文
  • 网站版面设计方案水电维修在哪个网站上做推广好些
  • 邹平建设局官方网站企业宣传片广告公司
  • 南京建设集团网站建站极速通
  • 网站建设与推广员岗位职责网站开发应如何入账