0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

OpenAI の text-embedding-ada-002 でベクトル化し、コサイン類似度を計算(Angular)

Last updated at Posted at 2024-02-28

はじめに

ChatGPTを用いたアプリケーションの開発中、ChatGPTへの直列した命令数が増えるとレスポンス時間が長くなるという問題に直面しました。そこで、レスポンス時間を短縮するために、コサイン類似度を算出し、類似度が高いものだけに命令を絞り込み、ChatGPTに送る命令数を減らすというアプローチを試みました。これはその試みの備忘録となります。

以下では、入力された値をベクトル化し、そのデータと事前にベクトル化して用意していた大量のデータからそれぞれコサイン類似度を求め、コサイン類似度が高い上位10件を取得するソースコードとなっています。

ソース

.ts
import { HttpClient } from '@angular/common/http';
import { Component } from '@angular/core';

// コサイン類似度を計算するためのライブラリ
var similarity = require('compute-cosine-similarity');


// 入力された値
inputWord = "入力された値";

// 入力された値をベクトル化した値
inputWordEmbedding = "";

// 事前にベクトル化したデータ (exがベクトル値、noは紐づくユニークな番号)
embeddingData: { no: string, ex: number[] }[] = ["事前に用意していたデータ"]; 


// 類似度の高い上位10件を取得
async addUpper10(){
      //inputWordをベクトル化
      await this.callEmbedding(this.inputWord);

      // 事前に用意していたデータに対してそれぞれコサイン類似度を計算
      var similarities = this.embeddingData.map((item, index) => {
        return {
          no: item.no,
          // コサイン類似度を算出
          similarity: similarity(this.inputWordEmbedding, item.ex)
        };
      });

      // コサイン類似度でソート
      similarities.sort((a: { similarity: number; }, b: { similarity: number; }) => b.similarity - a.similarity);

      // トップ10を取得
      var top10 = similarities.slice(0, 10);

      // トップ10のnoを取得
      var top10no = top10.map((item: { no: any; }) => item.no);
  }

// embeddingAPI呼び出し
  callEmbedding(changeVectWord: string) {
    const _this = this;
    return new Promise(function (r, re) {
      _this.http.post('http://localhost:3000/api/embedding', 
      {
        text: [changeVectWord]
      })
      .subscribe({
        next(data: any) {
          _this.imputWordEmbedding = data.data[0].embedding;
          return r(data.data[0].embedding);
        },
        error(err) {
          alert('エラーが発生しました: ' + err.message);
          return re(err);
        }
      });
    })
  }
server.js
const express = require('express');
const app = express();
const { OpenAIClient, AzureKeyCredential } = require("@azure/openai");

// embedding認証情報
const embeddingEndpoint = "エンドポイント"
const embeddingAzureApiKey = "APIキー"
const embeddingDeploymentId = "デプロイ名"
const embeddingClient = new OpenAIClient(embeddingEndpoint, new AzureKeyCredential(embeddingAzureApiKey));


// embeddingAPI実行
app.post('/api/embedding', async (req, res) => {
    const input = req.body.text; // リクエストボディからテキストを取得
    const options = {
        //encoding_format: 'float' //この指定をできなかった
    };
    try {
        const embedding = await embeddingClient.getEmbeddings(embeddingDeploymentId, input, options);
        res.json(embedding); // レスポンスとして埋め込みを返す
    } catch (err) {
        console.error("The sample encountered an error:", err);
        res.status(500).send(err.message); // エラーメッセージを返す
    }
});

app.listen(3000, () => console.log('Server is listening on port 3000'));

おまけ

事前データの準備中に以下の問題も発生 :cold_sweat:

image.png

とのことでデータ量の多いものは、情報をキリのいい箇所で切ってベクトル化。
その後は以下の要領でベクトルを平均化した。

.ts
// 2つのベクトルの平均値算出
  averageVectors2(v1: string | any[], v2: string | any[]) {
    if (v1.length !== v2.length) {
      throw new Error('All vectors must be the same length');
    }
    let result = [];
    for (let i = 0; i < v1.length; i++) {
      let average = (v1[i] + v2[i]) / 2;
      // 少数第9位までに丸める
      let rounded = parseFloat(average.toFixed(9));
      result[i] = rounded;
    }
    console.log("ベクトル平均化の値:" + result);
    return result;
  }

終わりに

参考になりましたら「いいね」を押していただけると励みになりますのでよろしくお願いします:sunny::camel:

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?