赞
踩
这两天看的比较多的一个新闻就是 OpenAI 又更新了自己的 API。 除了各种大减价,增加 Token 数量之外,还新推出了一个叫做 Function calling 的能力。那么 Function calling 到底是什么东西,可能很多新闻类型的内容也没讲太明白,我和大家聊一下。
其实这个能力和我之前跟大家聊的 ChatGPT 插件功能有些类似。 如果没看过的朋友,我也简单和大家描述一下, ChatGPT 插件是这样一个流程,你的服务端给它提供一个描述文件,就是告诉 ChatGPT 怎么调用你的接口,以及这些接口都能做什么。 那么当用户在使用 ChatGPT 的时候,如果 ChatGPT 认为用户提的某些问题,你的插件能够更好的解决,那么 ChatGPT 就会直接去调用你插件的接口。
当然,如果我这个描述你还是不能很好的理解,可以看看我之前的文章:说说 ChatGPT Plugin, 看看你能否先知先觉
Function calling 其实就是把这个过程 API 化了。 这个东西出现的还真是快,其实我在前些天用 ChatGPT 插件的时候就一只在想这个问题,插件最强大的地方在于任何类型的应用,无论它本身是否有 AI 能力,都能用通过插件这个方式把大语言模型的能力用到自己的产品上面。
但是插件也有一个局限性,就是用户的使用场景受限,必须在 ChatGPT 界面中才行。我那会儿就在想要是这个能力能脱离 ChatGPT 本身的界面,那就更强大了。结果 OpenAI 还是厉害,我想到的这些问题,人家早就想明白了,而且很快的把它变成现实了。
https://platform.openai.com/docs/guides/gpt/function-calling
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
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。