Sdílet prostřednictvím


Klientská knihovna Azure OpenAI Assistants pro JavaScript – verze 1.0.0-beta.5

Klientská knihovna Azure OpenAI Assistants pro JavaScript je adaptací rozhraní REST API OpenAI, která poskytuje idiomatické rozhraní a bohatou integraci se zbytkem ekosystému sady Azure SDK. Může se připojit k prostředkům Azure OpenAI nebo ke koncovému bodu odvozování OpenAI mimo Azure, což je skvělá volba i pro vývoj mimo Azure OpenAI.

Klíčové odkazy:

Začínáme

Aktuálně podporovaná prostředí

  • LtS verze Node.js
  • Nejnovější verze prohlížečů Safari, Chrome, Edge a Firefox.

Požadavky

Pokud chcete použít prostředek Azure OpenAI, musíte mít předplatné Azure a přístup k Azure OpenAI. To vám umožní vytvořit prostředek Azure OpenAI a získat adresu URL připojení i klíče rozhraní API. Další informace najdete v tématu Rychlý start: Začínáme s generováním textu pomocí služby Azure OpenAI.

Pokud chcete použít klientskou knihovnu JS azure OpenAI Assistants pro připojení k openAI mimo Azure, budete potřebovat klíč rozhraní API z účtu vývojáře na adrese https://platform.openai.com/.

Nainstalujte balíček @azure/openai-assistants.

Nainstalujte klientskou knihovnu Azure OpenAI Assistants pro JavaScript pomocí npmpříkazu :

npm install @azure/openai-assistants

Vytvoření a ověření AssistantsClient

Pokud chcete nakonfigurovat klienta pro použití s Azure OpenAI, poskytněte prostředku Azure OpenAI platný identifikátor URI koncového bodu spolu s odpovídajícími přihlašovacími údaji klíče, přihlašovacími údaji tokenu nebo přihlašovacími údaji identity Azure, které mají oprávnění k používání prostředku Azure OpenAI. Pokud chcete místo toho nakonfigurovat klienta pro připojení ke službě OpenAI, zadejte klíč rozhraní API z portálu pro vývojáře OpenAI.

Použití klíče rozhraní API z Azure

Pomocí webu Azure Portal přejděte k prostředku OpenAI a načtěte klíč rozhraní API, nebo použijte následující fragment kódu Azure CLI :

Poznámka: Někdy se klíč rozhraní API označuje jako klíč předplatného nebo klíč rozhraní API předplatného.

az cognitiveservices account keys list --resource-group <your-resource-group-name> --name <your-resource-name>

Klíčové koncepty

Přehled konceptů a vztahů používaných s asistenty najdete v dokumentaci k tomu, jak fungují asistenti OpenAI . Tento přehled úzce navazuje na příklad s přehledem OpenAI a ukazuje základy vytváření, spouštění a používání pomocníků a vláken.

Začněte tím, že vytvoříte :AssistantsClient

const assistantsClient = new AssistantsClient("<endpoint>", new AzureKeyCredential("<azure_api_key>"));

S klientem je pak možné vytvořit asistent. asistent je účelově vytvořené rozhraní pro modely OpenAI, které může volat nástroje a zároveň umožňovat pokyny vysoké úrovně po celou dobu životnosti asistent.

Kód pro vytvoření asistent:

const assistant = await assistantsClient.createAssistant({
  model: "gpt-4-1106-preview",
  name: "JS Math Tutor",
  instructions: "You are a personal math tutor. Write and run code to answer math questions.",
  tools: [{ type: "code_interpreter" }]
});

Relace konverzace mezi asistentem a uživatelem se nazývá vlákno. Vlákna ukládají zprávy a automaticky zpracovávají zkrácení tak, aby se obsah vešel do kontextu modelu.

Vytvoření vlákna:

const assistantThread = await assistantsClient.createThread();

Zpráva představuje zprávu vytvořenou asistentem nebo uživatelem. Zprávy můžou obsahovat text, obrázky a další soubory. Zprávy jsou uloženy jako seznam ve vlákně. Když je vlákno vytvořené, můžete na něm vytvářet zprávy:

const question = "I need to solve the equation '3x + 11 = 14'. Can you help me?";
const messageResponse = await assistantsClient.createMessage(assistantThread.id, "user", question);

Spuštění představuje vyvolání asistenta ve vlákně. Asistent používá konfiguraci a zprávy vlákna k provádění úloh voláním modelů a nástrojů. Jako součást spuštění připojí Asistent zprávy do vlákna. Pak je možné spustit spuštění, které vyhodnotí vlákno proti asistent:

