如何使用 ChatGPT 助手 API 执行自定义操作

问题描述 投票:0回答:2

我正在尝试为餐厅创建一个 GPT 聊天机器人,可以询问顾客的联系信息和预订时间。在人工智能聊天机器人确定客户已向其提供所有这些详细信息后,我想运行我认为所谓的“操作”。我基本上想使用另一个 API 向对方发送电子邮件,表示我们将很快与您联系。然而,与此同时,我只想做一个console.log,上面写着“已确认”,这样我就知道人工智能理解它获得了所有详细信息,因此可以继续下一步(只是中间步骤)。然而,我正在努力解决如何从当前的代码转移到实际执行操作的情况,当前的代码只是根据特定的助手与用户聊天。这是我的代码(在后端的 Node 上运行,仅接收来自前端的响应并将其发送回):

const express = require('express');
const { OpenAI } = require('openai');
const cors = require('cors');
require('dotenv').config();

const app = express();
app.use(cors());
app.use(express.json());

const openai = new OpenAI(process.env.OPENAI_API_KEY);

app.post('/get-response', async (req, res) => {
    const userMessage = req.body.message;
    let threadId = req.body.threadId; // Receive threadId from the client
    const assistantId = 'MYASSISTANTID'; // Replace with your actual assistant ID

    // If no threadId or it's a new session, create a new thread
    if (!threadId) {
        const thread = await openai.beta.threads.create();
        threadId = thread.id;
    }

    await openai.beta.threads.messages.create(threadId, {
        role: "user",
        content: userMessage,
    });


    // Use runs to wait for the assistant response and then retrieve it
    const run = await openai.beta.threads.runs.create(threadId, {
        assistant_id: assistantId,
    });

    let runStatus = await openai.beta.threads.runs.retrieve(
        threadId,
        run.id
      );

      // Polling mechanism to see if runStatus is completed
      // This should be made more robust.
      while (runStatus.status !== "completed") {
        await new Promise((resolve) => setTimeout(resolve, 2000));
        runStatus = await openai.beta.threads.runs.retrieve(threadId, run.id);
      }


  //     //CHECKING FOR TABLE RESERVATION:
  //         // If the model output includes a function call
  //   if (runStatus.status === 'requires_action') {
  //     // You might receive an array of actions, iterate over it
  //     for (const action of runStatus.required_action.submit_tool_outputs.tool_calls) {
  //         const functionName = action.function.name;
  //         const arguments = JSON.parse(action.function.arguments);
          
  //         // Check if the function name matches 'table_reservation'
  //         if (functionName === 'table_reservation') {
  //             handleTableReservation(arguments);
  //             // Respond back to the model that the action has been handled
  //             await openai.beta.threads.runs.submit_tool_outputs(threadId, run.id, {
  //                 tool_outputs: [{
  //                     tool_call_id: action.id,
  //                     output: { success: true } // You can include more details if needed
  //                 }]
  //             });
  //         }
  //     }
  // }


      // Get the last assistant message from the messages array
      const messages = await openai.beta.threads.messages.list(threadId);

      // Find the last message for the current run
      const lastMessageForRun = messages.data
        .filter(
          (message) => message.run_id === run.id && message.role === "assistant"
        )
        .pop();

      // If an assistant message is found, console.log() it
      assistantMessage = ""
      if (lastMessageForRun) {
        assistantMessage = lastMessageForRun.content[0].text.value
        console.log(`${assistantMessage} \n`);
      }
    
    res.json({ message: assistantMessage, threadId: threadId });
});

const PORT = 3001;
app.listen(PORT, () => console.log(`Server listening on port ${PORT}`));

如果您查看上面的代码,您会意识到我尝试执行我所要求的操作,然后最终将其注释掉,因为它不起作用。

对于进一步的背景,我试图了解操作和工具是如何工作的,因为也许这就是我能够实现我想要做的事情的方式。我想出了以下我认为可能有用的代码(问题是我不知道如何组合这两段代码,并且下面的代码不使用我最终想要使用的助手) :

require('dotenv').config(); // This should be at the top of your file

const { OpenAI } = require('openai');
const openai = new OpenAI(process.env.OPENAI_API_KEY);


