langchain-ChatGLM源码阅读:参数设置

文章目录

    • 上下文关联
    • 对话轮数
    • 向量匹配 top k
    • 控制生成质量的参数
    • 参数设置心得

上下文关联

上下文关联相关参数:

  • 知识相关度阈值score_threshold
  • 内容条数k
  • 是否启用上下文关联chunk_conent
  • 上下文最大长度chunk_size

其主要作用是在所在文档中扩展与当前query相似度较高的知识库的内容,作为相关信息与query按照prompt规则组合后作为输入获得模型的回答。

在这里插入图片描述

  • 获取查询句query嵌入:faiss.py
def similarity_search_with_score(self, query: str, k: int = 4) -> List[Tuple[Document, float]]:"""Return docs most similar to query.Args:query: Text to look up documents similar to.k: Number of Documents to return. Defaults to 4.Returns:List of Documents most similar to the query and score for each"""embedding = self.embedding_function(query)docs = self.similarity_search_with_score_by_vector(embedding, k)return docs
  • 上下文生成:MyFAISS.py
def seperate_list(self, ls: List[int]) -> List[List[int]]:# TODO: 增加是否属于同一文档的判断lists = []ls1 = [ls[0]]for i in range(1, len(ls)):if ls[i - 1] + 1 == ls[i]:ls1.append(ls[i])else:lists.append(ls1)ls1 = [ls[i]]lists.append(ls1)return listsdef similarity_search_with_score_by_vector(self, embedding: List[float], k: int = 4) -> List[Document]:faiss = dependable_faiss_import()# (1,1024)vector = np.array([embedding], dtype=np.float32)# 默认FALSEif self._normalize_L2:faiss.normalize_L2(vector)# shape均为(1, k),这步获取与query有top-k相似度的知识库scores, indices = self.index.search(vector, k)docs = []id_set = set()store_len = len(self.index_to_docstore_id)rearrange_id_list = False# 遍历找到的k个最相似知识库的索引# k是第一次的筛选条件,score是第二次的筛选条件for j, i in enumerate(indices[0]):if i == -1 or 0 < self.score_threshold < scores[0][j]:# This happens when not enough docs are returned.continueif i in self.index_to_docstore_id:_id = self.index_to_docstore_id[i]# 执行接下来的操作else:continue# index→id→contentdoc = self.docstore.search(_id)if (not self.chunk_conent) or ("context_expand" in doc.metadata and not doc.metadata["context_expand"]):# 匹配出的文本如果不需要扩展上下文则执行如下代码if not isinstance(doc, Document):raise ValueError(f"Could not find document for id {_id}, got {doc}")doc.metadata["score"] = int(scores[0][j])docs.append(doc)continue# 其实存的都是indexid_set.add(i)docs_len = len(doc.page_content)# 跟外部变量定义的k重名了,烂# 一个知识库是分句后得到的一句话,i是当前知识库在总知识库中的位置,store_len是总知识库大小# 所以k说的是扩充上下文时最多能跨多少个知识库for k in range(1, max(i, store_len - i)):break_flag = Falseif "context_expand_method" in doc.metadata and doc.metadata["context_expand_method"] == "forward":expand_range = [i + k]elif "context_expand_method" in doc.metadata and doc.metadata["context_expand_method"] == "backward":expand_range = [i - k]else:# i=4922, k=1 → [4923, 4921]expand_range = [i + k, i - k]for l in expand_range:# 确保扩展上下文时不会造成重复if l not in id_set and 0 <= l < len(self.index_to_docstore_id):_id0 = self.index_to_docstore_id[l]doc0 = self.docstore.search(_id0)# 如果当前字数大于250或者是知识库跨了文件,扩充上下文过程终止# 这一句有些问题,有一端跨文件就终止,应该是两端同时跨才终止才对if docs_len + len(doc0.page_content) > self.chunk_size or doc0.metadata["source"] != \doc.metadata["source"]:break_flag = Truebreakelif doc0.metadata["source"] == doc.metadata["source"]:docs_len += len(doc0.page_content)id_set.add(l)rearrange_id_list = Trueif break_flag:break# 如果没有扩展上下文(不需要或是不能)if (not self.chunk_conent) or (not rearrange_id_list):return docsif len(id_set) == 0 and self.score_threshold > 0:return []id_list = sorted(list(id_set))# 连续必然属于同一文档,但不连续也可能在同一文档# 返回二级列表,第一级是连续的index列表,第二级是具体indexid_lists = self.seperate_list(id_list)for id_seq in id_lists:for id in id_seq:if id == id_seq[0]:_id = self.index_to_docstore_id[id]# doc = self.docstore.search(_id)doc = copy.deepcopy(self.docstore.search(_id))else:_id0 = self.index_to_docstore_id[id]doc0 = self.docstore.search(_id0)doc.page_content += " " + doc0.page_contentif not isinstance(doc, Document):raise ValueError(f"Could not find document for id {_id}, got {doc}")# indices为相关文件的索引# 因为可能会将多个连续的id合并,因此需要将同一seq内所有位于top-k的知识库的分数取最小值作为seq对应的分数doc_score = min([scores[0][id] for id in [indices[0].tolist().index(i) for i in id_seq if i in indices[0]]])doc.metadata["score"] = int(doc_score)docs.append(doc)# 注意这里docs没有按相似度排序,可以自行加个sortreturn docs
  • prompt生成:local_doc_qa.py
