ここ 2 日間でよく目にしたニュースの 1 つは、OpenAI が API を更新したというものです。さまざまな価格の値下げとトークンの数の増加に加えて、関数呼び出しと呼ばれる新しい機能も導入されました。では、関数呼び出しとは一体何なのでしょうか? 多くのニュース タイプのコンテンツはあまり明確ではないかもしれないので、お話しさせてください。
実際、この機能は、以前に説明した ChatGPT プラグイン機能に似ています。まだご覧になっていない方のために、簡単に説明させていただきますと、ChatGPT プラグインはそのようなプロセスであり、サーバーからは説明ファイルが提供され、ChatGPT にインターフェイスの呼び出し方法とこれらのインターフェイスで何ができるかを指示します。次に、ユーザーが ChatGPT を使用しているときに、ユーザーが提起した問題の一部をプラグインの方がうまく解決できると ChatGPT が判断した場合、ChatGPT はプラグインのインターフェイスを直接呼び出します。
もちろん、私の説明がまだよく理解できない場合は、私の以前の記事「ChatGPT プラグインについて話して、それが表示されるかどうかを確認してください」を読んでください。
関数呼び出しにより、実際にはこのプロセスが API になります。このことは非常に高速に表示されました。実際、数日前に ChatGPT プラグインを使用したとき、私はこの問題についてのみ考えていました。プラグインの最も強力な部分は、アプリケーションの種類に関係なく、あらゆる種類のアプリケーションを使用できることです。 AI 機能を備えているかどうか プラグインを通じて大規模言語モデルの機能を独自の製品に適用します。
ただし、プラグインには制限もあります。つまり、ユーザーの使用シナリオが制限されており、ChatGPT インターフェイス内に存在する必要があります。当時私は、この機能を ChatGPT 自体のインターフェイスから分離できれば、より強力になるのではないかと考えていました。その結果、OpenAI は依然として非常に強力であり、私が考えた問題はすでに人々に理解されており、すぐに現実化されています。
https://platform.openai.com/docs/guides/gpt/function-calling
関数呼び出し:
const { google } = require('googleapis')
const chatUseOpenAi = async (req, res) => {
let {
model = 'gpt-3.5-turbo-16k-0613',
messages = [
{
role: 'user',
content: '你好',
},
],
apiKey = 'sk-xxx',
params = {},
} = req.body
if (apiKey === 'xxx') {
let baseURL = 'http://xxx'
const searchGoogleGptFunction = {
name: 'search_google_when_gpt_cannot_answer',
description:
'当 gpt 遇到无法回答的或者需要搜索引擎协助回答时从 google 搜索',
parameters: {
type: 'object',
properties: {
query: {
type: 'string',
description: '搜索句,支持中文或者英文',
},
},
},
}
let getCurrentWeather = {
name: 'get_current_weather',
description: 'Get the current weather in a given location',
parameters: {
type: 'object',
properties: {
location: {
type: 'string',
description: 'The city and state, e.g. San Francisco, CA',
},
unit: { type: 'string', enum: ['celsius', 'fahrenheit'] },
},
required: ['location'],
},
}
let isUseGoogleSearch = true
params = {
...params,
functions: [searchGoogleGptFunction],
function_call: isUseGoogleSearch ? 'auto' : 'none', //fun?.function_call, none
}
let result = await axios.post(`${baseURL}/api/light/chat/openAi`, {
model,
messages,
apiKey,
params,
})
const { errorData, completion } = result.data.data
let tempSearchResult = ''
if (
completion &&
Array.isArray(completion.choices) &&
completion.choices.length > 0
) {
if (
completion.choices[0].finish_reason === 'function_call' &&
completion.choices[0]?.message?.function_call?.name ===
'search_google_when_gpt_cannot_answer'
) {
try {
let arguments =
completion.choices[0]?.message?.function_call?.arguments
console.log('arguments', arguments)
arguments = arguments ? JSON.parse(arguments) : {}
let baseURL = 'http://xxx'
let pageNum = 1
searchCount = searchCount + 1
let message = arguments.query
console.log('google搜索次数', searchCount)
console.log('google搜索关键词', message, Date())
let timer = setTimeout(() => {
customSendEmail({
subject: 'google搜索超时',
html: `google搜索超时,${message},${pageNum}`,
})
}, 1000 * 60)
try {
let result = await axios.post(
`${baseURL}/api/light/chat/googleSearchOnAzure`,
{
message,
pageNum: 1,
apiKey: 'xxx',
}
)
clearTimeout(timer)
const { searchResult } = result.data.data
delete searchResult.queries
tempSearchResult = searchResult
if (searchResult && Array.isArray(searchResult.items)) {
let googleResultList = searchResult.items.map((item) => {
return {
title: item.title,
snippet: item.snippet,
}
})
const googleResultForGPT = `这是我的提问:${message}\n这是我在google搜索“${message}”的结果:\n${JSON.stringify(
googleResultList
)}\n请结合搜索结果回答`
let messagesTemp = [
...messages,
{
role: 'function',
name: completion.choices[0]?.message?.function_call?.name,
content: googleResultForGPT,
},
]
let resultForGPT = await axios.post(
`${baseURL}/api/light/chat/openAi`,
{
model,
messages: messagesTemp,
apiKey,
params,
}
)
const { errorData, completion: completionForGTP } =
resultForGPT.data.data
res.send({
code: 200,
data: {
errorData,
completionForGTP,
params,
tempSearchResult,
},
message: '成功',
})
return
}
} catch (err) {
console.log('错误1', err.stack)
customSendEmail({
subject: 'google搜索失败',
html: `chatgpt自动调用<br/>${err.stack}`,
})
}
} catch (error) {
console.log('arguments, 解析错误')
customSendEmail({
subject: 'arguments, 解析错误',
html: `arguments, 解析错误<br/>${err.stack}`,
})
}
}
}
res.send({
code: 200,
data: {
errorData,
completion,
params,
tempSearchResult,
},
message: '成功',
})
} else {
res.send({
code: 400,
message: '失败:参数apiKey',
})
}
}
Google検索:
const chatGoogleSearchOnAzure = async (req, res) => {
let { message = '', pageNum = 1, apiKey = 'sk-xxx' } = req.body
if (apiKey === 'xxx') {
let start = (pageNum - 1) * 10
const customSearch = google.customsearch('v1')
const customSearchRes = await customSearch.cse.list({
cx: 'xxx',
key: 'xxx,
q: message,
start,
num: 10,
hl: 'zh-CN',
safe: 'off',
imgColorType: 'color',
})
const searchResult = customSearchRes.data
res.send({
code: 200,
data: {
searchResult: searchResult,
},
message: '成功',
})
} else {
res.send({
code: 400,
message: '失败:参数apiKey',
})
}
}
参考リンク:
https://juejin.cn/post/7249909247039143997