// Example dummy function hard coded to return the same weather
// In production, this could be your backend API or an external API
function getCurrentWeather(location) {
  if (location.toLowerCase().includes("tokyo")) {
    return JSON.stringify({ location: "Tokyo", temperature: "10", unit: "celsius" });
  } else if (location.toLowerCase().includes("san francisco")) {
    return JSON.stringify({ location: "San Francisco", temperature: "72", unit: "fahrenheit" });
  } else if (location.toLowerCase().includes("paris")) {
    return JSON.stringify({ location: "Paris", temperature: "22", unit: "fahrenheit" });
  } else {
    return JSON.stringify({ location, temperature: "unknown" });
  }
}

function get_table_reservations(bookingTime, numGuests) {
  if (bookingTime.toLowerCase().includes("4:30")) {
    return JSON.stringify({ availability: "Not available"});
  }
  else if (!bookingTime) {
    return JSON.stringify({ availability: "Please include a booking time"});
  }
  else {
    return JSON.stringify({ availability: "Available", forGuests: numGuests});
}
}


async function runConversation() {
  // Step 1: send the conversation and available functions to the model
  const messages = [
    { role: "user", content: "I want a table reservation for 3 people." },
  ];
  const tools = [
    {
      type: "function",
      function: {
        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"],
        },
      },
    },
    {
      type: "function",
      function: {
        name: "get_table_reservations",
        description: "Tell the user if a table is available for the number of guests and time they request",
        parameters: {
          type: "object",
          properties: {
            numGuests: {
              type: "integer",
              description: "The number of guests",
            },
            bookingTime: { type: "string", description: "The time requested for a reservation, eg. 8:30 PM" },
          },
          required: ["numGuests", "bookingTime"],
        },
      },
    },
  ];


  const response = await openai.chat.completions.create({
    model: "gpt-3.5-turbo-1106",
    messages: messages,
    tools: tools,
    tool_choice: "auto", // auto is default, but we'll be explicit
  });
  const responseMessage = response.choices[0].message;

  // Step 2: check if the model wanted to call a function
  const toolCalls = responseMessage.tool_calls;
  if (responseMessage.tool_calls) {
    // Step 3: call the function
    // Note: the JSON response may not always be valid; be sure to handle errors
    const availableFunctions = {
      get_current_weather: getCurrentWeather,
      get_table_reservations: get_table_reservations
    }; // only one function in this example, but you can have multiple
    messages.push(responseMessage); // extend conversation with assistant's reply
    for (const toolCall of toolCalls) {
      const functionName = toolCall.function.name;
      const functionToCall = availableFunctions[functionName];
      const functionArgs = JSON.parse(toolCall.function.arguments);
      console.log('Arguments:', toolCall.function.arguments, 'name:', functionName); // Add this line to debug
      const functionResponse = functionToCall(
        functionArgs.bookingTime,
        functionArgs.numGuests
      );
      messages.push({
        tool_call_id: toolCall.id,
        role: "tool",
        name: functionName,
        content: functionResponse,
      }); // extend conversation with function response
    }
    const secondResponse = await openai.chat.completions.create({
      model: "gpt-3.5-turbo-1106",
      messages: messages,
    }); // get a new response from the model where it can see the function response
    return secondResponse.choices;
  }
}


runConversation().then(console.log).catch(console.error);

或者,也许有一种更简单的方法可以通过 platform.openai 网站本身的助手页面来完成此操作。也许我需要在下面的屏幕截图中更改/添加一些内容,也许是一个函数。作为一个单独的问题,在助手 API 中添加函数的示例之一是“get_weather”,但我不确定它是如何工作的以及 get_weather 函数将如何运行或需要在哪里定义(也显示在下面的第二张截图)。

此外,如果有人能建议我在弄清楚这一步后如何开始使用电子邮件 API 来开始发送电子邮件,那将是一个很大的帮助(尽管我的问题的这一部分不太重要)

最后(我知道我问了很多问题),出于好奇,有人知道我是否可以用 Gemini 来实现与 GPT 助手所做的相同的事情吗?

提供所有这些详细信息

node.js artificial-intelligence openai-api chatgpt-api chatgpt-function-call
2个回答
0
投票

使用助手 API。声明一个函数调用工具并描述函数的每个参数和函数。如果您给出函数的准确含义,ChatGPT 将返回调用发送电子邮件的函数所需的信息。对于 Node 或 Python,您不仅可以在 Git 上找到大量库。然后在这里开始学习如何使用助手 API:Assistant API


0
投票

首先你必须创建一个助手。 Python示例取自OpenAI网站:

from openai import OpenAI
client = OpenAI()