def get_knowledge_based_answer(self, query, vs_path, chat_history=[], streaming: bool = STREAMING):related_docs_with_score = vector_store.similarity_search_with_score(query, k=self.top_k)torch_gc()if len(related_docs_with_score) > 0:prompt = generate_prompt(related_docs_with_score, query)else:prompt = queryanswer_result_stream_result = self.llm_model_chain({"prompt": prompt, "history": chat_history, "streaming": streaming})def generate_prompt(related_docs: List[str],query: str,prompt_template: str = PROMPT_TEMPLATE, ) -> str:context = "\n".join([doc.page_content for doc in related_docs])prompt = prompt_template.replace("{question}", query).replace("{context}", context)return prompt

对话轮数

在这里插入图片描述
其实就是要存多少历史记录,如果为0的话就是在执行当前对话时不考虑历史问答

  • 模型内部调用时使用,以chatglm为例:chatglm_llm.py
 def _generate_answer(self,inputs: Dict[str, Any],run_manager: Optional[CallbackManagerForChainRun] = None,generate_with_callback: AnswerResultStream = None) -> None:history = inputs[self.history_key]streaming = inputs[self.streaming_key]prompt = inputs[self.prompt_key]print(f"__call:{prompt}")# Create the StoppingCriteriaList with the stopping stringsstopping_criteria_list = transformers.StoppingCriteriaList()# 定义模型stopping_criteria 队列,在每次响应时将 torch.LongTensor, torch.FloatTensor同步到AnswerResultlistenerQueue = AnswerResultQueueSentinelTokenListenerQueue()stopping_criteria_list.append(listenerQueue)if streaming:history += [[]]for inum, (stream_resp, _) in enumerate(self.checkPoint.model.stream_chat(self.checkPoint.tokenizer,prompt,# 为0时history返回[]history=history[-self.history_len:-1] if self.history_len > 0 else [],max_length=self.max_token,temperature=self.temperature,top_p=self.top_p,top_k=self.top_k,stopping_criteria=stopping_criteria_list)):

向量匹配 top k

虽然放在了模型配置那一页,但实际上还是用来控制上下文关联里面的内容条数k的,不知道为什么写了两遍。。。
在这里插入图片描述

控制生成质量的参数

这些参数没有在前端显式地给出,而是写死在了模型定义里

  • 模型定义,以chatglm为例:chatglm_llm.py
class ChatGLMLLMChain(BaseAnswer, Chain, ABC):max_token: int = 10000temperature: float = 0.01# 相关度top_p = 0.4# 候选词数量top_k = 10checkPoint: LoaderCheckPoint = None# history = []history_len: int = 10

参数设置心得

  • score_threshold和k设太小会找不到问题对应的原文件,太大找到一堆不相关的
  • chunk_size设太小不能在原文件里找到问题对应的原文,太大无法有效归纳出答案
  • temperature和top_p默认值下生成的答案基本固定,但也很死板;过大的temperature导致回答的事实不稳定;过大的top_p导致回答的语言风格不稳定;调整top_k没发现结果有什么变化

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/59734.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

基于Doris实时数据开发的一些注意事项

300万字&#xff01;全网最全大数据学习面试社区等你来&#xff01; 最近Doris的发展大家是有目共睹的。例如冷热分离等新特性的持续增加。使得Doris在易用和成本上都有大幅提升。 基于Doris的一些存储实时数仓在越来越多的场景中开始有一些实践。大家也看到了这种方案频繁出现…