let runResponse = await assistantsClient.createRun(assistantThread.id, {
   assistantId: assistant.id,
   instructions: "Please address the user as Jane Doe. The user has a premium account." 
});

Jakmile se spuštění spustí, mělo by se dotazovat, dokud nedosáhne stavu terminálu:

do {
  await new Promise((resolve) => setTimeout(resolve, 800));
  runResponse = await assistantsClient.getRun(assistantThread.id, runResponse.id);
} while (runResponse.status === "queued" || runResponse.status === "in_progress")

Za předpokladu, že se spuštění úspěšně dokončilo, bude výpis zpráv z vlákna, které bylo spuštěno, odrážet nové informace přidané asistent:

const runMessages = await assistantsClient.listMessages(assistantThread.id);
for (const runMessageDatum of runMessages.data) {
  for (const item of runMessageDatum.content) {
    if (item.type === "text") {
      console.log(item.text.value);
    } else if (item.type === "image_file") {
      console.log(item.imageFile.fileId);
    }
  }
}

Příklad výstupu z této sekvence:

2023-11-14 20:21:23 -  assistant: The solution to the equation \(3x + 11 = 14\) is \(x = 1\).
2023-11-14 20:21:18 -       user: I need to solve the equation `3x + 11 = 14`. Can you help me?

Práce se soubory pro načítání

Na soubory můžou nahrávat asistenti nebo zprávy a pak na tyto soubory odkazovat. Nejprve použijte zobecněné rozhraní API pro nahrávání s účelem "asistentů", abyste zpřístupnili ID souboru:

const filename = "<path_to_text_file>";
await fs.writeFile(filename, "The word 'apple' uses the code 442345, while the word 'banana' uses the code 673457.", "utf8");
const uint8array = await fs.readFile(filename);
const uploadAssistantFile = await assistantsClient.uploadFile(uint8array, "assistants", { filename });

Po nahrání můžete ID souboru zadat asistent při vytvoření. Upozorňujeme, že ID souborů se použijí jenom v případě, že je povolený příslušný nástroj, jako je interpret kódu nebo načítání.

const fileAssistant = await assistantsClient.createAssistant({
  model: "gpt-4-1106-preview",
  name: "JS SDK Test Assistant - Retrieval",
  instructions: "You are a helpful assistant that can help fetch data from files you know about.",
  tools: [{ type: "retrieval" }],
  fileIds: [ uploadAssistantFile.id ]
});

S povoleným přidružením ID souboru a podporovaným nástrojem bude asistent moci při spouštění vláken využívat přidružená data.

Použití nástrojů funkcí a paralelního volání funkcí

Jak je popsáno v dokumentaci OpenAI k nástrojům asistent, nástroje, které odkazují na funkce definované volajícím jako funkce, je možné poskytnout asistent, aby mohl během běhu dynamicky přeložit a rozmístit jeho nejednoznačnost.

Zde je nastíněný jednoduchý asistent, který "ví, jak na to" prostřednictvím funkcí poskytovaných volajícím:

  1. Získání oblíbeného města uživatele
  2. Získání přezdívky pro dané město
  3. Získání aktuálního počasí (volitelně s jednotkou teploty) ve městě

Začněte definováním funkcí, které se mají použít – skutečné implementace jsou pouze reprezentativní zástupné procedury.

// Example of a function that defines no parameters
const getFavoriteCity = () => "Atlanta, GA";
const getUserFavoriteCityTool = { 
  type: "function",
  function: {
    name: "getUserFavoriteCity",
    description: "Gets the user's favorite city.",
    parameters: {
      type: "object",
      properties: {}
    }
  }
}; 

// Example of a function with a single required parameter
const getCityNickname = (city) => { 
  switch (city) { 
    case "Atlanta, GA": 
      return "The ATL"; 
    case "Seattle, WA": 
      return "The Emerald City"; 
    case "Los Angeles, CA":
      return "LA"; 
    default: 
      return "Unknown"; 
  }
};

const getCityNicknameTool = { 
  type: "function",
  function: {
    name: "getCityNickname",
    description: "Gets the nickname for a city, e.g. 'LA' for 'Los Angeles, CA'.",
    parameters: { 
      type: "object",
      properties: { 
        city: {
          type: "string",
          description: "The city and state, e.g. San Francisco, CA"
        } 
      }
    }
  }
};

// Example of a function with one required and one optional, enum parameter
const getWeatherAtLocation = (location, temperatureUnit = "f") => {
  switch (location) { 
    case "Atlanta, GA": 
      return temperatureUnit === "f" ? "84f" : "26c"; 
    case "Seattle, WA": 
      return temperatureUnit === "f" ? "70f" : "21c"; 
    case "Los Angeles, CA":
      return temperatureUnit === "f" ? "90f" : "28c"; 
    default: 
      return "Unknown"; 
  }
};