my_assistant = client.beta.assistants.create(
    instructions="You are a personal math tutor. When asked a question, write and run Python code to answer the question.",
    name="Math Tutor",
    tools=[{"type": "code_interpreter"}],
    model="gpt-4",
)
print(my_assistant)

这是为了防止您想使用代码解释器,如果您想使用函数调用工具,请使用下面的代码,您必须更改工具数组,如下例所示,使用函数 (get_weather) 来检索天气预报并采用 2 个参数。您必须添加函数和参数的描述,以便让 ChatGPT 知道该函数的作用。它将从描述中了解是否以及何时调用您的函数以及要使用哪些参数,并根据它返回的结果创建答案。

"tools": [
    {
      "type": "function",
      "function": {
        "name": "get_weather",
        "description": "Determine weather in my location",
        "parameters": {
          "type": "object",
          "properties": {
            "location": {
              "type": "string",
              "description": "The city and state e.g. San Francisco, CA"
            },
            "unit": {
              "type": "string",
              "enum": [
                "c",
                "f"
              ]
            }
          },
          "required": [
            "location"
          ]
        }
      }
    }
  ],

(函数声明实际上是一个 Josn Schema)您可以向数组添加更多工具。检索通常用于处理传递给 ChatGPT 的文件。

然后使用以下代码片段创建一个代表聊天的线程:

from openai import OpenAI
client = OpenAI()

empty_thread = client.beta.threads.create()
print(empty_thread)

ChatGPT 将返回这样的 Json:

{
  "id": "thread_abc123",
  "object": "thread",
  "created_at": 1699012949,
  "metadata": {}
}

现在您有一个绑定到线程(聊天)的助手。您可以选择在创建线程时添加消息,也可以使用添加消息 API 添加消息:

from openai import OpenAI
client = OpenAI()

thread_message = client.beta.threads.messages.create(
  "thread_abc123",
  role="user",
  content="What is the weather in Rome ?",
)
print(thread_message)

现在您有了一个助手和一个线程,您可以处理发送到 ChatGPT 的消息。为此,请创建一个 Runb 对象,如下所示:

from openai import OpenAI
client = OpenAI()

run = client.beta.threads.runs.create(
  thread_id="thread_abc123",
  assistant_id="asst_abc123"
)
print(run)

您指定从之前的呼叫中收到的线程 ID 和助手 ID。 此时,您将通过首先拨打电话收到答案:

from openai import OpenAI
client = OpenAI()

run_steps = client.beta.threads.runs.steps.list(
    thread_id="thread_abc123",
    run_id="run_abc123"
)
print(run_steps)

获取运行步骤(ChatGPT 在做什么)。它返回的对象如下所示:

{
  "id": "step_abc123",
  "object": "thread.run.step",
  "created_at": 1699063291,
  "run_id": "run_abc123",
  "assistant_id": "asst_abc123",
  "thread_id": "thread_abc123",
  "type": "message_creation",
  "status": "completed",
  "cancelled_at": null,
  "completed_at": 1699063291,
  "expired_at": null,
  "failed_at": null,
  "last_error": null,
  "step_details": {
    "type": "message_creation",
    "message_creation": {
      "message_id": "msg_abc123"
    }
  },
  "usage": {
    "prompt_tokens": 123,
    "completion_tokens": 456,
    "total_tokens": 579
  }
}

检查状态是否等于“已完成”。完成后,使用类似于以下的代码片段获取消息:

from openai import OpenAI
client = OpenAI()

message = client.beta.threads.messages.retrieve(
  message_id="msg_abc123",
  thread_id="thread_abc123",
)
print(message)

调用结果将是以下Json:

{
  "id": "msg_abc123",
  "object": "thread.message",
  "created_at": 1699017614,
  "thread_id": "thread_abc123",
  "role": "user",
  "content": [
    {
      "type": "text",
      "text": {
        "value": "This is the message from ChatGPT",
        "annotations": []
      }
    }
  ],
  "file_ids": [],
  "assistant_id": null,
  "run_id": null,
  "metadata": {}
}

“内容”片段包含ChatGPT的答案:

"content": [
        {
          "type": "text",
          "text": {
            "value": "This is the message from ChatGPT",
            "annotations": []
          }
        }
      ],

实际上它也可以返回一些注释,但它是一个超出此示例的主题,您可以通过阅读以下链接的 OpenAI 文档来了解它:Assistants API

有任何问题吗?

© www.soinside.com 2019 - 2024. All rights reserved.