从用户输入中提取见解的能力一直是OpenAI API的绝佳用例。我已经看到很多人使用GPT API执行NLP任务。从意图检测到分类到NER(命名实体识别),这非常有用,尤其是对于没有广泛ML背景的开发人员。
和这种“函数调用”的新功能将此用例带到一个全新的级别。在本文中,我们将探讨如何使用此功能在几行Python中获取有关股票的真实数据。
了解核心问题
获取库存数据并不困难,这只是简单的API调用问题。
这是棘手的部分:
-
确定用户想做什么
-
将用户目的映射到解决方案功能
-
提取我们功能期望的数据
-
将提示链接在一起响应
在函数调用功能的可用性之前,我们不得不兼顾所有导致复杂流程的事情。确保像langchain
这样的框架可以帮助我们简化这种杂耍。但是模型本身为我们做这件事的能力是非常了不起的。
我将以一个简单的示例进行演示:
回答用户关于股票价格和其他信息的问题
获取您的API键
要获取股票价格数据,我们将使用Polygon,
您可以在此处注册,然后访问您的API键:https://polygon.io/dashboard/api-keys
Polygon有一个Python客户端,但要保持其更抽象,我们将使用其REST API
如果您还没有OpenAi API键,请从这里获取它们:https://platform.openai.com/account/api-keys
让我们参与代码
首先,让我们安装openai
和reuests
!pip install openai
!pip install requests
现在,让我们设置一些全局变量和API键(OpenAI&Polygon)
import openai
global OPENAI_API_KEY
global POLYGON_API_KEY
OPENAI_API_KEY="Your OpenAI API Key goes here"
POLYGON_API_KEY="Your Polygon API Key goes here"
openai.api_key = OPENAI_API_KEY
导入,一些全局变量和设置代码
import datetime
import requests
import json
global today_str
today = datetime.date.today()
today_str = today.strftime('%Y-%m-%d')
获取库存数据的功能
让我们编写一个可以用来从Polygon API获取股票价格数据的函数
def get_stock_price_by_date(ticker_symbol, date):
url = f"https://api.polygon.io/v1/open-close/{ticker_symbol}/{date}?adjusted=true&apiKey={POLYGON_API_KEY}"
try:
response = requests.request(method='GET', url=url)
response.raise_for_status()
# print(response.text)
return json.dumps(response.text)
except Exception as e:
print(f"An error occurred: {e}")
return None
您可以尝试使用手动参数输入调用此函数,以确保其按预期工作
print(get_stock_price_by_date(ticker_symbol="GOOGL", date="2023-06-16"))
{
"status": "OK",
"from": "2023-06-15",
"symbol": "GOOGL",
"open": 123.14,
"high": 125.46,
"low": 122.4,
"close": 125.09,
"volume": 3.5146268e+07,
"afterHours": 124.85,
"preMarket": 123.48
}
让我们编写另一个功能,该功能根据SEC归档获取有关股票的数据
def get_stock_sec_details(ticker_symbol, date = today_str):
url = f"https://api.polygon.io/v3/reference/tickers/{ticker_symbol}?date={date}&apiKey={POLYGON_API_KEY}"
try:
response = requests.request(method='GET', url=url)
response.raise_for_status()
# print(response.text)
return json.dumps(response.text)
except Exception as e:
print(f"An error occurred: {e}")
return None
我们可以尝试调用此功能以检查其响应方式
print(get_stock_sec_details(ticker_symbol="AAPL"))
{
"request_id": "f7d8eb4aac2a75fbb4b8df1f25ab4ead",
"results": {
"ticker": "AAPL",
"name": "Apple Inc.",
"market": "stocks",
"locale": "us",
"primary_exchange": "XNAS",
"type": "CS",
"active": true,
"currency_name": "usd",
"cik": "0000320193",
"composite_figi": "BBG000B9XRY4",
"share_class_figi": "BBG001S5N8V8",
"market_cap": 2.92569585902e+12,
"phone_number": "(408) 996-1010",
"address": {
"address1": "ONE APPLE PARK WAY",
"city": "CUPERTINO",
"state": "CA",
"postal_code": "95014"
},
"description": "Apple designs a wide variety of consumer electronic devices, including smartphones (iPhone), tablets (iPad), PCs (Mac), smartwatches (Apple Watch), and AirPods, among others. In addition, Apple offers its customers a variety of services such as Apple Music, iCloud, Apple Care, Apple TV+, Apple Arcade, Apple Fitness, Apple Card, and Apple Pay, among others. Apple's products include internally developed software and semiconductors, and the firm is well known for its integration of hardware, software, semiconductors, and services. Apple's products are distributed online as well as through company-owned stores and third-party retailers.",
"sic_code": "3571",
"sic_description": "ELECTRONIC COMPUTERS",
"ticker_root": "AAPL",
"homepage_url": "https://www.apple.com",
"total_employees": 164000,
"list_date": "1980-12-12",
"branding": {
"logo_url": "https://api.polygon.io/v1/reference/company-branding/d3d3LmFwcGxlLmNvbQ/images/2023-05-01_logo.svg",
"icon_url": "https://api.polygon.io/v1/reference/company-branding/d3d3LmFwcGxlLmNvbQ/images/2023-05-01_icon.jpeg"
},
"share_class_shares_outstanding": 15728700000,
"weighted_shares_outstanding": 15728702000,
"round_lot": 100
},
"status": "OK"
}
利用函数调用
现在是我们将功能描述为OpenAi API
的部分
def run_conversation(message):
response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[{"role": "user", "content": f"Date today is {today_str}. Provide answer with a date. {message}"}],
functions=[
{
"name": "get_stock_price_by_date",
"description": "Get stock prices by date",
"parameters": {
"type": "object",
"properties": {
"ticker_symbol": {
"type": "string",
"description": "The ticker symbol for the stock listed on NASDAQ exchange",
},
"date": {
"type": "string",
"description": "date string in %Y-%m-%d format"
}
},
"required": ["stock_ticker", "date"],
},
},
{
"name": "get_stock_sec_details",
"description": "Get SEC filing details by stock ticker symbol",
"parameters": {
"type": "object",
"properties": {
"ticker_symbol": {
"type": "string",
"description": "The ticker symbol for the stock listed on NASDAQ exchange",
},
"date": {
"type": "string",
"description": "date string in %Y-%m-%d format"
}
},
"required": ["stock_ticker"],
},
}
],
function_call="auto",
)
标准聊天呼叫与此一个。
之间有2个区别。-
模型:要使用函数调用功能,我们必须使用最新的型号
gpt-3.5-turbo-0613
或gpt-4-0613
(GPT 4) -
描述功能的其他参数:
functions
&function_call
-
functions
期望函数描述的数组,您可以为此数组提供更多功能,并且该模型将尝试检测哪个功能最适合给定的用户输入 -
function_call
指示是生成模型的模型(auto
响应(none
响应,将在后续呼叫中以型号馈送到模型)还是将用户的面向用户响应呈现给用户
现在,根据模型的响应,我们将调用实际功能,在这里您可以检查哪个功能最适合模型
这是我们可以做到的
## Continuing the `run_conversation` function
internal_message = response["choices"][0]["message"]
if internal_message.get("function_call"):
function_name = internal_message["function_call"]["name"]
function_args = json.loads(internal_message["function_call"]["arguments"])
function_response = ""
# Printing which function is detected
print(function_name)
# If model detected stock price info is required
if function_name == "get_stock_price_by_date":
function_response = get_stock_price_by_date(
ticker_symbol=function_args.get("ticker_symbol"),
date=function_args.get("date"),
)
# If model detected stock SEC filing info is required
if function_name == "get_stock_sec_details":
function_response = get_stock_sec_details(
ticker_symbol=function_args.get("ticker_symbol")
)
second_response = openai.ChatCompletion.create(
model="gpt-3.5-turbo-0613",
messages=[
{"role": "user", "content": message},
internal_message,
{
"role": "function",
"name": function_name,
"content": function_response,
},
],
)
return second_response
这里要注意的一件事是,将计算函数描述(functions
数组中的对象)与输入令牌
好吧,让我们测试
print(run_conversation("tell me apple volume 3 days ago")["choices"][0]["message"]["content"])
get_stock_price_by_date
三天前,2023年6月13日的Apple(AAPL)的数量约为54,867,129股。
print(run_conversation("how many outstanding google shares are there")["choices"][0]["message"]["content"])
get_stock_sec_details
截至目前,大约有5,874,000,000份流通的Google股票。
可以得出结论,使用函数调用功能 -
-
该模型可以检测应调用哪个函数以满足用户的请求
-
它可以从用户的输入中提取所需的信息,并为我们提供函数参数
您可以在-https://github.com/anantrp/ai-experiments/blob/main/openai_function_calling_stock_prices_demo.ipynb
中找到本文的完整源代码您可以在-https://platform.openai.com/docs/guides/gpt/function-calling
上阅读有关函数的更多信息这可以超越简单的检索功能,我们可以构建执行器功能(可以执行操作的功能),例如发送电子邮件,订购产品,对我们的自定义软件系统采取行动以及更多
具有函数呼叫功能,我们有很大的潜力来构建明天的AI代理
我希望您能发现这很有价值 - 如果您这样做 - 真是太棒了ð与您的人们分享它也会有用的人。如果您有任何建议/评论,请自由。
快乐编码!