如果您在 colab 上打开此笔记本,您可能需要安装 LlamaIndex 🦙。
%pip install llama-index llama-index-llms-openai
基本用法¶
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
from llama_index.llms.openai import OpenAI
llm = OpenAI(
model="gpt-4o-mini",
# api_key="some key", # uses OPENAI_API_KEY env var by default
)
使用提示调用 complete
¶
from llama_index.llms.openai import OpenAI
resp = llm.complete("Paul Graham is ")
print(resp)
a computer scientist, entrepreneur, and venture capitalist. He is best known for co-founding the startup accelerator Y Combinator and for his work on Lisp, a programming language. Graham has also written several influential essays on startups, technology, and entrepreneurship.
使用消息列表调用 chat
¶
from llama_index.core.llms import ChatMessage
messages = [
ChatMessage(
role="system", content="You are a pirate with a colorful personality"
),
ChatMessage(role="user", content="What is your name"),
]
resp = llm.chat(messages)
print(resp)
assistant: Ahoy matey! The name's Rainbow Roger, the most colorful pirate on the seven seas! What can I do for ye today?
流式传输¶
使用 stream_complete
端点
resp = llm.stream_complete("Paul Graham is ")
for r in resp:
print(r.delta, end="")
a computer scientist, entrepreneur, and venture capitalist. He is best known for co-founding the startup accelerator Y Combinator and for his work on programming languages and web development. Graham is also a prolific writer and has published several influential essays on technology, startups, and entrepreneurship.
使用 stream_chat
端点
from llama_index.core.llms import ChatMessage
messages = [
ChatMessage(
role="system", content="You are a pirate with a colorful personality"
),
ChatMessage(role="user", content="What is your name"),
]
resp = llm.stream_chat(messages)
for r in resp:
print(r.delta, end="")
Ahoy matey! The name's Captain Rainbowbeard! Aye, I be a pirate with a love for all things colorful and bright. Me beard be as vibrant as a rainbow, and me ship be the most colorful vessel on the seven seas! What can I do for ye today, me hearty?
配置模型¶
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o")
resp = llm.complete("Paul Graham is ")
print(resp)
a computer scientist, entrepreneur, and venture capitalist. He is best known for co-founding the startup accelerator Y Combinator and for his work on Lisp, a programming language. Graham has also written several influential essays on startups, technology, and entrepreneurship.
messages = [
ChatMessage(
role="system", content="You are a pirate with a colorful personality"
),
ChatMessage(role="user", content="What is your name"),
]
resp = llm.chat(messages)
print(resp)
assistant: Ahoy matey! The name's Captain Rainbowbeard, the most colorful pirate on the seven seas! What can I do for ye today? Arrr!
!wget https://cdn.pixabay.com/photo/2016/07/07/16/46/dice-1502706_640.jpg -O image.png
from llama_index.core.llms import ChatMessage, TextBlock, ImageBlock
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o")
messages = [
ChatMessage(
role="user",
blocks=[
ImageBlock(path="image.png"),
TextBlock(text="Describe the image in a few sentences."),
],
)
]
resp = llm.chat(messages)
print(resp.message.content)
The image is a black and white photograph featuring three dice in mid-air above a checkered surface, likely a chessboard. The dice are captured in motion, with one showing the number five prominently. The background is dark, with a subtle light beam creating a triangular shape above the dice, adding a dramatic effect to the composition.
from llama_index.core.llms import ChatMessage
from llama_index.llms.openai import OpenAI
llm = OpenAI(
model="gpt-4o-audio-preview",
modalities=["text", "audio"],
audio_config={"voice": "alloy", "format": "wav"},
)
messages = [
ChatMessage(role="user", content="Hello! My name is Logan."),
]
resp = llm.chat(messages)
import base64
from IPython.display import Audio
Audio(base64.b64decode(resp.message.blocks[0].audio), rate=16000)
# Add the response to the chat history and ask for the user's name
messages.append(resp.message)
messages.append(ChatMessage(role="user", content="What is my name?"))
resp = llm.chat(messages)
Audio(base64.b64decode(resp.message.blocks[0].audio), rate=16000)
我们还可以使用音频作为输入,并获取音频的描述或转录文本。
!wget AUDIO_URL = "https://science.nasa.gov/wp-content/uploads/2024/04/sounds-of-mars-one-small-step-earth.wav" -O audio.wav
from llama_index.core.llms import ChatMessage, AudioBlock, TextBlock
messages = [
ChatMessage(
role="user",
blocks=[
AudioBlock(path="audio.wav", format="wav"),
TextBlock(
text="Describe the audio in a few sentences. What is it from?"
),
],
)
]
llm = OpenAI(
model="gpt-4o-audio-preview",
modalities=["text"],
)
resp = llm.chat(messages)
print(resp)
assistant: The audio is a famous quote from astronaut Neil Armstrong during the Apollo 11 moon landing in 1969. As he became the first human to step onto the moon's surface, he said, "That's one small step for man, one giant leap for mankind." This moment marked a significant achievement in space exploration and human history.
使用函数/工具调用¶
OpenAI 模型原生支持函数调用。这与 LlamaIndex 的工具抽象方便地集成,让您可以将任何任意 Python 函数插入到 LLM 中。
在下面的示例中,我们定义一个函数来生成一个 Song 对象。
from pydantic import BaseModel
from llama_index.core.tools import FunctionTool
class Song(BaseModel):
"""A song with name and artist"""
name: str
artist: str
def generate_song(name: str, artist: str) -> Song:
"""Generates a song with provided name and artist."""
return Song(name=name, artist=artist)
tool = FunctionTool.from_defaults(fn=generate_song)
strict
参数告诉 OpenAI 是否在生成工具调用/结构化输出时使用约束采样。这意味着生成的工具调用模式将始终包含预期的字段。
由于这似乎会增加延迟,因此默认设置为 false。
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-4o-mini", strict=True)
response = llm.predict_and_call(
[tool],
"Pick a random song for me",
# strict=True # can also be set at the function level to override the class
)
print(str(response))
name='Random Vibes' artist='DJ Chill'
我们还可以进行多个函数调用。
llm = OpenAI(model="gpt-3.5-turbo")
response = llm.predict_and_call(
[tool],
"Generate five songs from the Beatles",
allow_parallel_tool_calls=True,
)
for s in response.sources:
print(f"Name: {s.tool_name}, Input: {s.raw_input}, Output: {str(s)}")
Name: generate_song, Input: {'args': (), 'kwargs': {'name': 'Hey Jude', 'artist': 'The Beatles'}}, Output: name='Hey Jude' artist='The Beatles' Name: generate_song, Input: {'args': (), 'kwargs': {'name': 'Let It Be', 'artist': 'The Beatles'}}, Output: name='Let It Be' artist='The Beatles' Name: generate_song, Input: {'args': (), 'kwargs': {'name': 'Yesterday', 'artist': 'The Beatles'}}, Output: name='Yesterday' artist='The Beatles' Name: generate_song, Input: {'args': (), 'kwargs': {'name': 'Come Together', 'artist': 'The Beatles'}}, Output: name='Come Together' artist='The Beatles' Name: generate_song, Input: {'args': (), 'kwargs': {'name': 'Help!', 'artist': 'The Beatles'}}, Output: name='Help!' artist='The Beatles'
手动工具调用¶
如果您想控制工具的调用方式,也可以将工具调用和工具选择拆分成单独的步骤。
首先,让我们选择一个工具。
from llama_index.core.llms import ChatMessage
chat_history = [ChatMessage(role="user", content="Pick a random song for me")]
resp = llm.chat_with_tools([tool], chat_history=chat_history)
现在,让我们调用 LLM 选择的工具(如果选择了)。
如果发生了工具调用,我们应该将结果发送给 LLM 以生成最终响应(或另一个工具调用!)。
tools_by_name = {t.metadata.name: t for t in [tool]}
tool_calls = llm.get_tool_calls_from_response(
resp, error_on_no_tool_call=False
)
while tool_calls:
# add the LLM's response to the chat history
chat_history.append(resp.message)
for tool_call in tool_calls:
tool_name = tool_call.tool_name
tool_kwargs = tool_call.tool_kwargs
print(f"Calling {tool_name} with {tool_kwargs}")
tool_output = tool(**tool_kwargs)
chat_history.append(
ChatMessage(
role="tool",
content=str(tool_output),
# most LLMs like OpenAI need to know the tool call id
additional_kwargs={"tool_call_id": tool_call.tool_id},
)
)
resp = llm.chat_with_tools([tool], chat_history=chat_history)
tool_calls = llm.get_tool_calls_from_response(
resp, error_on_no_tool_call=False
)
Calling generate_song with {'name': 'Random Vibes', 'artist': 'DJ Chill'}
现在,我们应该有一个最终响应了!
print(resp.message.content)
Here's a random song for you: **"Random Vibes"** by **DJ Chill**. Enjoy!
结构化预测¶
函数调用的一个重要用例是提取结构化对象。LlamaIndex 提供了一个直观的界面,可以将任何 LLM 转换为结构化 LLM - 只需定义目标 Pydantic 类(可以是嵌套的),然后给定一个提示,我们就能提取出所需的对象。
from llama_index.llms.openai import OpenAI
from llama_index.core.prompts import PromptTemplate
from pydantic import BaseModel
from typing import List
class MenuItem(BaseModel):
"""A menu item in a restaurant."""
course_name: str
is_vegetarian: bool
class Restaurant(BaseModel):
"""A restaurant with name, city, and cuisine."""
name: str
city: str
cuisine: str
menu_items: List[MenuItem]
llm = OpenAI(model="gpt-3.5-turbo")
prompt_tmpl = PromptTemplate(
"Generate a restaurant in a given city {city_name}"
)
# Option 1: Use `as_structured_llm`
restaurant_obj = (
llm.as_structured_llm(Restaurant)
.complete(prompt_tmpl.format(city_name="Dallas"))
.raw
)
# Option 2: Use `structured_predict`
# restaurant_obj = llm.structured_predict(Restaurant, prompt_tmpl, city_name="Miami")
restaurant_obj
Restaurant(name='Tasty Bites', city='Dallas', cuisine='Italian', menu_items=[MenuItem(course_name='Appetizer', is_vegetarian=True), MenuItem(course_name='Main Course', is_vegetarian=False), MenuItem(course_name='Dessert', is_vegetarian=True)])
带有流式传输的结构化预测¶
任何通过 as_structured_llm
包装的 LLM 都支持通过 stream_chat
进行流式传输。
from llama_index.core.llms import ChatMessage
from IPython.display import clear_output
from pprint import pprint
input_msg = ChatMessage.from_str("Generate a restaurant in Boston")
sllm = llm.as_structured_llm(Restaurant)
stream_output = sllm.stream_chat([input_msg])
for partial_output in stream_output:
clear_output(wait=True)
pprint(partial_output.raw.dict())
restaurant_obj = partial_output.raw
restaurant_obj
{'city': 'Boston', 'cuisine': 'American', 'menu_items': [{'course_name': 'Appetizer', 'is_vegetarian': True}, {'course_name': 'Main Course', 'is_vegetarian': False}, {'course_name': 'Dessert', 'is_vegetarian': True}], 'name': 'Boston Bites'}
Restaurant(name='Boston Bites', city='Boston', cuisine='American', menu_items=[MenuItem(course_name='Appetizer', is_vegetarian=True), MenuItem(course_name='Main Course', is_vegetarian=False), MenuItem(course_name='Dessert', is_vegetarian=True)])
异步¶
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo")
resp = await llm.acomplete("Paul Graham is ")
print(resp)
a computer scientist, entrepreneur, and venture capitalist. He is best known for co-founding the startup accelerator Y Combinator and for his work as an essayist and author on topics related to technology, startups, and entrepreneurship. Graham is also the co-founder of Viaweb, one of the first web-based applications, which was acquired by Yahoo in 1998. He has been a prominent figure in the tech industry for many years and is known for his insightful and thought-provoking writings on a wide range of subjects.
resp = await llm.astream_complete("Paul Graham is ")
async for delta in resp:
print(delta.delta, end="")
Paul Graham is an entrepreneur, venture capitalist, and computer scientist. He is best known for his work in the startup world, having co-founded the accelerator Y Combinator and investing in many successful startups such as Airbnb, Dropbox, and Stripe. He is also a prolific writer, having authored several books on topics such as startups, programming, and technology.
也支持异步函数调用。
llm = OpenAI(model="gpt-3.5-turbo")
response = await llm.apredict_and_call([tool], "Generate a song")
print(str(response))
name='Sunshine' artist='John Smith'
按实例级别设置 API 密钥¶
如果需要,您可以为不同的 LLM 实例使用不同的 API 密钥。
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo", api_key="BAD_KEY")
resp = llm.complete("Paul Graham is ")
print(resp)
a computer scientist, entrepreneur, and venture capitalist. He is best known as the co-founder of the startup accelerator Y Combinator. Graham has also written several influential essays on startups and entrepreneurship, which have gained a wide following in the tech industry. He has been involved in the founding and funding of numerous successful startups, including Reddit, Dropbox, and Airbnb. Graham is known for his insightful and often controversial opinions on various topics, including education, inequality, and the future of technology.
附加 kwargs¶
除了在每次聊天或完成调用中添加相同的参数外,您还可以使用 additional_kwargs
在每个实例级别设置它们。
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo", additional_kwargs={"user": "your_user_id"})
resp = llm.complete("Paul Graham is ")
print(resp)
from llama_index.llms.openai import OpenAI
llm = OpenAI(model="gpt-3.5-turbo", additional_kwargs={"user": "your_user_id"})
messages = [
ChatMessage(
role="system", content="You are a pirate with a colorful personality"
),
ChatMessage(role="user", content="What is your name"),
]
resp = llm.chat(messages)
安装¶
%pip install llama-cloud
%pip install llama-index-indices-managed-llama-cloud
设置 OpenAI 和 LlamaCloud API 密钥¶
import os
os.environ["OPENAI_API_KEY"] = "sk-..."
os.environ["LLAMA_CLOUD_API_KEY"] = "llx-..."
from llama_cloud.client import LlamaCloud
client = LlamaCloud(token=os.environ["LLAMA_CLOUD_API_KEY"])
# Embedding config
embedding_config = {
"type": "OPENAI_EMBEDDING",
"component": {
"api_key": os.environ["OPENAI_API_KEY"],
"model_name": "text-embedding-ada-002", # You can choose any OpenAI Embedding model
},
}
# Transformation auto config
transform_config = {
"mode": "auto",
"config": {
"chunk_size": 1024, # editable
"chunk_overlap": 20, # editable
},
}
pipeline = {
"name": "openai-rag-pipeline", # Change the name if needed
"embedding_config": embedding_config,
"transform_config": transform_config,
"data_sink_id": None,
}
pipeline = client.pipelines.upsert_pipeline(request=pipeline)
文件上传¶
我们将上传文件并将其添加到索引中。
with open("../data/10k/uber_2021.pdf", "rb") as f:
file = client.files.upload_file(upload_file=f)
files = [{"file_id": file.id}]
pipeline_files = client.pipelines.add_files_to_pipeline(
pipeline.id, request=files
)
检查摄取作业状态¶
jobs = client.pipelines.list_pipeline_jobs(pipeline.id)
jobs[0].status
<ManagedIngestionStatus.SUCCESS: 'SUCCESS'>
from llama_index.indices.managed.llama_cloud import LlamaCloudIndex
index = LlamaCloudIndex(
name="openai-rag-pipeline",
project_name="Default",
organization_id="YOUR ORG ID",
api_key=os.environ["LLAMA_CLOUD_API_KEY"],
)
在示例查询上进行测试¶
query = "What is the revenue of Uber in 2021?"
检索器¶
这里我们使用混合搜索和重排序器(默认为 cohere 重排序器)。
retriever = index.as_retriever(
dense_similarity_top_k=3,
sparse_similarity_top_k=3,
alpha=0.5,
enable_reranking=True,
)
retrieved_nodes = retriever.retrieve(query)
显示检索到的节点¶
from llama_index.core.response.notebook_utils import display_source_node
for retrieved_node in retrieved_nodes:
display_source_node(retrieved_node, source_length=1000)
节点 ID: 6341cc9c-1d81-46d6-afa3-9c2490f79514
相似度 0.99879813
文本: 2021 年与 2020 年对比
收入增加了 63 亿美元,增长 57%,这主要归因于总预订量增长了 56%,按固定汇率计算增长了 53%。总预订量的增长主要得益于外卖总预订量增长 71%,按固定汇率计算增长 66%,这归因于受 COVID-19 相关居家令需求的影响,外卖订单量和客单价均有所增加,以及在美国和国际市场持续扩张。此外,出行总预订量增长 38%,按固定汇率计算增长 36%,这归因于随着业务从 COVID-19 的影响中恢复,出行次数增加。此外,我们还看到外卖收入增加,这归因于某些录入营收成本的骑手付款和激励措施增加,我们在这些业务中主要负责配送服务并向骑手支付服务费用。
节点 ID: e022d492-0fe0-4988-979e-dc5de9eeaf2d
相似度 0.996597
文本: 2021 年亮点
2021 年总预订量总体增长 325 亿美元,较 2020 年增长 56%,按固定汇率计算增长 53%。外卖总预订量较 2020 年增长 66%(按固定汇率计算),这归因于受 COVID-19 相关居家令需求的影响,外卖订单量和客单价均有所增加,以及在美国和国际市场持续扩张。此外,我们还看到外卖收入增加,这归因于某些录入营收成本的骑手付款和激励措施增加,我们在这些业务中主要负责配送服务并向骑手支付服务费用。出行总预订量较 2020 年增长 36%(按固定汇率计算),这归因于随着业务从 COVID-19 的影响中恢复,出行次数增加。
收入为 175 亿美元,同比增长 57%,反映了我们外卖业务的整体增长和货运收入的增加,这归因于 ...
节点 ID: 00d31b26-b734-4475-b47a-8cb839ff65e0
相似度 0.9962638
文本: 2021 年与 2020 年对比
营收成本(不含折旧和摊销)增加 42 亿美元,增长 81%,主要归因于某些市场骑手付款和激励措施增加 21 亿美元,保险费用增加 6.6 亿美元(主要由于我们外卖业务的行驶里程增加),以及货运承运商付款增加 8.73 亿美元。---
查询引擎¶
查询引擎用于设置完整的 RAG 工作流程。
query_engine = index.as_query_engine(
dense_similarity_top_k=3,
sparse_similarity_top_k=3,
alpha=0.5,
enable_reranking=True,
)
响应¶
response = query_engine.query(query)
print(response)
The revenue of Uber in 2021 was $17.5 billion.