上星期我发布了一篇用llama_index制作文档机器人的文章,感兴趣的朋友不少。于是,这周我多花了一些时间研究它,将一些运用上的常见问题记录了下来。
从本文开始,笔者将会让GPT更多地参与到文字撰写中。
GPT:在本文中,咱们将深入评论llama_index的运用,并供给一些关键的留意事项,以保证你可以成功完结你的方针。请坐稳,放松自己,准备好进入llama_index的令人兴奋的国际吧!
笔者:倒也没有那么令人兴奋……
1.两个留意事项
调试:检查实际发送给GPT的内容
GPT:调试是运用任何技术的过程中都必须考虑到的重要步骤。在llama_index中,你可能会好奇它真正传给GPT模型的文字是什么。这样可以协助你更好地了解llama_index和GPT模型之间的交互,并保证它们之间的通讯是正确的。
gpt-index.readthedocs.io/en/latest/g…
LLM模型的挑选
GPT:当你开始看log时,会意识到它query时默认运用的大预言模型是text-davinci-002模型。假如你想要选用gpt-3.5-turbo模型,你需求进行一些修正。
gpt-index.readthedocs.io/en/latest/g…
2.llama_index运作流程、怎么进行更复杂的查询(要点)
GPT:在第一篇文章中,咱们介绍了GPTSimpleVectorIndex将一切文档作为一个接连的文本进行查询。其流程大概是这样的:
+-----------+ +-----------------+ +-------------+
| 相关文档 | ——> | Embedding API | ——> | VectorIndex |
+-----------+ +-----------------+ +-------------+
|
------------------+
|
V
+-----------+ +-------+ +--------------+
| 用户问题 | ——----------> | Query | ——> | GPT API |
+-----------+ +-------+ +--------------+
|
|
V
+--------+
| Answer |
+--------+
笔者:图像得很好。留意其中VectorIndex可以被存到磁盘,不需求每次都创立。
GPT:但是,假如你的资料库许多,一个vecIndex可能不够用,你可以创立多个Index,并用不同的方法安排你的文档。llama_index官方供给了一个示例来协助你完结这个方针:
gpt-index.readthedocs.io/en/latest/h…
笔者:对,这个示例有两个难点:
不同的index(索引方法)
笔者:官方供给的几个典型Index如下:
gpt-index.readthedocs.io/en/latest/g…
图中只画了query操作的步骤,而且看起来也比较难了解,你可以加上我的总结来服用:
●ListIndex:query一个listIndex时,它会按照顺序,逐个对它的子index进行query操作。每一次答案都会对前一个答案进行refine操作(GPT优化)。
+-----------+ +-----------------+ +-------------+
| 相关文档 | ——> | 多个子Index | ——> | ListIndex |
+-----------+ +-----------------+ +-------------+
|
------------------+
|
V
+-----------+ +-------+ +----------------+ +----------------+ +---------------+
| 用户问题 | ——----------> | Query | ——> | 子Index调query |-->| 子Index调query |-->| 子Index调query |
+-----------+ +-------+ +----------------+ +----------------+ +---------------+
| | |
V V V
+--------+ +---------------+ +----------------+
| Answer | ----> | 新旧Answer一同 | ----> | 新旧Answer一同 |
| | | 让GPT优化 | | 让GPT优化 |
+--------+ +---------------+ +----------------+
|
V
+-------+
| Answer|
+-------+
●KeywordTableIndex:创立index时,会先提取一切子index的内容的关键词;到了query这个TableIndex时,会将疑问句里的关键词提取出来,然后对子index的关键词进行匹配。拿出一切匹配的子index,逐个进行query。然后像List一样,会逐个进行refine操作(对子index提取关键词、对问题提取关键词的算法都有三个:正则、RAKE、问GPT)
+-----------+ +-----------------+ +------------------+ +-------------------+
| 相关文档 | ——> | 多个子Index | ——> | 提取各自的关键词 | ——> | KeyWordTableIndex |
+-----------+ +-----------------+ +------------------+ +-------------------+
|
--------------------------------------------+
|
V
+-----------+ +-------+ +---------------------+
| 用户问题 | ——----------> | Query | ——> | 提取用户问题的keyword|
+-----------+ +-------+ +---------------------+
| |
V |
+----------------+ |
| 找出一切keyword| <-----|
| 符合的子index |
+----------------+
|
V
+----------------+ +---------------+ +----------------+ +---------------+
| 子Index调query |-->| 子Index调query | -->| 子Index调query |-->| 子Index调query |
| | | | | | | |
+----------------+ +---------------+ +----------------+ +---------------+
| | | |
V V V V
+--------+ +---------------+ +---------------+ +----------------+
| Answer | ----> | 新旧Answer一同 | ----> | 新旧Answer一同 | ----> | 新旧Answer一同 |
| | | 让GPT优化 | | 让GPT优化 | | 让GPT优化 |
+--------+ +---------------+ +---------------+ +----------------+
|
V
+-----------+
| 终究Answer|
+-----------+
●TreeIndex:创立index时,会先找GPT提取一切子index的总结内容。到了用户query阶段,会将这些index的总结词发给GPT,让GPT挑选其中的几个节点,然后query所选中的节点,得到终究成果。
+-----------+ +-----------------+ +--------------------------+ +-------------------+
| 相关文档 | ——> | 多个子Index | ——> | 找GPT总结它们内容(summary) | ——> | TreeIndex |
+-----------+ +-----------------+ +--------------------------+ +-------------------+
|
---------------------------------------------------+
|
V
+-----------+ +-------+
| 用户问题 | ——----------> | Query |
+-----------+ +-------+
|
V
+-------------------+
| 询问GPT,哪n个节点 |
| 的summary最匹配问题 |
+--------------------+
|
V
+----------------+ +---------------+ +----------------+ +---------------+
| 子Index调query |-->| 子Index调query | -->| 子Index调query |-->| 子Index调query |
| | | | | | | |
+----------------+ +---------------+ +----------------+ +---------------+
| | | |
V V V V
+--------+ +---------------+ +---------------+ +----------------+
| Answer | ----> | 新旧Answer一同 | ----> | 新旧Answer一同 | ----> | 新旧Answer一同 |
| | | 让GPT优化 | | 让GPT优化 | | 让GPT优化 |
+--------+ +---------------+ +---------------+ +----------------+
|
V
+-----------+
| 终究Answer|
+-----------+
像ListIndex和TableIndex,都有一个特色:假如子index的数量会不停增长,那么在用户提问时,你无法控制终究会产生多少次query。笔者以为假如你的运用实时性要求较高,尽量不要滥用它们。只要在表达确认长度的编排联系的时分,query次数是可控的,就可以用他们。
别的。上图中多个answer兼并优化这一个阶段称为“response合成”阶段,图里画的是 create and refine
方法,llama_index别的还供给了tree_summarize
方法,这里就不赘述了。
ComposableGraph
笔者:比如中说到的另一个可能比较困惑的东西:ComposableGraph,个人觉得比较恰当的了解是:index之间的嵌套只代表它们的父子联系,假如你希望你的查询是递归进行的,就要用ComposableGraph。
笔者:别的,有了ComposableGraph之后,你给每个Index传递其参数的方法就得经过ComposableGraph.query函数的query_config参数,见下方代码。其中struct_id、index_struct_type都是用于挑选子index的。query_mode、query_kwargs则是要传递给它们的参数。
[
{
"index_struct_id":vectorIndex1.doc_id(),
"index_struct_type":"simple_dict",
"query_mode":"default",
"query_kwargs":{
"similarity_top_k":3
}
},
{
"index_struct_type":"simple_dict",
"query_mode":"default",
"query_kwargs":{
"similarity_top_k":1
}
}
]
3. prompt
GPT:上文所说到的一些操作。比如query、refine、KeywordTable的提取关键字、TreeIndex的summary等操作,都需求请求GPT模型来完结。假如你想要更好地了解llama_index的作业原理,那么找到这些操作的prompt是十分重要的。在llama_index的代码中,你可以找到这些操作对应的prompt,
github.com/jerryjliu/l…
笔者:我在运用的过程中,遇到过一个Bug:在上文说到的ListIndex执行query操作后,在response合成时,gpt-3.5在前一个answer里得到了有用的东西,然后鄙人一次refine时,却变成这样的回来:“上文现已供给适宜的答案,不需求进行优化”。
究其原因,便是gpt-3.5-turbo
没有遵循llama_index内置提示词的规则干事。所以,笔者只能经过自定义提示词的方法解决。
gpt-index.readthedocs.io/en/latest/h…
假如你用的是ComposableGraph,则可以在query_configs里传入。
别的,因为默认提示词是英文的,用于做中文产品时,有时你输入中文问题它会回答英文。也要经过该问题解决,只需求将它内部的default_prompt翻译一下即可。
4. 显现引证来源
GPT:将你的资料库整理成树形后。假如你正在开发问答类运用,那么出处引证功用就十分重要了。因为被GPT总结过后的内容很可能会丢掉一些信息,所以引证原始内容就变得尤为必要,new bing就有这个功用。在llama_index中,你可以很容易地找到它所运用的index,并从回来成果中获取它的内容。下面供给一个比如来协助你更好地了解怎么完结这个功用:假设你正在运用llama_index的query操作,得到了一个含有多个答案的回来成果。接下来,你可以经过检查每个答案所用到的index来确认哪个答案是正确的,然后运用index的内容作为出处引证。鄙人面的段落中,我将为你供给更多具体的指导和协助,以保证你可以成功完结出处引证功用。
res=graph.query('UsingAction怎么用?')
responseByGPT=str(res) # 文字成果
refDoc=[]
fornodeinres.source_nodes:
ifnode.similarity!=None:
refDoc.append(f'(类似度{node.similarity})https://puerts.github.io/docs/puerts'+node.doc_id) # 此处我提早将文档路径设为了doc_id,你也可以设在extra_info里
print("\n".join([
responseByGPT,
"relatedDoc",
"\n".join(refDoc)
]))
5. 总结
笔者:我在写这一篇的时分,chatgpt-plugin现已官宣了,其配套开源项目(相当于插件开发套件) openai/chatgpt-retrieval-plugin也现已发布。技术方案和llama_index
共同。很显然这套提早搜索的方案,今后会是GPT定制的常态操作。所以理论上来说只要了解了llama_index
,了解chatgpt-plugin
就不难。
chatgpt-retrieval-plugin
和llama_index
不一样的是,它只供给了vectorIndex的搜索方法(其实最有用的便是这个),而且它内部没有完结与GPT QA的操作 —— 在chatgpt-plugin
线上运行时,这部分作业是运作在他们服务器的。所以它和llama_index
并不彻底堆叠,他们是可以共存运用的。
另一个不一样的点:他们内置了一个简略的Rest服务器供给这个vector搜索服务,这样咱们可以用别的语言运用它,或是对接到别的LLM上。但更亮的是:会给这个Rest服务器生成十分利于GPT了解的自然语言API阐明文件,这是chatgpt-plugin运作的核心。
更多的有缘再写吧。