Langchain搭建LLM应用程序之十二 RAG-向量数据库实现合同信息抽取
·
为什么要用向量数据库
传统数据库系统通常以结构化的形式存储数据,即由预定义的字段及其对应值构成。当我们面临的内容不再是数据,而是知识,提出的问题也不再局限于某个字段值,而是自然语言描述的问题,传统的关键字检索局限性就太大了。
为实现非结构化数据的高效检索,关键在于将其转化为结构化的表示形式。向量化技术为此提供了可行的解决方案。通过对海量文档进行文本分块、向量化处理,并将其存储于专用数据库中,可将非结构化内容转换为数值化的向量表示。在进行检索时,查询内容经过相同的向量化处理,通过计算向量间的相似度,从数据库中找出与之最接近的k个向量。最终,所需的答案即蕴含于这k个向量所对应的文本块之中。
代码实现
-
加载文档
from langchain_community.document_loaders import Docx2txtLoader contract_file_path = "/Users/q/基金合同.docx" document = Docx2txtLoader(contract_file_path) doc = document.load() # 返回的是一个包含 document 对象的列表 -
构造切割器及文档切割
from langchain.text_splitter import RecursiveCharacterTextSplitter text_splitter = RecursiveCharacterTextSplitter(separators=["\n\n", "\n", "。", "!", "?", ";", ",", " ", ""], chunk_size=200,chunk_overlap=50) documents = text_splitter.split_documents(doc) -
构造向量模型
from langchain_community.embeddings import DashScopeEmbeddings embeddings = DashScopeEmbeddings( model="text-embedding-v1", dashscope_api_key=my_api_key ) -
切割后文档存入向量数据库
from langchain.vectorstores import FAISS store = FAISS.from_documents(documents, embeddings) -
执行检索
from langchain_community.document_loaders import Docx2txtLoader from langchain.text_splitter import RecursiveCharacterTextSplitter from langchain.vectorstores import FAISS import time query="基金名称" docs=store.similarity_search(query,k=2) doc_content = "\n".join([item.page_content for item in docs]) -
构建 chat 模型client
from langchain_community.llms import Tongyi from langchain.prompts import PromptTemplate # 使用阿里云专用LLM类 llm = Tongyi( model_name='qwen-max', # 这里可以使用 qwen-max api_key=my_api_key, temperature=0.3, max_tokens=300 ) -
创建提示词模板并调用大模型检索
from langchain.prompts import PromptTemplate prompt_template = """你是一个专业的信息提取助手。你的任务是从给定的文本中精确提取指定字段的值。 要求: 1. 只提取文本中明确提到的信息,不要推测或生成不存在的信息 2. 如果字段值不存在,返回 null 3. 保持值的原始格式,不要修改 4. 对于数字、日期等格式,保持原文中的形式 5. 如果字段有多个可能的值,选择最符合语境的一个 原文档内容为: {source_content} 请根据文档内容提取字段{field_name}的值,并以数组嵌套json格式输出,json 的key是 field_name 和 value。 """ prompt_template = PromptTemplate(template=prompt_template, input_variables=['source_content','field_name']) prompt = prompt_template.format(source_content=doc_content, field_name="基金名称") print(llm.invoke(prompt))
总结
- 选择合适的切割器和embedding 模型是保证检索质量的关键,参考切割器选型;
- 文档存储入向量数据库是一个比较耗时的过程,生产中可以使用预加载结合缓存的方式提升响应速率;
- 利用 RAG 先检索到文档块,再请求 LLM 可以节省 token
更多推荐

所有评论(0)