当前位置: 首页 > article >正文

LlamaIndex核心概念查询管道(Query Pipelines)简介

LlamaIndex 查询管道简介

概述

LlamaIndex提供了一个声明性查询API,允许您将不同的模块链接在一起,以便在数据上编排从简单到高级的工作流。

这是以QueryPipeline抽象为中心的。装入各种模块(从llm到提示符,再到检索器,再到其他管道),将它们全部连接到一个顺序链或DAG中,并端到端地运行它。

注意:您可以在没有声明性管道抽象的情况下编排所有这些工作流(通过命令式地使用模块并编写自己的函数)。那么,QueryPipeline 的优点是什么呢?

  • 用更少的代码行/样板文件表达通用工作流
  • 更大的可读性
  • 与常见的低代码/无代码解决方案(例如LangFlow)有更好的奇偶性/更好的集成点
  • 声明式接口允许管道组件的易于序列化,提供管道的可移植性/更容易部署到不同的系统。

指南

在本指南中,我们将介绍我们的QueryPipeline界面并展示一些您可以处理的基本工作流程。

  • 将提示和 LLM 链接在一起
  • 将查询重写(提示 + LLM)与检索链接在一起
  • 将完整的RAG 查询管道(查询重写、检索、重新排序、响应合成)链接在一起
  • 设置自定义查询组件
  • 逐步执行管道

设置

在这里我们设置了一些数据+索引(来自 PG 的文章),我们将在本食谱的其余部分使用它们。

pip install llama-index-embeddings-openai
pip install llama-index-postprocessor-cohere-rerank
pip install llama-index-llms-openai
# 设置 Arize Phoenix 用于日志记录/可观察性
import  phoenix  as  px
import llama_index.core

px.launch_app ()
llama_index.core.set_global_handler("arize_phoenix")

🌍 要在浏览器中查看 Phoenix 应用程序,请访问 http://127.0.0.1:6006/
📺 要在笔记本中查看 Phoenix 应用程序,请运行 px.active_session().view()
📖 有关如何使用 Phoenix 的更多信息,请查看 https://docs.arize.com/phoenix

import os

os.environ["OPENAI_API_KEY"] = "sk-..."
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings

Settings.llm = OpenAI(model="gpt-3.5-turbo")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
from llama_index.llms.openai import OpenAI
from llama_index.embeddings.openai import OpenAIEmbedding
from llama_index.core import Settings

Settings.llm = OpenAI(model="gpt-3.5-turbo")
Settings.embed_model = OpenAIEmbedding(model="text-embedding-3-small")
from llama_index.core import SimpleDirectoryReader

reader = SimpleDirectoryReader("../data/paul_graham")
docs = reader.load_data()
import os
from llama_index.core import (
    StorageContext,
    VectorStoreIndex,
    load_index_from_storage,
)

if not os.path.exists("storage"):
    index = VectorStoreIndex.from_documents(docs)
    # save index to disk
    index.set_index_id("vector_index")
    index.storage_context.persist("./storage")
else:
    # rebuild storage context
    storage_context = StorageContext.from_defaults(persist_dir="storage")
    # load index
    index = load_index_from_storage(storage_context, index_id="vector_index")

将提示和 LLM 链接在一起

在本节中,我们展示了将提示与LLM 链接在一起的超级简单的工作流程。

我们只需chain在初始化时进行定义。这是查询管道的一个特殊情况,其中的组件是纯顺序的,我们会自动将输出转换为下一个输入的正确格式。

from llama_index.core.query_pipeline import QueryPipeline
from llama_index.core import PromptTemplate

# try chaining basic prompts
prompt_str = "Please generate related movies to {movie_name}"
prompt_tmpl = PromptTemplate(prompt_str)
llm = OpenAI(model="gpt-3.5-turbo")

p = QueryPipeline(chain=[prompt_tmpl, llm], verbose=True)
output = p.run(movie_name="The Departed")

运行模块 8dc57d24-9691-4d8d-87d7-151865a7cd1b 并输入:
电影名称:无间行者
运行模块 7ed9e26c-a704-4b0b-9cfd-991266e754c0 并输入:
消息:请生成与《无间行者》相关的电影

print(str(output))