const getWeatherAtLocationTool = { 
  type: "function",
  function: {
    name: "getWeatherAtLocation",
    description: "Gets the current weather at a provided location.",
    parameters: { 
      type: "object",
      properties: { 
        location: {
          type: "string",
          description: "The city and state, e.g. San Francisco, CA"
        },
        temperatureUnit: {
          type: "string",
          enum: ["f", "c"],
        }
      },
      required: ["location"]
    }
  }
};

S funkcemi definovanými v příslušných nástrojích je teď možné vytvořit asistent s povolenými nástroji:

  const weatherAssistant = await assistantsClient.createAssistant({
  // note: parallel function calling is only supported with newer models like gpt-4-1106-preview
  model: "gpt-4-1106-preview",
  name: "JS SDK Test Assistant - Weather",
  instructions: `You are a weather bot. Use the provided functions to help answer questions.
    Customize your responses to the user's preferences as much as possible and use friendly
    nicknames for cities whenever possible.
  `,
  tools: [getUserFavoriteCityTool, getCityNicknameTool, getWeatherAtLocationTool]
});

Pokud asistent volá nástroje, volající kód bude muset přeložit ToolCall instance na odpovídající ToolOutputSubmission instance. Základní příklad se pro usnadnění extrahuje tady:

const getResolvedToolOutput = (toolCall) => {
  const toolOutput = { toolCallId: toolCall.id };

  if (toolCall["function"]) {
    const functionCall = toolCall["function"];
    const functionName = functionCall.name;
    const functionArgs = JSON.parse(functionCall["arguments"] ?? {});

    switch (functionName) {
      case "getUserFavoriteCity":
        toolOutput.output = getFavoriteCity();
        break;
      case "getCityNickname":
        toolOutput.output = getCityNickname(functionArgs["city"]);
        break;
      case "getWeatherAtLocation":
        toolOutput.output = getWeatherAtLocation(functionArgs.location, functionArgs.temperatureUnit);
        break;
      default:
        toolOutput.output = `Unknown function: ${functionName}`;
        break;
    }
  }
  return toolOutput;
};

Pokud chcete zpracovat vstup uživatele, jako je "what's the weather like right's like right in my favorite city?" (Jaké je počasí v mém oblíbeném městě?), mělo by být dotazování odpovědi na dokončení doplněno RunStatus o kontrolu RequiresAction přítomnosti vlastnosti nebo v tomto případě RequiredAction přítomnost vlastnosti na spuštění. Kolekce ToolOutputSubmissions by pak měla být odeslána do spuštění prostřednictvím metody , SubmitRunToolOutputs aby spuštění bylo možné pokračovat:

const question = "What's the weather like right now in my favorite city?";
let runResponse = await assistantsClient.createThreadAndRun({ 
  assistantId: weatherAssistant.id, 
  thread: { messages: [{ role: "user", content: question }] },
  tools: [getUserFavoriteCityTool, getCityNicknameTool, getWeatherAtLocationTool]
});

do {
  await new Promise((resolve) => setTimeout(resolve, 500));
  runResponse = await assistantsClient.getRun(runResponse.threadId, runResponse.id);
  
  if (runResponse.status === "requires_action" && runResponse.requiredAction.type === "submit_tool_outputs") {
    const toolOutputs = [];

    for (const toolCall of runResponse.requiredAction.submitToolOutputs.toolCalls) {
      toolOutputs.push(getResolvedToolOutput(toolCall));
    }
    runResponse = await assistantsClient.submitToolOutputsToRun(runResponse.threadId, runResponse.id, toolOutputs);
  }
} while (runResponse.status === "queued" || runResponse.status === "in_progress")

Všimněte si, že při použití podporovaných modelů může asistent požadovat paralelní zavolání několika funkcí. Starší modely můžou současně volat jenom jednu funkci.

Jakmile jsou všechna potřebná volání funkcí vyřešena, bude spuštění pokračovat normálně a dokončené zprávy ve vlákně budou obsahovat výstup modelu doplněný o výstupy poskytnutého funkčního nástroje.

Poradce při potížích

protokolování

Povolení protokolování může pomoct odhalit užitečné informace o selháních. Pokud chcete zobrazit protokol požadavků a odpovědí HTTP, nastavte proměnnou AZURE_LOG_LEVEL prostředí na info. Případně je možné protokolování povolit za běhu voláním setLogLevel v :@azure/logger

const { setLogLevel } = require("@azure/logger");

setLogLevel("info");

Podrobnější pokyny k povolení protokolů najdete v dokumentaci k balíčkům @azure/protokolovacího nástroje.