家居网站建设行业现状,wordpress预约订单插件,网站程序是什么,网站搜索引擎优化工具WebLangChain_ChatGLM 介绍 本文将详细介绍基于网络检索信息的检索增强生成系统#xff0c;即 WebLangChain。通过整合 LangChain#xff0c;成功将大型语言模型与最受欢迎的外部知识库之一——互联网紧密结合。鉴于中文社区中大型语言模型的蓬勃发展#xff0c;有许多可供利…WebLangChain_ChatGLM 介绍 本文将详细介绍基于网络检索信息的检索增强生成系统即 WebLangChain。通过整合 LangChain成功将大型语言模型与最受欢迎的外部知识库之一——互联网紧密结合。鉴于中文社区中大型语言模型的蓬勃发展有许多可供利用的开源大语言模型。ChatGLM、Baichuan、Qwen 等大语言模型针对中文交互场景进行了优化以提升其对中文理解和问答的能力。所以我们还将介绍如何在检索增强生成应用中集成中文社区广泛使用的开源模型 ChatGLM3。这一步骤的实施将进一步拓展系统的适用性和性能使其更好地服务于中文用户。 本文配套的代码仓库 https://github.com/kebijuelun/weblangchain_chatglm 文章目录 WebLangChain_ChatGLM 介绍检索增强生成 (RAG) 是什么WebLangChain_ChatGLM 流程概述WebLangChain_ChatGLM 运行方式介绍环境准备ChatGLM3 环境配置与运行方式WebLangChain 环境配置与运行方式 聊天页面 Demo WebLangChain_ChatGLM 底层实现介绍RAG 系统设计逻辑探讨什么时候要进行搜索直接使用用户的原始问题作为检索词还是其派生词作为检索词如何处理后续问题即多轮问答查找多个搜索词还是只查找一个需要进行多次搜索吗是应该只给出答案还是应该提供额外的信息 小结引用 检索增强生成 (RAG) 是什么
检索增强生成Retrieval-augmented generation, 简称 RAG是一种通过从外部来源获取事实来增强生成式人工智能模型准确性和可靠性的技术。
法官根据他们对法律的一般理解听取和裁决案件。然而在一些特殊情况下例如医疗事故诉讼或劳资纠纷等案件需要深入的专业知识。为了确保裁决的权威性和准确性法官可能会派遣法庭书记员去法律图书馆查找可以引用的先例和具体案例。
就像一个优秀的法官需要深厚的法律知识一样大型语言模型LLMs也能回答各种用户问题。然而为了提供具有权威性的答案并支持模型生成的信息需要进行一些研究。这种过程类似于法庭书记员的工作被称为检索增强生成。 在检索增强生成过程中模型会利用网络检索、知识库检索等工具通过检索与用户问题相关的文献和先例获取权威性引用来源。这样一来模型生成的答案不仅基于其预训练的知识还结合了最新的检索信息提高了回答的准确性和可信度。这种综合性的方法使得大型语言模型更能胜任回答涉及专业领域的问题类似于法庭书记员在法庭中为法官提供支持和参考的角色。
WebLangChain_ChatGLM 流程概述
一般的检索流程如下
使用包装了 Tavily 的 Search API 的检索器拉取与用户初始查询相关的原始内容。 对于随后的对话轮次我们还将原始查询重新表述为不包含对先前聊天历史的引用的 “独立查询 (standalone query)”。 由于原始文档的大小通常超过模型的最大上下文窗口大小我们执行额外的 上下文压缩步骤 来筛选传递给模型的内容。 首先使用 文本拆分器 拆分检索到的文档。然后使用 嵌入过滤器 删除与初始查询不符合相似性阈值的任何块。 将检索到的上下文、聊天历史和原始问题传递给 LLM 作为最终生成的上下文。
WebLangChain_ChatGLM 运行方式介绍
环境准备
WebLangChain_ChatGLM 使用的代码基于 git 仓库进行管理详细代码参考 github 上的 weblangchain_chatglm 代码仓库 weblangchain_chatglm 代码仓库。 首先需要下载代码库到本地
git clone gitgithub.com:kebijuelun/weblangchain_chatglm.git
cd weblangchain_chatglm然后参考下述流程分别对 ChatGLM3 和 WebLangChain 进行配置。
ChatGLM3 环境配置与运行方式
基于 conda 进行环境隔离conda create -n chatglm python3.10; conda activate chatglm (注意 ChatGLM3 和 WebLangChain 环境隔离很重要能避免一些库版本不兼容问题)
拉取 ChatGLM3 代码模块git submodule update --init --recursive下载 ChatGLM3 的 huggingface 模型: git clone https://huggingface.co/THUDM/chatglm3-6b添加 ChatGLM3 模型路径的环境变量export MODEL_PATH$(realpath ./chatglm3-6b)安装环境依赖pip install -r requirements.txt部署 ChatGLM3 模型服务: cd openai_api_demo; python3 openai_api.py
默认情况下模型以 FP16 精度加载部署 ChatGLM3 服务需要占用大概 13G 显存如果读者的显存无法满足需求可以尝试使用 ChatGLM3 开源的低成本部署方式以 4-bit 量化方式加载模型可以将显存占用量缩小到 6G 左右。模型量化虽然会带来一定的性能损失不过经过测试ChatGLM3-6B 在 4-bit 量化下仍然能够进行自然流畅的生成。 ChatGLM3 代码仓库。
WebLangChain 环境配置与运行方式
基于 conda 进行环境隔离conda create -n weblangchain python3.10; conda activate weblangchain
安装后端依赖项: poetry install.添加环境变量 source env.sh
注确保设置环境变量以配置应用程序默认情况下WebLangChain 使用 Tavily 从网页获取内容。可以通过 tavily 注册 获取 tavily API 密钥并更新到 ./env.sh 中。同时需要在 openai 注册 获取 openai API 密钥更新到 ./env.sh 中。如果想要添加或替换不同的基本检索器例如如果想要使用自己的数据源可以在 main.py 中更新 get_retriever() 方法。
启动 Python 后端: poetry run make start.运行 yarn 安装前端依赖项:
安装 Node Version Manager (NVM): wget -qO- https://raw.githubusercontent.com/nvm-sh/nvm/v0.39.5/install.sh | zsh (可能需要替换 zsh 为用户使用的版本如 bash)设置 NVM 环境变量: export NVM_DIR${XDG_CONFIG_HOME:-$HOME}/.nvm; [ -s $NVM_DIR/nvm.sh ] \. $NVM_DIR/nvm.sh安装 Node.js 版本 18: nvm install 18使用 Node.js 版本 18: nvm use 18进入 “nextjs” 目录并使用 Yarn 安装依赖: cd nextjs; yarn.
启动前端: yarn dev.在浏览器中打开 localhost:3000.
聊天页面 Demo 当成功完成以上环境配置和代码运行后可以在网页端看到以下交互界面该交互界面支持挑选搜索工具和大语言模型默认使用 Tavily 作为搜索工具ChatGLM3 作为大语言模型。在对话框中读者可以尝试进行一些问题咨询weblangchain 的设计就是让用户问一些需要检索互联网内容的问题时能够进行更准确的回复所以对话框下也提供了一些问题样例。 以下是一个问题样例我们在前端页面输入 “宫保鸡丁怎么做” 这个问题。weblangchain_chatglm 首先根据用户的输入问题在互联网检索相关内容可以看到有两个内容被检索出来。然后大语言模型会根据检索内容生成回复详细介绍宫保鸡丁的具体做法。最后Tavily 的检索还会返回一些与用户问题相关的图片可以在回复的最后看到一些与宫保鸡丁相关的图片。 WebLangChain_ChatGLM 底层实现介绍
(注意本节内容的内容需要一定 LCEL 语法知识如果读者不了解请先阅读 LCELLang Chain Expression Language 介绍LangChain 的开发提效技巧 进行学习)
weblangchain_chatglm 代码库中有一些 JavaScript 代码用于搭建前端页面这里我们主要对与 LangChain 相关的 Python 后端代码进行介绍主要的代码逻辑在代码仓库根目录下的 main.py 文件中。
为了对代码的重点逻辑进行讲解这里我们仅对功能主逻辑相关的代码按照顺序进行讲解。首先需要对大语言模型进行定义
# OpenAI API的基本地址 (注意这里其实是本地部署的 ChatGLM3 模型服务地址)
openai_api_base http://127.0.0.1:8000/v1# ChatOpenAI 模型的配置
llm ChatOpenAI(modelgpt-3.5-turbo-16k,streamingTrue,temperature0.1,
).configurable_alternatives(# 为字段设置标识符# 在配置最终可运行时我们可以使用此标识符配置此字段ConfigurableField(idllm),default_keyopenai,# ChatOpenAI 模型的备用配置chatglmchatglmChatOpenAI(modelchatglm3-6b, openai_api_baseopenai_api_base)
)这里代码支持了 OpenAI 的对话模型调用同时也支持调用我们之前本地部署的 ChatGLM3 模型服务。在前端中我们设定了默认模型为 ChatGLM3用户也可以选择 OpenAI 的模型来进行检索增强生成尝试。
然后我们需要定义检索器这里我们默认使用 tavily 检索器。
# 获取与 Tavily 相关的检索器链
def get_retriever():# 创建 OpenAI Embeddings 实例embeddings OpenAIEmbeddings()# 创建 RecursiveCharacterTextSplitter 实例splitter RecursiveCharacterTextSplitter(chunk_size800, chunk_overlap20)# 创建 EmbeddingsFilter 实例用于过滤相似度低于 0.8 的文档relevance_filter EmbeddingsFilter(embeddingsembeddings, similarity_threshold0.8)# 创建 DocumentCompressorPipeline 实例包含 splitter 和 relevance_filterpipeline_compressor DocumentCompressorPipeline(transformers[splitter, relevance_filter])# 创建 TavilySearchAPIRetriever 实例设置 k 值为 3并包含原始内容和图像信息base_tavily_retriever TavilySearchAPIRetriever(k3,include_raw_contentTrue,include_imagesTrue,)# 创建 ContextualCompressionRetriever 实例包含 pipeline_compressor 和 base_tavily_retrievertavily_retriever ContextualCompressionRetriever(base_compressorpipeline_compressor, base_retrieverbase_tavily_retriever)# 创建 GoogleCustomSearchRetriever 实例base_google_retriever GoogleCustomSearchRetriever()# 创建 ContextualCompressionRetriever 实例包含 pipeline_compressor 和 base_google_retrievergoogle_retriever ContextualCompressionRetriever(base_compressorpipeline_compressor, base_retrieverbase_google_retriever)# 创建 YouRetriever 实例使用 YDC API 密钥base_you_retriever YouRetriever(ydc_api_keyos.environ.get(YDC_API_KEY, not_provided))# 创建 ContextualCompressionRetriever 实例包含 pipeline_compressor 和 base_you_retrieveryou_retriever ContextualCompressionRetriever(base_compressorpipeline_compressor, base_retrieverbase_you_retriever)# 创建 KayAiRetriever 实例设置数据集 ID、数据类型和上下文数量base_kay_retriever KayAiRetriever.create(dataset_idcompany,data_types[10-K, 10-Q],num_contexts6,)# 创建 ContextualCompressionRetriever 实例包含 pipeline_compressor 和 base_kay_retrieverkay_retriever ContextualCompressionRetriever(base_compressorpipeline_compressor, base_retrieverbase_kay_retriever)# 创建 KayAiRetriever 实例设置数据集 ID、数据类型和上下文数量为 PressReleasebase_kay_press_release_retriever KayAiRetriever.create(dataset_idcompany,data_types[PressRelease],num_contexts6,)# 创建 ContextualCompressionRetriever 实例包含 pipeline_compressor 和 base_kay_press_release_retrieverkay_press_release_retriever ContextualCompressionRetriever(base_compressorpipeline_compressor,base_retrieverbase_kay_press_release_retriever,)# 返回 retriever 链可配置不同的 retriever 作为默认值并提供 Google、You、Kay 和 Kay Press Release 的备选项return tavily_retriever.configurable_alternatives(ConfigurableField(idretriever),default_keytavily,googlegoogle_retriever,youyou_retriever,kaykay_retriever,kay_press_releasekay_press_release_retriever,).with_config(run_nameFinalSourceRetriever)# 获取检索器
retriever get_retriever()这里我们主要关注其中的 Tavily 检索器。Tavily 是一个搜索 API转为人工智能体设计专门用于 RAG 目的。通过 Tavily Search API人工智能开发人员可以轻松将其应用程序与实时在线信息集成在一起。Tavily 的主要目标是从可信赖的来源提供真实可靠的信息提高 AI 生成内容的准确性和可靠性。 Tavily 有以下几个特点对于 RAG 应用非常友好
速度快返回每个页面的良好摘要因此不必加载每个页面返回与检索问题相关的图像
让我们尝试一个简单的检索来了解 Tavily API 调用的方式和返回结果
from langchain.retrievers.tavily_search_api import TavilySearchAPIRetrieverretriever TavilySearchAPIRetriever(k1)
result retriever.invoke(2022年举办的足球世界杯冠军是)
print(result[0])
# - page_content分享 央视网消息北京时间12月19日2022年卡塔尔世界杯决赛阿根廷对阵法国。 上半场迪马利亚制造点球梅西点球破门随后迪马里亚进球扩大领先优势下半场姆巴佩梅开二度加时阶段双方各入一球拖入点球大战。 最终阿根廷战胜法国夺得第三个世界杯冠军。 metadata{title: 世界杯-阿根廷点球大战战胜法国 时隔36年斩获第三冠_体育_央视网(cctv.com), source: http://worldcup.cctv.com/2022/12/19/ARTIxD38qwfaQp1YAK9Mx608221219.shtml, score: 0.95291, images: None}这里可以看到 Tavily 返回的内容有与检索问题相关的网页内容和网址等信息。
在获取大语言模型和检索器后我们需要将这两个组件连接为链
def create_retriever_chain(llm: BaseLanguageModel, retriever: BaseRetriever
) - Runnable:# 从模板创建重新表达问题的提示CONDENSE_QUESTION_PROMPT PromptTemplate.from_template(REPHRASE_TEMPLATE)# 创建重新表达问题的执行链包含 CONDENSE_QUESTION_PROMPT、llm 和 StrOutputParsercondense_question_chain (CONDENSE_QUESTION_PROMPT | llm | StrOutputParser()).with_config(run_nameCondenseQuestion,)# 创建对话链包含重新表达问题的执行链和检索器conversation_chain condense_question_chain | retriever# 创建分支执行链根据是否有聊天历史选择不同的路径return RunnableBranch((RunnableLambda(lambda x: bool(x.get(chat_history))).with_config(run_nameHasChatHistoryCheck),conversation_chain.with_config(run_nameRetrievalChainWithHistory),),(RunnableLambda(itemgetter(question)).with_config(run_nameItemgetter:question)| retriever).with_config(run_nameRetrievalChainWithNoHistory),).with_config(run_nameRouteDependingOnChatHistory)# 创建 LangChain 的执行链
def create_chain(llm: BaseLanguageModel,retriever: BaseRetriever,
) - Runnable:# 创建检索器链retriever_chain create_retriever_chain(llm, retriever) | RunnableLambda(format_docs).with_config(run_nameFormatDocumentChunks)# 创建 _context 执行映射包含 context、question 和 chat_history 字段_context RunnableMap({context: retriever_chain.with_config(run_nameRetrievalChain),question: RunnableLambda(itemgetter(question)).with_config(run_nameItemgetter:question),chat_history: RunnableLambda(itemgetter(chat_history)).with_config(run_nameItemgetter:chat_history),})# 创建聊天提示prompt ChatPromptTemplate.from_messages([(system, RESPONSE_TEMPLATE),MessagesPlaceholder(variable_namechat_history),(human, {question}),])# 创建响应合成器包含 prompt、llm 和 StrOutputParserresponse_synthesizer (prompt | llm | StrOutputParser()).with_config(run_nameGenerateResponse,)# 创建完整的执行链包含 question、chat_history 和 _context 字段return ({question: RunnableLambda(itemgetter(question)).with_config(run_nameItemgetter:question),chat_history: RunnableLambda(serialize_history).with_config(run_nameSerializeHistory),}| _context| response_synthesizer)# 获取 LangChain 的执行链
chain create_chain(llm, retriever)可以看到这里的链的调用方面使用了一定我们之前介绍的 LCEL 语法。整个链条的调用也是很清晰
首选创建 retriever_chain对于第一个问题即没有对话历史的情况下会直接将问题直接传递给搜索引擎。而对于后续问题根据对话历史生成一个单一的搜索查询传递给搜索引擎使用 Tavily 获取搜索结果。创建 _context 执行映射用于获取搜索结果作为上下文内容将用户的问题 (question)、对话历史 (chat_history)、搜索内容 (_context) 整合到 prompt 中将 prompt 送入大语言模型获取模型回复最后提取文本输出作为最后的返回结果
这里的提示词的构造如下所示
RESPONSE_TEMPLATE \
您是一位专业的研究员和作家负责回答任何问题。基于提供的搜索结果URL 和内容为给定的问题生成一个全面而且信息丰富、但简洁的答案长度不超过 250 字。您必须只使用来自提供的搜索结果的信息。使用公正和新闻性的语气。将搜索结果合并成一个连贯的答案。不要重复文本。一定要使用 [${{number}}] 标记引用搜索结果。只引用最相关的结果以准确回答问题。将这些引用放在提到它们的句子或段落的末尾 - 不要全部放在末尾。如果不同的结果涉及同名实体的不同部分请为每个实体编写单独的答案。如果要在同一句子中引用多个结果请将其格式化为 [${{number1}}] [${{number2}}]。然而您绝对不应该对相同的数字进行这样的操作 - 如果要在一句话中多次引用 number1只需使用 [${{number1}}]而不是 [${{number1}}] [${{number1}}]。为了使您的答案更易读您应该在答案中使用项目符号。在适用的地方放置引用而不是全部放在末尾。如果上下文中没有与当前问题相关的信息只需说“嗯我不确定。”不要试图编造答案。位于以下context HTML 块之间的任何内容都是从知识库中检索到的而不是与用户的对话的一部分。
context{context}
context/请记住一定要在回答的时候带上检索的内容来源标号。如果上下文中没有与问题相关的信息只需说“嗯我不确定。”不要试图编造答案。位于上述 context HTML 块之前的任何内容都是从知识库中检索到的而不是与用户的对话的一部分。
REPHRASE_TEMPLATE \
考虑到以下对话和一个后续问题请将后续问题重新表达为独立的问题。聊天记录
{chat_history}
后续输入{question}
独立问题可以看出提示词的主要目的是限制大型语言模型的响应使其参考检索结果。同时期望模型在响应中添加引用的具体编号。我们注意到这一要求需要语言模型具有较强的指令跟随能力。使用 ChatGPT3.5 相对于 ChatGLM3 能够更高概率地获得期望的响应。然而目前 ChatGLM3 以远低于 ChatGPT3.5 的参数量实现了相应的效果这也表明了 ChatGLM3 具有一定的实力。
整个 RAG 流程通过 LangChain 实现起来非常直观和简洁。在后续的小结中我们将进一步讨论 RAG 的系统设计。
RAG 系统设计逻辑探讨
这里我们将参考 weblangchain 的 RAG 系统设计思路简单讨论 RAG 系统中的注意事项 weblangchain RAG system。
什么时候要进行搜索
在RAG应用程序的开发中面临的一个关键决策是是否始终执行信息查找操作。为何要考虑避免无谓的信息查找呢若应用程序更倾向于成为通用聊天机器人过度频繁的信息查找可能并非理想选择。在这种情况下用户仅仅与应用程序打招呼如说“你好”进行不必要的检索可能只是浪费时间和资源。制定是否执行信息查找的逻辑有多种方法。首先可以使用一个简单的分类层确定是否值得进行信息查找。另一种方法是允许大型语言模型生成搜索查询并在不需要查找信息时生成一个空的搜索查询。然而总是执行信息查找也存在一些潜在问题。首先这种逻辑可能耗费过多时间和资源超过了其实际价值例如可能需要额外的大型语言模型调用。其次如果过于假设用户主要将应用程序用作搜索工具而不是通用聊天机器人可能增加犯错误的风险即在应该查找信息时却未执行此操作。
对于应用程序而言选择了始终执行信息查找。这一决策背后的原因在于 weblangchain 试图构建一个服务于上网咨询问题人员的应用。这使对用户行为有了强烈的先验认知即用户通常寻求信息进行研究。在这种情况下添加逻辑以确定是否执行信息查找可能不值得付出相应的成本时间、金钱、错误的风险。
然而这一决策确实存在一些潜在问题——若始终执行信息查找当有用户试图进行正常对话时可能会显得有些不寻常。
直接使用用户的原始问题作为检索词还是其派生词作为检索词
RAG 的最直接方法是使用用户的问题并直接搜索该短语这种方式既迅速又简便。然而这一方法可能存在一些缺陷具体而言用户的输入可能未充分反映他们实际欲查找的内容。 一个典型的例子是冗长的问题。冗长的问题通常包含大量词语这些词语会分散注意力使真正的问题难以辨认。考虑以下搜索查询作为例子
“嗨我想知道一个问题的答案。可以吗假设可以。我的名字是哈里森是 LangChain 的首席执行官。我喜欢大型语言模型和 OpenAI。梅西·彼得斯是谁”
我们实际上欲回答的问题是 “梅西·彼得斯是谁”但其中有许多分散注意力的文本。为解决这种情况一种方法是不使用原始问题而是从用户的问题生成一个专门的搜索查询。这样做的好处是生成了一个更为明确的搜索查询但缺点是需要额外的大型语言模型调用。
对于我们的应用程序我们假设大多数初始用户问题都相当直接因此我们将选择直接查找原始查询。然而这种方法可能对于类似上述问题的情况无法有效处理。
如何处理后续问题即多轮问答
在基于聊天的RAG应用程序中有效处理后续问题是至关重要的任务。这一重要性源自后续问题引入了以下情况
涉及先前对话的间接后续问题如何处理完全与先前对话无关的后续问题应该如何应对
一般而言有两种常见的处理后续问题的方式
直接搜索后续问题 对于与先前对话毫不相干的问题这种方式效果较好但当后续问题涉及先前对话时可能存在问题。利用大型语言模型生成新的搜索查询或查询 这种方式通常效果良好但会增加一些额外的延迟。
对于后续问题而言它们更有可能不是独立的良好搜索查询。因此为了解决这一问题额外的成本和延迟是值得的以生成一个专门的搜索查询。 比如针对之前的样例在第一轮中问了 “梅西·彼得斯是谁” 问题第二轮中如果询问“她的一些歌曲是什么” 针对前两轮问答生成一个搜索查询以获得与之相关的有效搜索结果。这样就能够更好地处理冗长的问题。
查找多个搜索词还是只查找一个
搜索词的数量也训练一定考量。是否总是一个搜索词或者它可能是多个搜索词如果是多个搜索词是否有时可能是 0 个搜索词允许可变数量的搜索词的好处是更加灵活。缺点是会引入更多的复杂性。这种复杂性是否值得呢
允许 0 个搜索词的复杂性可能不值得。类似于之前是否总是查找信息的决策我们假设用户使用我们的 weblangchain 应用是因为他们有意查找信息。因此总是生成一个查询是合理的。生成多个查询会增加更长的搜索时间。为了保持系统的简洁性weblangchain 应用程序中将只生成一个搜索查询。
然而这也有其不足之处。考虑下面的问题
“谁赢得了 2023 年第一场 NFL 比赛谁赢得了 2023 年女足世界杯”
这是在询问两个非常不同的事情这种情况使用一个检索词往往无法获取最佳的结果。检索结果一般只与其中一个问题有关然后另外一个问题往往大语言模型未完全解决幻觉问题的前提下在不知道事实的情况下会进行瞎编。
需要进行多次搜索吗
大多数 RAG 应用程序只执行单个查找步骤。然而让它执行多个查找步骤可能会有一些好处。 请注意这与生成多个搜索查询是不同的。当生成多个搜索查询时可以并行搜索这些查询。允许多次查找的动机是最终答案可能取决于先前查找步骤的结果而这些查找必须按顺序进行。在 RAG 应用程序中这样做相对较少见因为它会增加更多的成本和延迟。
能够多次查找信息的应用程序开始变得更像智能体。这有其优缺点。优点是它使这些应用程序能够回答更复杂问题的更长尾部分。然而这通常是以延迟为代价这些应用程序更慢和可靠性它们有时可能偏离轨道为代价的。
不能多次查找信息的应用程序则相反——它们通常更快更可靠但能力较差难以处理更复杂问题的长尾。
举个例子考虑一个问题
“谁赢得了 2023 年女足世界杯该国的 GDP 是多少”
考虑到单次检索的应用程序不能多次查找信息我们不会指望它能够很好地处理这种情况。而多次搜索的应用程序由于可以执行多个动作它有可能正确回答这个问题。不过值得注意的是回答所花费的时间可能会明显长于单次搜索的应用程序。weblangchain 为了更快的聊天体验使用了单次检索的设计思路。
是应该只给出答案还是应该提供额外的信息
一种广泛采用的做法是不仅提供答案还提供答案所依据的来源引用。这对于用户具有重要意义原因主要是它使得验证大语言模型在其响应中提出的任何主张变得容易因为用户可以导航到引用的源并自行检查。
weblangchain 的提示词的使用是在特定的约定下引用其来源。该特定约定涉及要求大语言模型生成以下注释中的来源[N]。然后在客户端解析它并将其呈现为超链接。效果如下 需要注意不是所有的大语言模型都能确保这样的来源引用效果实际测试使用 ChagGPT3.5 还是有比较大概率能按照提示词的约束对每个重要的语句都给定参考链接的如果不能正确给出则需要用户自行查看 weblangchain 给定的引用链接来确认信息来源的可靠性。
小结
在本文中我们全面介绍了一个检索增强生成程序样例具体涵盖了 weblangchain_chatglm 的环境安装、运行方式以及底层原理。我们深入了解了这一系统的设计要点并强调了在检索增强生成的系统中需要特别注意的方面。这些设计决策往往是一种权衡需要开发者在实际应用场景中做出明智的选择。例如总是查找信息可能增加系统的复杂性而允许多次查找信息可能引入更多的延迟。这些权衡需要根据具体的应用场景和用户需求做出并在系统设计中找到最佳平衡点。
引用 weblangchain_chatglm 代码仓库 ChatGLM3 代码仓库 weblangchain RAG system what-is-retrieval-augmented-generation langchain-expression-language