OpenAI¶
本笔记本演示如何使用 OpenAI 大型语言模型。
如需集成与官方 OpenAI API 不兼容的 OpenAI 兼容 API,请参阅 OpenAI-Compatible LLMs 集成文档。
如果您在 Colab 上打开此 Notebook,可能需要安装 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.
音频支持¶
OpenAI 目前提供音频输入与输出的测试版功能,该功能基于其音频预览模型实现。
使用这些模型时,可通过 modalities 参数配置输出形式(文本或音频)。输出音频的详细配置还可通过 audio_config 参数进行设置。更多信息请参阅 OpenAI 官方文档。
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 函数接入大语言模型。
在以下示例中,我们定义了一个用于生成 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)
现在,让我们调用大语言模型选择的工具(如果有的话)。
如果存在工具调用,我们应该将结果发送给大语言模型以生成最终响应(或发起另一次工具调用!)。
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 提供了一个直观的接口,可将任何大型语言模型转化为结构化语言模型——只需定义目标 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.
额外参数¶
无需为每次聊天或补全调用重复添加相同参数,您可以通过 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)
Node ID: 6341cc9c-1d81-46d6-afa3-9c2490f79514
Similarity: 0.99879813
Text: 2021 Compared to 2020
Revenue increased $6.3 billion, or 57%, primarily attributable to an increase in Gross Bookings of 56%, or 53% on a constant currency basis. The increase in Gross Bookings was primarily driven by an increase in Delivery Gross Bookings of 71%, or 66% on a constant currency basis, due to an increase in food delivery orders and higher basket sizes as a result of stay-at-home order demand related to COVID-19, as well as continued expansion across U.S. and international markets. The increase was also driven by Mobility Gross Bookings growth of 38%, or 36% on a constant currency basis, due to increases in Trip volumes as the business recovers from the impacts of COVID-19. Additionally, we saw an increase in Delivery revenue resulting from an increase in certain Courier payments and incentives that are recorded in cost of revenue, where we are primarily responsible for delivery services and pay Couriers for services provided.
Node ID: e022d492-0fe0-4988-979e-dc5de9eeaf2d
Similarity: 0.996597
Text: Highlights for 2021
Overall Gross Bookings increased by $32.5 billion in 2021, up 56%, or 53% on a constant currency basis, compared to 2020. Delivery Gross Bookings grew 66% from 2020, on a constant currency basis, due to an increase in food delivery orders and higher basket sizes as a result of stay-at-home order demand related to COVID-19, as well as continued expansion across U.S. and international markets. Additionally, we saw an increase in Delivery revenue resulting from an increase in certain Courier payments and incentives that are recorded in cost of revenue, where we are primarily responsible for delivery services and pay Couriers for services provided. Mobility Gross Bookings grew 36%, on a constant currency basis, from 2020, due to increases in Trip volumes as the business recovers from the impacts of COVID-19.
Revenue was $17.5 billion, or up 57% year-over-year, reflecting the overall growth in our Delivery business and an increase in Freight revenue attributable to ...
Node ID: 00d31b26-b734-4475-b47a-8cb839ff65e0
Similarity: 0.9962638
Text: 2021 Compared to 2020
Cost of revenue, exclusive of depreciation and amortization, increased $4.2 billion, or 81%, mainly due to a $2.1 billion increase in Courier payments and incentives in certain markets, a $660 million increase in insurance expense primarily due to an increase in miles driven in our Delivery business, and a $873 million increase in Freight carrier payments.
---
查询引擎¶
QueryEngine 用于配置完整的 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.