免费获取学习方案
ARTICLE DETAIL

资讯详情

深耕编程基础知识与建站技术分享的一线实战洞察。

基于LangChain与向量数据库构建法律智能体:从RAG原理到消费律所应用

基于LangChain与向量数据库构建法律智能体:从RAG原理到消费律所应用 在传统法律服务领域客户常常面临高昂的费用、复杂的流程和漫长的等待时间。一个简单的合同审查或消费纠纷咨询其成本与效率往往不成正比。与此同时人工智能技术特别是大型语言模型和智能体Agent技术的发展为重塑这一行业提供了新的可能性。它们能够处理结构化的法律文本、理解用户意图、并基于知识库提供初步的咨询和文档生成服务。“智能体消费律所”这一概念正是将AI智能体技术与法律服务深度结合的产物。它并非要取代律师而是作为律师的超级助理和客户的第一触点通过自动化、智能化的方式处理大量标准化、重复性的法律咨询和文书工作从而大幅降低服务门槛和成本提升服务效率。对于普通消费者和小微企业而言这意味着能以更低的价格、更快的速度获得基础的法律支持。本文将深入探讨如何从技术层面构建一个“智能体消费律所”的核心原型。我们将从理解其技术架构开始逐步完成环境准备、知识库构建、智能体核心功能开发、前后端集成并最终部署一个可交互的演示系统。通过这个过程你将掌握利用现代AI技术栈如LangChain、向量数据库、Streamlit等打造垂直领域智能应用的关键路径。1. 理解智能体消费律所的技术架构在动手编码之前必须先厘清整个系统的技术构成和数据流向。一个基础的智能体消费律所原型通常包含以下几个核心层次1.1 核心组件与数据流整个系统围绕“智能体”工作其核心是能够理解法律问题、检索相关知识并生成可靠回答或文档的AI模型。以下是典型的数据处理流程用户输入用户通过Web界面或API提出一个自然语言问题例如“租房合同里押金条款应该注意什么”意图识别与问题分类系统首先对用户问题进行初步分析判断其属于哪个法律领域如劳动法、合同法、消费者权益保护法以及问题类型咨询、文档生成、流程查询。知识检索根据分类结果系统从预先构建的法律知识库中检索最相关的法律条文、案例摘要、合同模板或常见问答。这里的关键技术是向量检索。上下文构建与提示工程将用户原始问题、检索到的相关知识片段、以及系统的角色设定“你是一名专业的法律助理”组合成一个结构化的提示Prompt提交给大语言模型。大语言模型推理大语言模型如GPT-4、Claude或本地部署的模型基于构建的上下文生成专业、准确且符合法律伦理的回复。输出与后处理将模型的回复返回给用户。对于文档生成类请求可能还需要将回复结构化填充到预设的模板中生成PDF或Word文档。1.2 关键技术选型为了构建上述流程我们需要选择合适的技术栈大语言模型LLM接口作为智能体的“大脑”。初期开发可使用OpenAI GPT或Anthropic Claude的API便于快速验证。生产环境需要考虑成本、数据隐私和响应速度可能转向本地部署的模型如Llama 3、Qwen系列或通过Azure OpenAI等服务。嵌入模型与向量数据库作为智能体的“长期记忆”。使用嵌入模型如OpenAI的text-embedding-3-small或开源的BGE-M3将法律知识文本转化为向量。向量数据库如Chroma、Weaviate、Qdrant或PGVector用于高效存储和检索这些向量。智能体框架用于编排整个流程。LangChain或LlamaIndex是当前的主流选择它们提供了连接LLM、向量数据库、工具调用等组件的标准化方式极大简化了开发。应用框架与部署用于构建用户界面和部署服务。Streamlit或Gradio适合快速构建交互式演示原型。对于更复杂的生产级Web应用可采用FastAPI构建后端API配合React/Vue构建前端。法律知识源系统的基石。需要收集、清洗和结构化法律知识包括但不限于法律法规条文可从官方渠道获取结构化数据。标准合同模板。常见法律问题与解答QA。典型案例的摘要与要点。2. 环境准备与项目初始化我们将使用Python作为主要开发语言并利用LangChain框架来构建智能体核心。首先确保你的开发环境就绪。2.1 开发环境与工具Python: 版本 3.9 或以上。包管理: 使用pip或poetry。推荐使用虚拟环境venv或conda隔离项目依赖。代码编辑器: VS Code、PyCharm等。版本控制: Git。2.2 创建项目并安装核心依赖创建一个新的项目目录并初始化虚拟环境。# 创建项目目录 mkdir ai_legal_agent cd ai_legal_agent # 创建虚拟环境 (以venv为例) python -m venv venv # 激活虚拟环境 # Windows: venv\Scripts\activate # Linux/Mac: source venv/bin/activate # 安装核心依赖 pip install langchain langchain-community langchain-openai pip install chromadb # 轻量级向量数据库适合原型开发 pip install tiktoken # 用于计算Token管理成本 pip install python-dotenv # 管理环境变量 pip install streamlit # 用于构建Web演示界面 pip install pypdf # 用于解析PDF格式的法律文档2.3 配置API密钥与环境变量为了调用大语言模型和嵌入模型API你需要准备相应的API密钥。我们将使用.env文件来安全地管理这些敏感信息。在项目根目录创建.env文件。根据你使用的服务商填入对应的API密钥。以下以OpenAI为例# .env 文件内容 OPENAI_API_KEY你的OpenAI_API密钥 # 如果使用其他模型如Azure OpenAI或Anthropic可添加如下配置 # AZURE_OPENAI_API_KEYyour_key # AZURE_OPENAI_ENDPOINTyour_endpoint # ANTHROPIC_API_KEYyour_key重要提示务必在.gitignore文件中加入.env避免将密钥提交到代码仓库。3. 构建法律知识库智能体的专业性很大程度上取决于其知识库的质量。这一步的目标是将原始的法律文本转化为向量数据库中可以快速检索的形式。3.1 准备原始法律文本数据假设我们有一些基础的法律文本文件格式可以是TXT、PDF或MD。我们在项目中创建一个data/目录来存放它们。项目结构建议如下ai_legal_agent/ ├── app.py # Streamlit主应用文件 ├── core/ # 核心逻辑模块 │ ├── __init__.py │ ├── knowledge_base.py # 知识库构建与加载 │ └── legal_agent.py # 智能体核心逻辑 ├── data/ # 原始法律文本数据 │ ├── labor_law.txt │ ├── contract_templates/ │ └── consumer_rights.md ├── vector_db/ # 向量数据库存储目录由Chroma自动创建 ├── .env # 环境变量 ├── requirements.txt # 项目依赖 └── README.mddata/labor_law.txt示例内容《中华人民共和国劳动合同法》第十九条 劳动合同期限三个月以上不满一年的试用期不得超过一个月劳动合同期限一年以上不满三年的试用期不得超过二个月三年以上固定期限和无固定期限的劳动合同试用期不得超过六个月。 同一用人单位与同一劳动者只能约定一次试用期。 ...3.2 实现知识库构建脚本在core/knowledge_base.py中我们将编写构建和加载知识库的代码。# core/knowledge_base.py import os from langchain_community.document_loaders import TextLoader, DirectoryLoader from langchain_text_splitters import RecursiveCharacterTextSplitter from langchain_openai import OpenAIEmbeddings from langchain_community.vectorstores import Chroma from dotenv import load_dotenv # 加载环境变量 load_dotenv() class LegalKnowledgeBase: def __init__(self, persist_directory./vector_db): 初始化知识库。 :param persist_directory: 向量数据库持久化目录 self.persist_directory persist_directory # 初始化嵌入模型使用OpenAI的text-embedding-3-small self.embeddings OpenAIEmbeddings(modeltext-embedding-3-small) self.vector_store None def build_from_directory(self, data_directory./data): 从指定目录加载文档分割文本并构建向量数据库。 :param data_directory: 存放法律文本数据的目录 # 1. 加载文档 # 使用通配符加载多种格式的文本文件 loader DirectoryLoader(data_directory, glob**/*.txt, loader_clsTextLoader) documents loader.load() # 可以继续加载其他格式如PDF、MD # pdf_loader DirectoryLoader(data_directory, glob**/*.pdf, loader_clsPyPDFLoader) # documents.extend(pdf_loader.load()) if not documents: print(未在目录中找到任何文档。) return print(f成功加载 {len(documents)} 个文档。) # 2. 分割文本 # 法律条文逻辑性强分割不宜过碎。这里按字符数分割并保持一定重叠。 text_splitter RecursiveCharacterTextSplitter( chunk_size1000, # 每个片段的字符数 chunk_overlap200, # 重叠字符数保持上下文连贯 separators[\n\n, \n, 。, , , , ] # 分割符优先级 ) splits text_splitter.split_documents(documents) print(f文档被分割成 {len(splits)} 个文本片段。) # 3. 创建并持久化向量存储 self.vector_store Chroma.from_documents( documentssplits, embeddingself.embeddings, persist_directoryself.persist_directory ) self.vector_store.persist() print(f向量数据库已构建并保存至 {self.persist_directory}) def load_existing(self): 加载已存在的向量数据库。 if os.path.exists(self.persist_directory): self.vector_store Chroma( persist_directoryself.persist_directory, embedding_functionself.embeddings ) print(已加载现有向量数据库。) return True else: print(未找到已存在的向量数据库请先运行 build_from_directory。) return False def similarity_search(self, query, k4): 在知识库中进行相似性搜索。 :param query: 查询文本 :param k: 返回最相关的k个结果 :return: 相关文档列表 if self.vector_store is None: if not self.load_existing(): return [] docs self.vector_store.similarity_search(query, kk) return docs if __name__ __main__: # 直接运行此文件可以构建知识库 kb LegalKnowledgeBase() kb.build_from_directory()关键解释文本分割RecursiveCharacterTextSplitter是LangChain提供的智能分割器它会优先按大段落\n\n分割不行再按句子分割保证语义相对完整。对于法律条文chunk_size1000是一个合理的起点。向量化与存储OpenAIEmbeddings将文本转换为向量。Chroma.from_documents方法一次性完成向量化、存储和索引创建。persist_directory参数确保数据保存在本地磁盘下次无需重新构建。相似性搜索similarity_search是核心检索方法它接收用户查询将其向量化然后在向量空间中找到最相似的文本片段。运行此脚本以构建知识库python core/knowledge_base.py4. 实现智能体核心逻辑有了知识库接下来需要创建智能体它负责协调检索与生成。我们在core/legal_agent.py中实现。4.1 定义系统提示词与检索增强生成链提示词Prompt是引导大语言模型行为的关键。我们需要精心设计一个适合法律场景的系统提示词。# core/legal_agent.py from langchain_openai import ChatOpenAI from langchain.chains import RetrievalQA from langchain.prompts import PromptTemplate from .knowledge_base import LegalKnowledgeBase import os from dotenv import load_dotenv load_dotenv() class LegalAgent: def __init__(self, model_namegpt-3.5-turbo): 初始化法律智能体。 :param model_name: 使用的LLM模型名称 # 初始化大语言模型 self.llm ChatOpenAI(modelmodel_name, temperature0.1) # temperature调低使输出更确定、更专业 self.knowledge_base LegalKnowledgeBase() self.knowledge_base.load_existing() # 加载已有知识库 self.qa_chain None self._setup_chain() def _setup_chain(self): 设置检索增强生成RAG链。 # 定义系统提示词模板 prompt_template 你是一名专业的法律助理专门为消费者和小微企业提供法律咨询服务。 请严格根据以下提供的法律知识上下文来回答问题。如果上下文中的信息不足以回答问题请如实告知用户你无法基于现有知识给出准确答案并建议其咨询执业律师。 回答应当专业、清晰、简洁并优先引用相关法律条款。 避免编造信息或做出超出上下文范围的法律判断。 上下文 {context} 问题 {question} 请根据上述上下文提供回答 PROMPT PromptTemplate( templateprompt_template, input_variables[context, question] ) # 创建RetrievalQA链 # 这里使用stuff链类型它将所有检索到的文档合并成一个上下文传入Prompt。 # 对于法律咨询这通常是合适的因为需要综合多条法律条文。 self.qa_chain RetrievalQA.from_chain_type( llmself.llm, chain_typestuff, retrieverself.knowledge_base.vector_store.as_retriever(search_kwargs{k: 4}), # 检索4个最相关的文档片段 chain_type_kwargs{prompt: PROMPT}, return_source_documentsTrue # 返回源文档便于验证和解释 ) def ask(self, question): 向智能体提问。 :param question: 用户的法律问题 :return: 包含答案和源文档的字典 if self.qa_chain is None: return {error: 智能体未正确初始化。} try: result self.qa_chain.invoke({query: question}) return { answer: result[result], source_documents: result[source_documents] } except Exception as e: return {error: f处理问题时发生错误{str(e)}} def generate_document(self, doc_type, user_inputs): 根据模板和用户输入生成法律文档简化版。 实际应用中这里会连接一个更复杂的模板引擎和文档组装逻辑。 :param doc_type: 文档类型如租赁合同、借条 :param user_inputs: 用户提供的填充信息字典 :return: 生成的文档文本 # 这里是一个简单的示例。实际项目应从数据库或文件加载模板。 templates { simple_agreement: 简易协议书 甲方{party_a} 乙方{party_b} 根据《中华人民共和国民法典》等相关法律规定双方经协商一致达成如下协议 1. {clause_one} 2. {clause_two} 本协议一式两份双方各执一份具有同等法律效力。 甲方签字__________ 乙方签字__________ 日期{date} } if doc_type not in templates: return f暂不支持生成 {doc_type} 类型的文档。 template templates[doc_type] try: # 简单格式化实际应做更严格的输入验证和转义 generated_doc template.format(**user_inputs) return generated_doc except KeyError as e: return f生成文档时缺少必要参数{e} if __name__ __main__: # 测试智能体 agent LegalAgent(model_namegpt-3.5-turbo) test_question 劳动合同的试用期最长可以是多久 response agent.ask(test_question) print(问题, test_question) print(答案, response.get(answer)) print(\n--- 参考来源 ---) for i, doc in enumerate(response.get(source_documents, [])): print(f[{i1}] {doc.page_content[:200]}...) # 打印前200字符4.2 关键代码解析与注意事项提示词工程系统提示词明确了智能体的角色、职责和限制。{context}和{question}是占位符会被LangChain自动替换。强调“根据上下文”和“避免编造”对于法律场景至关重要。检索器配置as_retriever(search_kwargs{k: 4})表示每次检索4个最相关的文档片段。k值需要权衡太小可能遗漏关键信息太大会增加上下文长度和成本。链类型选择chain_typestuff是最简单的方式将所有检索到的文档拼接到Prompt中。对于更复杂的、需要多步推理或汇总的任务可以考虑map_reduce或refine。错误处理在ask方法中使用了try-except确保网络或API异常不会导致整个应用崩溃。文档生成generate_document方法展示了一个极其简化的模板填充流程。真实系统需要更强大的模板管理、变量验证和输出格式化如生成PDF。运行测试脚本验证智能体是否能基于知识库正确回答问题python core/legal_agent.py5. 构建交互式Web应用为了让非技术用户也能使用我们使用Streamlit快速构建一个Web界面。创建app.py文件。# app.py import streamlit as st from core.legal_agent import LegalAgent import time # 设置页面标题和图标 st.set_page_config(page_title智能法律助理, page_icon⚖️, layoutwide) # 初始化智能体使用缓存避免重复加载 st.cache_resource def load_agent(): # 可以在这里根据环境变量选择模型例如 # model os.getenv(OPENAI_MODEL, gpt-3.5-turbo) return LegalAgent(model_namegpt-3.5-turbo) agent load_agent() st.title(⚖️ 智能法律助理) st.markdown( 欢迎使用智能法律助理。我可以基于中国现行法律法规为您提供常见的法律问题咨询。 **请注意**本助手提供的信息仅供参考不构成正式法律意见。对于重大法律事务请务必咨询执业律师。 ) # 创建选项卡 tab1, tab2 st.tabs([ 法律咨询, 文档生成]) with tab1: st.header(法律咨询) # 会话状态管理保存聊天历史 if messages not in st.session_state: st.session_state.messages [] # 显示历史消息 for message in st.session_state.messages: with st.chat_message(message[role]): st.markdown(message[content]) # 如果是助理的回答可以显示来源可选 if message.get(sources): with st.expander(查看参考依据): for src in message[sources]: st.caption(src[:300] ...) # 聊天输入框 if prompt : st.chat_input(请输入您的法律问题例如试用期被辞退有补偿吗): # 添加用户消息到历史 st.session_state.messages.append({role: user, content: prompt}) with st.chat_message(user): st.markdown(prompt) # 生成助理回复 with st.chat_message(assistant): message_placeholder st.empty() message_placeholder.markdown(⏳ 正在思考...) # 调用智能体 response agent.ask(prompt) if error in response: full_response f抱歉处理时出现错误{response[error]} sources [] else: full_response response[answer] sources [doc.page_content for doc in response.get(source_documents, [])] # 模拟流式输出效果 message_placeholder.markdown(full_response) # 显示来源 if sources: with st.expander(本次回答参考了以下法律条文): for i, src in enumerate(sources): st.text_area(f依据 {i1}, src, height100, disabledTrue) # 添加助理回复到历史 st.session_state.messages.append({role: assistant, content: full_response, sources: sources}) with tab2: st.header(简易文档生成) st.markdown(根据您的输入快速生成基础法律文书。) doc_type st.selectbox(选择文档类型, [简易协议书, 借条简易版, 催告函模板]) # 根据文档类型动态显示输入字段 if doc_type 简易协议书: col1, col2 st.columns(2) with col1: party_a st.text_input(甲方名称) clause_one st.text_area(第一条协议内容) with col2: party_b st.text_input(乙方名称) clause_two st.text_area(第二条协议内容) date st.date_input(协议日期) user_inputs { party_a: party_a, party_b: party_b, clause_one: clause_one, clause_two: clause_two, date: str(date) } elif doc_type 借条简易版: # 简化示例实际字段更多 lender st.text_input(出借人) borrower st.text_input(借款人) amount st.number_input(借款金额元, min_value0.0) user_inputs {lender: lender, borrower: borrower, amount: amount} else: user_inputs {} if st.button(生成文档, typeprimary): if doc_type 简易协议书: result agent.generate_document(simple_agreement, user_inputs) else: result 该文档模板正在开发中... st.subheader(生成结果) st.code(result, languageNone) # 以纯文本代码块形式显示便于复制 st.download_button( label下载为文本文件, dataresult, file_namef{doc_type}.txt, mimetext/plain ) # 侧边栏信息 with st.sidebar: st.info( **使用说明** 1. 在“法律咨询”选项卡中直接提问。 2. 系统会从法律知识库中检索相关信息并生成回答。 3. 点击“查看参考依据”可以了解回答的法律来源。 4. 在“文档生成”中可快速创建基础法律文书。 ) st.divider() if st.button(清空对话历史): st.session_state.messages [] st.rerun()5.1 运行与验证在项目根目录下运行Streamlit应用streamlit run app.py浏览器会自动打开http://localhost:8501。你可以尝试以下操作进行验证法律咨询在聊天框输入“劳动合同试用期最长多久”。观察系统是否能从知识库中检索到《劳动合同法》第十九条并给出准确回答。点击“查看参考依据”确认答案来源。文档生成切换到“文档生成”选项卡选择“简易协议书”填写一些测试信息点击生成。检查生成的文档是否正确地填充了模板。6. 常见问题排查与优化在开发和运行过程中你可能会遇到以下典型问题。下表列出了现象、原因和解决方案。问题现象可能原因检查与解决方案运行streamlit run app.py时报ModuleNotFoundError依赖未安装或虚拟环境未激活1. 确认虚拟环境已激活命令行前有(venv)。2. 运行pip install -r requirements.txt安装所有依赖。智能体回答“未找到知识库”或回答内容与法律无关向量数据库未成功构建或加载1. 检查core/knowledge_base.py中的persist_directory路径。2. 运行python core/knowledge_base.py重新构建知识库观察控制台输出是否有加载和分割文档的日志。3. 检查data/目录下是否有.txt等格式的源文件。回答速度很慢1. OpenAI API 网络延迟。2. 检索的文档片段k值过多。3. 本地嵌入模型计算慢如果使用。1. 检查网络连接。2. 尝试减小search_kwargs{k: 4}中的k值例如改为2。3. 如果使用本地嵌入模型考虑使用GPU或换用更轻量的模型。回答内容出现“幻觉”编造法律条文1. 提示词约束力不够。2. 检索到的相关文档太少或无关。3. LLM的temperature参数过高。1. 强化提示词中“严格根据上下文”和“避免编造”的指令。2. 增加检索数量k或优化知识库文本分割策略如按法条分割。3. 将temperature调至0.1或更低。Streamlit 应用界面显示异常或卡顿1. 会话状态管理不当。2. 每次渲染都重新加载大模型或知识库。1. 使用st.cache_resource缓存智能体等重型对象。2. 避免在每次交互中重复初始化。检查代码是否将初始化逻辑放在了函数外部或使用了缓存装饰器。API调用超时或报错RateLimitError1. API密钥无效或余额不足。2. 请求频率超限。1. 检查.env文件中的OPENAI_API_KEY是否正确并确认账户有额度。2. 在代码中增加重试逻辑和指数退避或降低请求频率。7. 从原型到生产环境的最佳实践上述原型验证了核心概念但要作为一个可靠的服务还需要考虑以下方面7.1 知识库质量与维护数据来源权威性确保法律条文来自官方公报或可信数据库合同模板由专业律师审阅。数据清洗与结构化原始文本需要清洗去除无关字符、格式化并尽可能结构化例如将“第X条”作为元数据存储便于更精确的检索。增量更新法律会更新知识库也需要支持增量添加新文档而无需全量重建。Chroma等数据库支持此功能。检索优化除了向量检索可结合关键词检索如BM25进行混合搜索提升召回率。为不同文档类型法条、案例、问答设置不同权重。7.2 智能体能力增强多步骤推理与工具调用复杂问题可能需要拆解。可以使用LangChain的Agent框架让智能体自主决定调用“计算器”、“法条查询”、“案例检索”等工具。对话历史与上下文管理当前的简单聊天历史是线性的。生产环境需要更复杂的会话管理支持多轮对话、指代消解如“上一条说的那个补偿”。输出规范化与审核对于文档生成需要更强大的模板引擎如Jinja2并可能引入人工审核流程或规则引擎进行初步校验。7.3 系统性能与可靠性异步处理对于耗时的文档生成或复杂咨询应采用异步任务队列如Celery避免阻塞Web请求。缓存策略对常见问题FAQ的答案进行缓存减少对LLM和向量数据库的调用提升响应速度并降低成本。限流与熔断对API调用实施限流防止滥用。在依赖服务如OpenAI API不稳定时应有熔断机制。监控与日志记录所有用户查询、智能体回答、检索来源和API调用耗时。这有助于分析效果、优化模型和排查问题。7.4 安全、合规与伦理数据隐私用户咨询可能涉及敏感信息。必须明确隐私政策对传输和存储的数据进行加密并考虑支持本地化部署以满足数据不出境的要求。责任边界必须在交互界面显著位置声明“本服务提供的信息不构成正式法律意见仅供参考”。对于识别出的复杂或高风险问题系统应主动建议用户联系人工律师。内容过滤在Prompt和最终输出层设置过滤器防止生成不当、有害或误导性内容。可解释性与审计保留每次问答的完整上下文、检索到的源文档和模型生成的原始内容确保结果的可追溯性这对于法律应用至关重要。构建一个真正的“智能体消费律所”是一项涉及法律、技术和产品的复杂工程。本文提供的原型是一个坚实的起点它展示了如何将AI智能体技术应用于垂直领域。接下来的迭代方向可以集中在提升知识库的深度和广度、优化检索与生成的准确性、设计更流畅的用户交互流程并最终构建起涵盖咨询、文档、流程指引乃至案件管理的完整服务体系。技术的价值在于解决真实世界的痛点而将法律服务变得更普惠、更高效正是这样一个充满潜力的方向。
返回列表