助手:1.《无间道》(2002)——启发《无间道风云》的香港原创电影
2. 城中大盗(2010)——本·阿弗莱克执导并主演的犯罪惊悚片
3.《神秘河》(2003)——克林特·伊斯特伍德执导的犯罪剧
4.《好家伙》(1990)——马丁·斯科塞斯执导的经典黑帮电影
5. 爱尔兰人(2019)——马丁·斯科塞斯执导的另一部犯罪剧,由罗伯特·德尼罗和阿尔·帕西诺主演
6. 无间行者 (2006) - 无间行者是一部 2006 年的美国犯罪电影,由马丁·斯科塞斯执导,威廉·莫纳汉编剧。这是 2002 年香港电影《无间道》的翻拍版。该片由莱昂纳多·迪卡普里奥、马特·达蒙、杰克·尼科尔森和马克·沃尔伯格主演,马丁·辛、雷·温斯顿、维拉·法米加和亚历克·鲍德温担任配角。

查看中间输入/输出

为了调试和其他目的,我们还可以查看每个步骤的输入和输出。

output, intermediates = p.run_with_intermediates(movie_name="The Departed")

运行模块 8dc57d24-9691-4d8d-87d7-151865a7cd1b 并输入:
电影名称:无间行者

运行模块 7ed9e26c-a704-4b0b-9cfd-991266e754c0 并输入:
消息:请生成与《无间行者》相关的电影

intermediates["8dc57d24-9691-4d8d-87d7-151865a7cd1b"]

ComponentIntermediates(inputs={‘movie_name’: ‘无间行者’}, output={‘prompt’: ‘请生成与《无间行者》相关的电影’})

intermediates["7ed9e26c-a704-4b0b-9cfd-991266e754c0"]

ComponentIntermediates(inputs={‘messages’: ‘请生成与《无间行者》相关的电影’}, output={‘output’: ChatResponse(message=ChatMessage(role=<MessageRole.ASSISTANT: ‘assistant’>, content=‘1. 无间道 (2002) - 启发《无间行者》的原创香港电影\n2. 城中大盗 (2010) - 本·阿弗莱克执导的犯罪惊悚片\n3. 神秘河 (2003) - 克林特·伊斯特伍德执导的犯罪剧\n4. 好家伙 (1990) - 马丁·斯科塞斯执导的经典犯罪片\n5. 爱尔兰人 (2019) - 马丁·斯科塞斯执导的另一部犯罪片,由罗伯特·德尼罗和阿尔·帕西诺主演\n6. 教父 (1972) - 弗朗西斯·福特·科波拉执导的经典犯罪片\n7. 热火警花 (1995) - 一部惊悚片,由迈克尔·曼执导,阿尔·帕西诺和罗伯特·德尼罗主演\n8. 无间行者 (2006) - 由马丁·斯科塞斯执导的犯罪惊悚片,莱昂纳多·迪卡普里奥和马特·达蒙主演。’, additional_kwargs={}), raw={‘id’: ‘chatcmpl-9EKf2nZ4latFJvHy0gzOUZbaB8xwY’, ‘choices’: [Choice(finish_reason=‘stop’, index=0, logprobs=None, message=ChatCompletionMessage(content=‘1. 无间道 (2002) - 启发《无间行者》的原版香港电影\n2. 城中大盗 (2010) - 本·阿弗莱克执导的犯罪惊悚片\n3. 神秘河 (2003) - 克林特·伊斯特伍德执导的犯罪剧\n4.好家伙(1990)——马丁·斯科塞斯执导的经典犯罪片\n5. 爱尔兰人(2019)——马丁·斯科塞斯执导的另一部犯罪片,由罗伯特·德尼罗和阿尔·帕西诺主演\n6. 教父(1972)——弗朗西斯·福特·科波拉执导的经典犯罪片\n7. 盗火线(1995)——迈克尔·曼执导的犯罪惊悚片,由阿尔·帕西诺和罗伯特·德尼罗主演\n8.无间行者 (2006) - 由马丁·斯科塞斯执导的一部犯罪惊悚片,莱昂纳多·迪卡普里奥和马特·达蒙主演。’, role=‘assistant’, function_call=None, tool_calls=None))], ‘created’: 1713203040, ‘model’: ‘gpt-3.5-turbo-0125’, ‘object’: ‘chat.completion’, ‘system_fingerprint’: ‘fp_c2295e73ad’, ‘usage’: CompletionUsage(completion_tokens=184, prompt_tokens=15, total_tokens=199)}, delta=None, logprobs=None, additional_kwargs={})})

尝试输出解析

让我们将输出解析为结构化的 Pydantic 对象。

from typing import List
from pydantic import BaseModel, Field
from llama_index.core.output_parsers import PydanticOutputParser


class Movie(BaseModel):
    """Object representing a single movie."""

    name: str = Field(..., description="Name of the movie.")
    year: int = Field(..., description="Year of the movie.")