设备固定资产管理系统

资产管理是企业经营和发展的基础&#xff0c;特别是设备资产管理。适当的设备资产管理可以有效地提升企业的经营效率&#xff0c;为提高核心竞争能力提供高效的前提。 固资及设备管理系统&#xff08;EAM&#xff09;它是一种有效的固定资产管理模式&#xff0c;可以帮助企业更…

四 、Mysql 开发

四 、Mysql开发 102 可以使用MySQL直接存储文件吗&#xff1f; 可以使用 BLOB (binary large object)&#xff0c;用来存储二进制大对象的字段类型。 TinyBlob 255 值的长度加上用于记录长度的1个字节(8位) Blob 65K值的长度加上用于记录长度的2个字节(16位) MediumBlob 16M值…

【iOS安全】开启任意app的WebView远程调试

参考&#xff1a;https://mp.weixin.qq.com/s/bNKxQaVrPaXsZ5BPbsXy7w &#xff08;来自周智老师的公众号&#xff09; 概述 Safari 有一个内置的前端调试器&#xff0c; 在iPhone通过局域网或者USB连接MacBook 并启用Safari 远程调试之后&#xff0c;前端调试器默认情况下对…

Visual Studio Code中对打开的脚本格式统一

什么是Language Server Protocol (LSP)? Language Server Protocol&#xff08;语言服务器协议&#xff0c;简称LSP&#xff09;是微软在2016年提出的一套统一的通讯协议方案。LSP定义了一套编辑器或者IDE与语言服务器&#xff08;Language Server&#xff09;之间使用的协议&…

八大排序

目录 选择排序-直接插入排序 插入排序-希尔排序 选择排序-简单选择排序 选择排序-堆排序 交换排序-冒泡排序 交换排序-快速排序 归并排序 基数排序 选择排序-直接插入排序 基本思想: 如果碰见一个和插入元素相等的&#xff0c;那么插入元素把想插入的元素放在相等元素…

研发工程师玩转Kubernetes——使用emptyDir在同一Pod不同容器间共享数据

kubernets可以通过emptyDir实现在同一Pod的不同容器间共享文件系统。 正如它的名字&#xff0c;当Pod被创建时&#xff0c;emptyDir卷会被创建&#xff0c;这个时候它是一个空的文件夹&#xff1b;当Pod被删除时&#xff0c;emptyDir卷也会被永久删除。 同一Pod上不同容器之间…

Python 之禅

Python 社区的理念都包含在 Tim Peters 撰写的 “Python 之禅” 中 在 Windows 平台的 cmd 命令中打开 python&#xff0c;输入 import this&#xff0c;就能看到 Python 之禅: 翻译&#xff1a; Tim Peters 的 python 之禅Beautiful is better than ugly. # 优美胜于丑陋&am…

Cesium相机理解

关于cesium相机&#xff0c;包括里面内部原理网上有很多人讲的都很清楚了&#xff0c;我感觉这两个人写的都挺好得&#xff1a; 相机 Camera | Cesium 入门教程 (syzdev.cn) Cesium中的相机—setView&lookAtTransform_cesium setview_云上飞47636962的博客-CSDN博客上面这…

Metamask登录方式集成

Metamask登录 https://www.toptal.com/ethereum/one-click-login-flows-a-metamask-tutorial#how-the-login-flow-works 参考&#xff1a; https://zh.socialgekon.com/one-click-login-with-blockchain 后端需要在用户表中增加address和nonce字段。兼容其他登录方式&#xff0…

06-5_Qt 5.9 C++开发指南_Splash 与登录窗口(MouseEvent鼠标事件;注册表;加密)

文章目录 1. 实例功能概述2. 对话框界面设计和类定义3. QDIgLogin 类功能实现3.1 构造函数里的初始化3.2 应用程序设置的存储3.3 字符串加密3.4 用户名和密码输入判断3.5 窗口拖动功能的实现 4. Splash 登录窗口的使用5. 框架及源码5.1 可视化UI设计5.2 qdlglogin.h5.3 qdlglog…

Java练习

添加你喜欢的歌手以及你喜欢他唱过的歌曲&#xff0c;并遍历 package Test0726;import java.util.ArrayList; import java.util.HashMap; import java.util.*;public class SingerTest {public static void main(String[] args) {HashMap singers new HashMap();String singe…