Node.jsでAzure OpenAI Embeddings APIを利用してみる


OpenAIの埋め込み(Embeddings)をJavaScriptから使ってみます。

https://platform.openai.com/docs/guides/embeddings/what-are-embeddings


## OpenAI Embeddings API

文章をベクトル変換してくれるAPIです。

クラメソさんの記事がイメージがつかみやすいです。

 https://dev.classmethod.jp/articles/search-with-openai-embeddings/ 

## 準備とインストール、環境など

```bash
$ npm init -y
```

- Node.js v21
- @azure/openai: v1.0.0-beta.10
- openai: v4.24.7

### Azure AI Studioでモデルを作る

GPTなどではなく、`text-embedding-ada-002`を選択します。

> ![スクリーンショット 2024-01-17 3.14.40.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/35387/78a87c5e-7980-0f30-263f-58fb43f64490.png "スクリーンショット 2024-01-17 3.14.40.png")

デプロイ名は任意の名前でOKです。`n0bisuke-text-embedding-ada-002`など

## OpenAI SDK版とAzure SDK版

どっちでも書けたので、二つメモしておきます。

現時点だとAzure SDK版はフォーマットの指定が出来ない？ぽい雰囲気があったのでOpenAIのSDKで利用したほうが良いかもです。

（多分OpenAIのSDKのラッパーな気がするので、できるんだけど、ドキュメントが見つけられなかった。）

試しに入れている文章はGPTに作ってもらった`田中`という苗字の説明文章です。

```
日本の非常に一般的な苗字で、田んぼや中央地域を意味することが多い。この名前は、農業が盛んな地域や中心地の住民に由来している可能性がある。
```

### OpenAI SDK版 - Embeddings API

- SDKインストール

```
$ npm i openai
```

- コピペ用

```js
//import OpenAI from "openai";
const OpenAI = require("openai");

const apiVersion = '2023-06-01-preview'; //一旦固定(?)

const endpoint = 'https://XXXXXXXXX.openai.azure.com'; //Azure OpenAIのエンドポイント
const azureApiKey = `XXXXXXXXXXXXXXXXX`; //Azure OpenAIのAPIキー
const deploymentId = "n0bisuke-text-embedding-ada-002"; //作成したモデル名 - デプロイ名

//クライアント作成
const openai = new OpenAI({
    apiKey: azureApiKey,
    baseURL: `${endpoint}/openai/deployments/${deploymentId}`,
    defaultQuery: { 'api-version': apiVersion },
    defaultHeaders: { 'api-key': azureApiKey },
});

async function main() {
	const input = "日本の非常に一般的な苗字で、田んぼや中央地域を意味することが多い。この名前は、農業が盛んな地域や中心地の住民に由来している可能性がある。";
    const embedding = await openai.embeddings.create({
        model: deploymentId,
        input: input,
        encoding_format: 'float',
    });

    console.log(embedding);
}

main().catch((err) => {
	console.error("The sample encountered an error:", err);
});
```

- 実行

```bash
$ node app.js

{
  object: 'list',
  data: [ { object: 'embedding', index: 0, embedding: [Array] } ],
  model: '/var/azureml-app/azureml-models/text-embedding-ada-002-8k/584175/',
  usage: { prompt_tokens: 76, total_tokens: 76 }
}
```

### Azure OpenAIのSDK版 - Embeddings API

- SDKインストール

```
$ npm i @azure/openai
```

- コピペ用

この辺を見つつサンプル書いてみました。

https://learn.microsoft.com/ja-jp/javascript/api/@azure/openai/getembeddingsoptions?view=azure-node-preview#@azure-openai-getembeddingsoptions-requestoptions

https://learn.microsoft.com/ja-jp/javascript/api/@azure/openai/embeddings?view=azure-node-preview

https://learn.microsoft.com/ja-jp/javascript/api/@azure/openai/openaiclient?view=azure-node-preview#@azure-openai-openaiclient-getchatcompletions

```js
//import { OpenAIClient, AzureKeyCredential } from "@azure/openai";
const { OpenAIClient,AzureKeyCredential } = require("@azure/openai");

const endpoint = 'https://XXXXXXXXX.openai.azure.com'; //Azure OpenAIのエンドポイント
const azureApiKey = `XXXXXXXXXXXXXXXXX`; //Azure OpenAIのAPIキー
const deploymentId = "n0bisuke-text-embedding-ada-002"; //作成したモデル名 - デプロイ名

const openai = new OpenAIClient(endpoint, new AzureKeyCredential(azureApiKey));

async function main(){
    const input = `日本の非常に一般的な苗字で、田んぼや中央地域を意味することが多い。この名前は、農業が盛んな地域や中心地の住民に由来している可能性がある。`;
    const options = {
        //encoding_format: 'float' //この指定をできなかった
    };
    const embedding = await openai.getEmbeddings(deploymentId, input, options);
    console.log(embedding);
}

main().catch((err) => {
  console.error("The sample encountered an error:", err);
});
```

- 実行

```bash
$ bun app.js

{
  data: [
    {
      embedding: [
        -0.0074692625, -0.016184496, ....省略
      ],
      index: 0,
    }
  ],
  usage: {
    promptTokens: 76,
    totalTokens: 76,
  },
}
```