class Movies(BaseModel):
    """Object representing a list of movies."""

    movies: List[Movie] = Field(..., description="List of movies.")


llm = OpenAI(model="gpt-3.5-turbo")
output_parser = PydanticOutputParser(Movies)
json_prompt_str = """\
Please generate related movies to {movie_name}. Output with the following JSON format: 
"""
json_prompt_str = output_parser.format(json_prompt_str)

# add JSON spec to prompt template
json_prompt_tmpl = PromptTemplate(json_prompt_str)

p = QueryPipeline(chain=[json_prompt_tmpl, llm, output_parser], verbose=True)
output = p.run(movie_name="Toy Story")

运行模块 2e4093c5-ae62-420a-be91-9c28c057bada 并输入:
电影名称:玩具总动员

运行模块 3b41f95c-f54b-41d7-8ef0-8e45b5d7eeb0 并输入:
消息:请生成与《玩具总动员》相关的电影。输出格式如下:

以下是需要遵循的 JSON 架构:

{“title”:“电影”,“description”:“代表电影列表的对象。”,“type…

运行模块 27e79a16-72de-4ce2-8b2e-94932c4069c3 并输入:
输入:助手:{
“电影”:[
{
“名称”:“海底总动员”,
“年份”:2003
},
{
“名称”:“怪物公司”,
“年份”:2001
},
{
“名称”:“汽车总动员”,
“年份”:2006

print(str(output))

Movies(movies=[Movie(name=‘海底总动员’, year=2003), Movie(name=‘怪物公司.’, year=2001), Movie(name=‘汽车总动员’, year=2006), Movie(name=‘超人特工队’, year=2004), Movie(name=‘料理鼠王’, year=2007)])

流媒体支持

查询管道具有 LLM 流支持(只需执行as_query_component(streaming=True))。中间输出将自动转换,最终输出可以是流输出。以下是一些示例。

1. 使用流式传输链接多个提示
prompt_str = "Please generate related movies to {movie_name}"
prompt_tmpl = PromptTemplate(prompt_str)
# let's add some subsequent prompts for fun
prompt_str2 = """\
Here's some text:

{text}

Can you rewrite this with a summary of each movie?
"""
prompt_tmpl2 = PromptTemplate(prompt_str2)
llm = OpenAI(model="gpt-3.5-turbo")
llm_c = llm.as_query_component(streaming=True)

p = QueryPipeline(
    chain=[prompt_tmpl, llm_c, prompt_tmpl2, llm_c], verbose=True
)
# p = QueryPipeline(chain=[prompt_tmpl, llm_c], verbose=True)

output = p.run(movie_name="The Dark Knight")
for o in output:
    print(o.delta, end="")

运行模块 213af6d4-3450-46af-9087-b80656ae6951 并输入:
电影名称:黑暗骑士

运行模块 3ff7e987-f5f3-4b36-a3e1-be5a4821d9d9 并输入:
消息:请生成与《黑暗骑士》相关的电影

运行模块 a2841bd3-c833-4427-9a7e-83b19872b064 并输入:
文本:<生成器对象 llm_chat_callback。<本地>.wrap。<本地>.wrapped_llm_chat。<本地>.wrapped_gen 位于 0x298d338b0>

运行模块 c7e0a454-213a-460e-b029-f2d42fd7d938 并输入:
消息:以下是一些文本:

1. 蝙蝠侠:侠影之谜(2005)
2.《蝙蝠侠:黑暗骑士崛起》(2012)
3. 蝙蝠侠大战超人:正义黎明(2016)
4. 超人:钢铁之躯(2013)
5. 复仇者联盟(2012)
6. 钢铁侠(2008)
7. 美国上尉……
  1. 蝙蝠侠:侠影之谜(2005):年轻的布鲁斯·韦恩成为蝙蝠侠,在哥谭市打击犯罪,面对自己的恐惧,在拉斯·艾尔·古尔的指导下接受训练。
  2. 黑暗骑士崛起(2012):蝙蝠侠回归,保护哥谭市免遭无情恐怖分子贝恩的袭击,贝恩计划摧毁这座城市及其希望的象征。
  3. 蝙蝠侠大战超人:正义黎明 (2016):蝙蝠侠和超人因意识形态冲突而发生冲突,引发了一场史诗般的战斗,同时出现了威胁人类的新威胁。
  4. 钢铁之躯(2013):超人的起源故事,他掌握了自己的超能力,并面对佐德将军,一个试图摧毁地球的氪星人。
  5. 复仇者联盟(2012):地球上最强大的英雄,包括钢铁侠、美国队长、雷神和绿巨人,联手阻止洛基和他的外星军队征服世界。
  6. 钢铁侠(2008):亿万富翁托尼·斯塔克打造了一套高科技战衣逃脱囚禁,成为超级英雄钢铁侠,利用他的科技对抗邪恶。
  7. 美国队长:冬日战士(2014):美国队长与黑寡妇和猎鹰联手,揭露神盾局内部的阴谋,同时面对被称为冬日战士的致命刺客。
  8. 超凡蜘蛛侠(2012):彼得·帕克,一名被放射性蜘蛛咬伤的高中生,成为蜘蛛侠并与威胁纽约市的恶魔蜥蜴展开战斗。
  9. 守望者(2009):故事背景设定在另一个现实世界,一群退休的治安维持会成员调查一名成员的谋杀案,发现了一个可能带来灾难性后果的阴谋。
  10. 罪恶之城(2005):一部新黑色电影选集,以犯罪猖獗的盆地城市为背景,讲述了各种人物经历腐败、暴力和救赎的故事。
  11. V 字仇杀队(2005):在一个反乌托邦的未来,一个名叫 V 的蒙面义警与极权政府作斗争,激励人民奋起反抗,夺回自由。
  12. 银翼杀手 2049(2017):一位年轻的银翼杀手发现了一个长期埋藏的秘密,这促使他去寻找前银翼杀手里克·德卡德,同时解开未来社会的谜团。
  13. 盗梦空间(2010):一个技术娴熟的窃贼进入人们的梦境窃取信息,但他却被要求植入一个想法,从而引发一场穿越多层现实的令人费解的旅程。
  14. 黑客帝国 (1999):一名电脑黑客发现了现实的真相,加入了一群反叛者,与在模拟世界中奴役人类的有意识的机器作战。
  15. 乌鸦(1994 年):一位音乐家被一只超自然的乌鸦复活,向杀害他和他未婚妻的团伙寻求报复,展开了一个黑暗而充满气氛的复仇故事。
2流输出提供给输出解析器
p = QueryPipeline(
    chain=[
        json_prompt_tmpl,
        llm.as_query_component(streaming=True),
        output_parser,
    ],
    verbose=True,
)
output = p.run(movie_name="Toy Story")
print(output)
        

运行模块 fe1dbf6a-56e0-44bf-97d7-a2a1fe9d9b8c 并输入:
电影名称:玩具总动员

运行模块 a8eaaf91-df9d-46c4-bbae-06c15cd15123 并输入:
消息:请生成与《玩具总动员》相关的电影。输出格式如下:

以下是需要遵循的 JSON 架构:

{“title”:“电影”,“description”:“代表电影列表的对象。”,“type…

运行模块 fcbc0b09-0ef5-43e0-b007-c4508fd6742f 并输入:
输入:<生成器对象 llm_chat_callback。<本地>.wrap。<本地>.wrapped_llm_chat。<本地>.wrapped_gen 位于 0x298d32dc0>

Movies(movies=[Movie(name=‘海底总动员’, year=2003), Movie(name=‘怪物公司.’, year=2001), Movie(name=‘汽车总动员’, year=2006), Movie(name=‘超人特工队’, year=2004), Movie(name=‘料理鼠王’, year=2007)])

将查询重写工作流程(提示 + LLM)与检索链接在一起

在这里,我们尝试一个稍微复杂的工作流程,在启动检索之前,我们通过两个提示发送输入。

  • 生成关于给定主题的问题。
  • 幻觉回答给定的问题,以便更好地检索。

由于每个提示仅接受一个输入,请注意会QueryPipeline自动将 LLM 输出链接到提示中,然后链接到 LLM

您将在下一节中看到如何更明确地定义链接。

pip install llama-index-postprocessor-cohere-rerank
from llama_index.postprocessor.cohere_rerank import CohereRerank

# generate question regarding topic
prompt_str1 = "Please generate a concise question about Paul Graham's life regarding the following topic {topic}"
prompt_tmpl1 = PromptTemplate(prompt_str1)
# use HyDE to hallucinate answer.
prompt_str2 = (
    "Please write a passage to answer the question\n"
    "Try to include as many key details as possible.\n"
    "\n"
    "\n"
    "{query_str}\n"
    "\n"
    "\n"
    'Passage:"""\n'
)
prompt_tmpl2 = PromptTemplate(prompt_str2)

llm = OpenAI(model="gpt-3.5-turbo")
retriever = index.as_retriever(similarity_top_k=5)
p = QueryPipeline(
    chain=[prompt_tmpl1, llm, prompt_tmpl2, llm, retriever], verbose=True
)

nodes = p.run(topic="college")
len(nodes)

运行模块 f5435516-61b6-49e9-9926-220cfb6443bd 并输入:
话题: 大学
运行模块 1dcaa097-cedc-4466-81bb-f8fd8768762b,输入:
信息:请针对以下主题提出一个关于 Paul Graham 生活的简明问题:大学
运行模块 891afa10-5fe0-47ed-bdee-42a59d0e916d 并输入:
query_str:助理:保罗·格雷厄姆的大学经历如何塑造他的职业生涯和创业思维?
运行模块 5bcd9964-b972-41a9-960d-96894c57a372 并输入:
留言:请写一篇文章来回答问题
尝试包含尽可能多的关键细节。
保罗·格雷厄姆的大学经历如何塑造他的职业生涯和创业思维?
通道:”””
运行模块 0b81a91a-2c90-4700-8ba1-25ffad5311fd 并输入:
输入:助理:保罗·格雷厄姆的大学经历在塑造他的职业生涯和创业思维方面发挥了关键作用。作为康奈尔大学的学生,格雷厄姆沉浸在计算机世界中……

创建完整的 RAG 管道作为 DAG

这里,我们将完整的RAG管道链接在一起,包括查询重写、检索、重新排序和响应合成。

这里我们不能使用chain 语法,因为某些模块依赖于多个输入(例如,响应合成需要检索到的节点和原始问题)。相反,我们将通过add_modulesadd_link显式地构造DAG。

1. 具有查询重写的 RAG 管道

我们首先使用 LLM 重写查询,然后将其传递给下游模块 - 检索/重新排序/合成。

from llama_index.postprocessor.cohere_rerank import CohereRerank
from llama_index.core.response_synthesizers import TreeSummarize


# define modules
prompt_str = "Please generate a question about Paul Graham's life regarding the following topic {topic}"
prompt_tmpl = PromptTemplate(prompt_str)
llm = OpenAI(model="gpt-3.5-turbo")
retriever = index.as_retriever(similarity_top_k=3)
reranker = CohereRerank()
summarizer = TreeSummarize(llm=llm)

# define query pipeline
p = QueryPipeline(verbose=True)
p.add_modules(
    {
        "llm": llm,
        "prompt_tmpl": prompt_tmpl,
        "retriever": retriever,
        "summarizer": summarizer,
        "reranker": reranker,
    }
)

接下来,我们用add_link绘制模块之间的链接。Add_link接受源/目标模块id,还可以选择source_keydest_key。如果分别有多个输出/输入,请指定source_keydest_key

您可以通过命令查看每个模块的输入/输出键集,module.as_query_component().input_keysmodule.as_query_component().output_keys.

这里我们显式地为rerankersummarizer 模块指定dest_key,因为它们接受两个输入(query_str 和 nodes)。

p.add_link("prompt_tmpl", "llm")
p.add_link("llm", "retriever")
p.add_link("retriever", "reranker", dest_key="nodes")
p.add_link("llm", "reranker", dest_key="query_str")
p.add_link("reranker", "summarizer", dest_key="nodes")
p.add_link("llm", "summarizer", dest_key="query_str")

# look at summarizer input keys
print(summarizer.as_query_component().input_keys)

required_keys = {‘query_str’,‘nodes’}optional_keys = set()
我们用它networkx来存储图形表示。这为我们提供了一种查看 DAG 的简单方法!

## create graph
from pyvis.network import Network

net = Network(notebook=True, cdn_resources="in_line", directed=True)
net.from_nx(p.dag)
net.show("rag_dag.html")

## another option using `pygraphviz`
# from networkx.drawing.nx_agraph import to_agraph
# from IPython.display import Image
# agraph = to_agraph(p.dag)
# agraph.layout(prog="dot")
# agraph.draw('rag_dag.png')
# display(Image('rag_dag.png'))

response = p.run(topic="YC")

运行模块 prompt_tmpl 并输入:
话题:YC

运行模块 llm 并输入:
消息:请针对以下主题生成有关 Paul Graham 生活的问题 YC

运行模块检索器并输入:
输入: 助理: Paul Graham 在 Y Combinator (YC)的创立和发展中扮演了什么角色?

运行模块重新排序器并输入:
query_str:助理:保罗·格雷厄姆在 Y Combinator(YC)的创立和发展中扮演了什么角色?
节点:[NodeWithScore(节点=TextNode(id_=‘ccd39041-5a64-4bd3-aca7-48f804b5a23f’,嵌入=无,元数据={‘file_path’:‘…/data/paul_graham/paul_graham_essay.txt’,‘file_name’:‘paul_graham_essay.txt’,'文件…

运行模块摘要器并输入:
query_str:助理:保罗·格雷厄姆在 Y Combinator(YC)的创立和发展中扮演了什么角色?
节点:[NodeWithScore(节点=TextNode(id_=‘120574dd-a5c9-4985-ab3e-37b1070b500a’,嵌入=无,元数据={‘file_path’:‘…/data/paul_graham/paul_graham_essay.txt’,‘file_name’:‘paul_graham_essay.txt’,'文件…

print(str(response))

Paul Graham 在 Y Combinator (YC) 的创立和发展中发挥了重要作用。他是 YC 的联合创始人之一,为这家投资公司提供了初始资金。他与合作伙伴一起实施了他们讨论的想法,并创办了自己的投资公司。Paul Graham 还在塑造 YC 独特的批量模式方面发挥了关键作用,该模式为一组初创公司提供资金,并在三个月内提供密集支持。他积极参与选择和帮助创始人,还撰写论文并参与 YC 的内部软件开发。

# you can do async too
response = await p.arun(topic="YC")
print(str(response))

并行运行模块和输入:
模块键:prompt_tmpl。输入:
话题:YC
并行运行模块和输入:
模块密钥:llm。输入:
消息:请针对以下主题生成有关 Paul Graham 生活的问题 YC
并行运行模块和输入:
模块键:检索器。输入:
输入: 助理: Paul Graham 在 Y Combinator (YC)的创立和发展中扮演了什么角色?
并行运行模块和输入:
模块键:reranker。输入:
query_str:助理:保罗·格雷厄姆在 Y Combinator(YC)的创立和发展中扮演了什么角色?
节点:[NodeWithScore(节点=TextNode(id_=‘ccd39041-5a64-4bd3-aca7-48f804b5a23f’,嵌入=无,元数据={‘file_path’:‘…/data/paul_graham/paul_graham_essay.txt’,‘file_name’:‘paul_graham_essay.txt’,‘文件…
并行运行模块和输入:
模块关键字:summarizer。输入:
query_str:助理:保罗·格雷厄姆在 Y Combinator(YC)的创立和发展中扮演了什么角色?
节点:[NodeWithScore(节点=TextNode(id_=‘120574dd-a5c9-4985-ab3e-37b1070b500a’,嵌入=无,元数据={‘file_path’:’…/data/paul_graham/paul_graham_essay.txt’,‘file_name’:‘paul_graham_essay.txt’,'文件…

Paul Graham 在 Y Combinator (YC) 的创立和发展中发挥了重要作用。他是 YC 的联合创始人之一,为这家投资公司提供了初始资金。他与合作伙伴一起实施了他们讨论的想法,并决定创办自己的投资公司。Paul Graham 还在塑造 YC 独特的批量模式方面发挥了关键作用,该模式为一组初创公司提供资金,并在三个月内提供密集支持。他积极参与选择和帮助创始人,并参与了与 YC 相关的各种项目,包括撰写论文和开发内部软件。

2. 无查询重写的 RAG 管道

这里我们设置了一个没有查询重写步骤的RAG管道。

这里我们需要一种将输入查询链接到检索器、重新排序器和摘要器的方法。我们可以通过定义一个特殊的InputComponent来实现这一点,它允许我们将输入链接到多个下游模块。

from llama_index.postprocessor.cohere_rerank import CohereRerank
from llama_index.core.response_synthesizers import TreeSummarize
from llama_index.core.query_pipeline import InputComponent

retriever = index.as_retriever(similarity_top_k=5)
summarizer = TreeSummarize(llm=OpenAI(model="gpt-3.5-turbo"))
reranker = CohereRerank()
p = QueryPipeline(verbose=True)
p.add_modules(
    {
        "input": InputComponent(),
        "retriever": retriever,
        "summarizer": summarizer,
    }
)
p.add_link("input", "retriever")
p.add_link("input", "summarizer", dest_key="query_str")
p.add_link("retriever", "summarizer", dest_key="nodes")
output = p.run(input="what did the author do in YC")

运行模块输入:
输入:作者在 YC 做什么
运行模块检索器并输入:
输入:作者在 YC 做什么
运行模块摘要器并输入:
query_str:作者在 YC 做什么
节点:[NodeWithScore(节点=TextNode(id_=‘86dea730-ca35-4bcb-9f9b-4c99e8eadd08’,嵌入=无,元数据={‘file_path’:‘…/data/paul_graham/paul_graham_essay.txt’,‘file_name’:‘paul_graham_essay.txt’,'文件…

print(str(output))

作者曾在 YC 参与过各种项目,包括撰写论文和开发 YC 的内部软件。他们还通过自掏腰包资助该项目,并组织了批量模式,每年两次资助一批初创企业,在 YC 的创建和运营中发挥了关键作用。他们在为期三个月的密集项目中为初创企业提供支持和指导,并将位于剑桥的大楼用作 YC 的总部。此外,他们每周都会举办晚宴,邀请初创企业专家进行演讲。

在查询管道中定义自定义组件

您可以轻松地定义自定义组件。只需创建QueryComponent的子类,实现验证/运行函数+一些帮助器,然后插入即可。

让我们将第一个示例中的相关电影生成提示符+LLM链包装到一个自定义组件中。

from llama_index.core.query_pipeline import (
    CustomQueryComponent,
    InputKeys,
    OutputKeys,
)
from typing import Dict, Any
from llama_index.core.llms.llm import LLM
from pydantic import Field


class RelatedMovieComponent(CustomQueryComponent):
    """Related movie component."""

    llm: LLM = Field(..., description="OpenAI LLM")

    def _validate_component_inputs(
        self, input: Dict[str, Any]
    ) -> Dict[str, Any]:
        """Validate component inputs during run_component."""
        # NOTE: this is OPTIONAL but we show you here how to do validation as an example
        return input

    @property
    def _input_keys(self) -> set:
        """Input keys dict."""
        # NOTE: These are required inputs. If you have optional inputs please override
        # `optional_input_keys_dict`
        return {"movie"}

    @property
    def _output_keys(self) -> set:
        return {"output"}

    def _run_component(self, **kwargs) -> Dict[str, Any]:
        """Run the component."""
        # use QueryPipeline itself here for convenience
        prompt_str = "Please generate related movies to {movie_name}"
        prompt_tmpl = PromptTemplate(prompt_str)
        p = QueryPipeline(chain=[prompt_tmpl, llm])
        return {"output": p.run(movie_name=kwargs["movie"])}

让我们尝试一下自定义组件!我们还将添加一个步骤,将输出转换为莎士比亚。

llm = OpenAI(model="gpt-3.5-turbo")
component = RelatedMovieComponent(llm=llm)

# let's add some subsequent prompts for fun
prompt_str = """\
Here's some text:

{text}

Can you rewrite this in the voice of Shakespeare?
"""
prompt_tmpl = PromptTemplate(prompt_str)

p = QueryPipeline(chain=[component, prompt_tmpl, llm], verbose=True)

output = p.run(movie="Love Actually")

运行模块 31ca224a-f226-4956-882b-73878843d869 并输入:
電影: 真爱至上
运行模块 febb41b5-2528-416a-bde7-6accdb0f9c51 并输入:
文字:助理:1.《情人节》(2010)
2.《除夕夜》(2011年)
3.《恋爱假期》(2006)
4.《疯狂愚蠢的爱》(2011)
5.《诺丁山》(1999)
6.《四个婚礼和一个葬礼》(1994年)
7.“布里奇特·J……
运行模块 e834ffbe-e97c-4ab0-9726-24f1534745b2 并输入:
消息:以下是一些文本:

1.《情人节》(2010)
2.《除夕夜》(2011年)
3.《恋爱假期》(2006)
4.《疯狂愚蠢的爱》(2011)
5.《诺丁山》(1999)
6.《四个婚礼和一个葬礼》(1994年)
7.“B…

print(str(output))
助手:1.“情人节”(2010)——“这是充满爱的一天,心与心交织在一起,
   丘比特之箭找到了神圣的目标。”

2.《除夕夜》(2011年)——“当旧年消逝,新年来临,
   我们聚集在一起,庆祝早晨。”

3.《恋爱假期》(2006)——“两个灵魂,在漂泊中寻找欢乐,
   在如此珍贵的假期中找到慰藉。”

4.《疯狂愚蠢的爱》(2011)——“一个狂野而疯狂的爱情故事,
   心迷失了,又找到了,并且感到快乐。”

5.《诺丁山》(1999)——“在伦敦小镇,爱情之花盛开,
   谦卑的人会找到爱情,并打破阴霾。”

6.《四个婚礼和一个葬礼》(1994年)——“四次誓言,一次哀悼,
   爱的旅途,有欢笑有泪水。”

7.《BJ单身日记》(2001)——“一位才华横溢、魅力十足的姑娘,
   记录她的生活,和爱情的警报。”

8.《时空恋旅人》(2013)——“一个关于时间的故事,爱情超越了时间,
   而珍贵的时刻永远不会真正结束。”

9.《涉外大饭店》(2011)——“在印度这片梦想绽放的土地上,
   酒店鲜花盛开,心灵找到金子。”

10.《恋恋笔记本》(2004)——“跨越时空的爱情,
    文字与记忆在此找到自己的位置。”

11. “缘分天注定”(2001) - “无论是偶然还是命运,两个灵魂相遇,
    为了寻找爱情,他们无法躲藏。”

12. “PS 我爱你”(2007) - “在爱的怀抱中写下的信中,
    逝去的灵魂,依然能找到踪迹。”

13.《和莎莫的500天》(2009)——“一个既甜蜜又酸涩的爱情故事,
    季节变换,心灵吞噬。”

14.《星运里的错》(2014)——“两颗心,在星空中燃烧,
    爱情的悲剧,希望永不消亡。”

15.《爱乐之城》(2016) - “在梦想和歌曲中,两颗心交织在一起,
    一座充满魔力的城市,爱情的星星在这里排列。”

管道的逐步执行

如果您符合以下条件,则一次执行一个管道是一个好主意:

  • 想要更好地调试执行顺序
  • 在每个步骤之间记录数据
  • 向用户反馈正在处理的内容
  • 以及更多!

要执行管道,您必须创建一个run_state,然后循环执行。下面是一个基本示例。

run_state = p.get_run_state(movie_name="The Departed")

next_module_keys = p.get_next_module_keys(run_state)

while True:
    for module_key in next_module_keys:
        # get the module and input
        module = run_state.module_dict[module_key]
        module_input = run_state.all_module_inputs[module_key]

        # run the module
        output_dict = module.run_component(**module_input)

        # process the output
        p.process_component_output(
            output_dict,
            module_key,
            run_state,
        )

    # get the next module keys
    next_module_keys = p.get_next_module_keys(
        run_state,
    )

    # if no more modules to run, break
    if not next_module_keys:
        run_state.result_outputs[module_key] = output_dict
        break

# the final result is at `module_key`
# it is a dict of 'output' -> ChatResponse object in this case
print(run_state.result_outputs[module_key]["output"].message.content)
1.《无间道》(2002)——《无间道风云》的灵感来源——香港原创电影
2. 城中大盗(2010)——本·阿弗莱克执导的犯罪惊悚片
3.《神秘河》(2003)——克林特·伊斯特伍德执导的犯罪剧
4.《好家伙》(1990)——马丁·斯科塞斯执导的经典黑帮电影
5. 爱尔兰人(2019)——马丁·斯科塞斯执导的另一部犯罪剧,由罗伯特·德尼罗和阿尔·帕西诺主演
6. 无间行者 (2006) - 无间行者是一部 2006 年的美国犯罪电影,由马丁·斯科塞斯执导,威廉·莫纳汉编剧。这是 2002 年香港电影《无间道》的翻拍版。该片由莱昂纳多·迪卡普里奥、马特·达蒙、杰克·尼科尔森和马克·沃尔伯格主演,马丁·辛、雷·温斯顿、维拉·法米加和亚历克·鲍德温担任配角。

http://www.kler.cn/news/355483.html

相关文章:

  • java-poi实现自定义注解excel生成合并单元格数据导出
  • VScode运行C语言终端输出中文乱码问题解决方案
  • qt+opengl 实现一个3D立体体
  • [LeetCode 题3] 没有重复字符的最长的子字符串
  • Excel制作工资表
  • Server-Sent Event(SSE) GPT场景实现
  • Python脚本实现发送QQ邮件
  • RabbitMQ 入门(八)SpringAMQP消息转换器
  • jmeter中对于有中文内容的csv文件怎么保存
  • C语言复习第4章 数组
  • webm格式怎么转换成mp4?几个操作简单的视频格式转换方法
  • 华为OD机试真题---勾股数元组
  • css 如何根据子元素给他的父元素设置样式
  • 【Vue】Vue3.0(十一)Vue 3.0 中 computed 计算属性概念、使用及示例
  • 还在滥用模糊查找?这类场景下 MySQL 多值索引性能更加强悍!
  • Leetcode|209.长度最小的子数组 And 59.螺旋矩阵||
  • 【C++】哈希表的封装——同时实现unordered_map和unordered_set
  • 【Vue】Vue3.0 (十二)、watchEffect 和watch的区别及使用
  • 【电商项目】1分布式基础篇
  • ASPICE在国内应用的挑战与改进空间