見出し画像

ChatGPT + Embeddings で蜜源・花粉源に詳しいチャットボットをつくる 後編

すぐにチャットボットに触りたい方はこちら。

中編でベクトルデータベースに格納するまでやりました。

引き続き説明していきます。


ChatGPT + Embeddings

1,2: 問い合わせのembedding

質問を受け取ったらembeddingします。

//Node.js

import {OpenAIApi} from 'openai'

const configuration = new Configuration({
    apiKey: OPENAI_API_KEY,
    organization: OPENAI_ORGANIZATION,
  });
  
const openAi = new OpenAIApi(configuration)

const query = '冬の蜜源植物を3つ教えてください'

const queryEmbeddingResponse = await openAI.createEmbedding({
    model: 'text-embedding-ada-002',
    input: query,
  });

 const queryEmbedding = queryEmbeddingResponse.data.data[0].embedding


3,4 データベースに問い合わせ

そのベクトルデータを使ってデータベースに問い合わせ、ChatGPTにわたす情報を見つけます。
具体的には入力ベクトルデータとデータベース上のベクトルデータのコサインを計算して大きなものから順に取得することをデータベース側でやっています。ベクトルデータベース便利。

import axios, { AxiosResponse } from 'axios'

//Pinecone の Node.js クライアントはあるのですが挙動が変だったので使いませんでした

const options = {
    method: 'POST',
    //インデックスごとに異なります
    url: 'https://test-project_id.svc.environment.pinecone.io/query',
    headers: {
      accept: 'application/json',
      'content-type': 'application/json',
      'Api-Key': PINECONE_API_KEY,
    },
    //スコア上位から100件取得 metadata含める
    data: {namespace: 'beehappy-db',includeValues: 'false', includeMetadata: true, vector: queryEmbedding, topK: 100}
  }

const results = await axios.request(options)

//ChatGPTに与える情報
let articles = ""

//参照したデータベース記事一覧
const references = [] as {score: number,url: string, title: string}[]

if(results.data && results.data.matches && results.data.matches.length > 0){
  const matches = results.data.matches as {score: number; metadata: {body: string, title: string, url: string}}[]
  
  for(const match of matches) {
    if(match.metadata){
      const body = match.metadata.body
      const url = match.metadata.url
      const score = match.score
      const nextArticle = `\n\nNectar & Pollen Sources Database article section: \n"""\n${url}\n${body}\n"""`;

    //numTokensはトークン数を計算する関数 別に準備する
      const currentTokens = numTokens(articles + nextArticle + query)
      
      //トークン数の上限まで詰め込む ただし、返事の分はとっておく maxTokensはmodelによって異なる
      if(currentTokens < (maxTokens - 2000)) {
        articles += nextArticle
        //参照した記事へのリンクを生成するため
        references.push({score: score, url: match.metadata.url, title: match.metadata.title})
      }else{
        break
      }
    }
  }
}

4,5,6 ChatGPTに情報と質問を投げて返事を待つ

role: system で先ほど生成した articles を以下のような文言とともに渡します。role: user で質問を渡します。

そしてChatGPTに投げる!

const messages = [
    {
      role: "system",
      content: `Use the below articles on Nectar & Pollen Sources Database to answer the subsequent question. If the answer cannot be found in the articles, write 'I could not find an answer'. ${articles}`
    },
    { role: "user", content: query}

const requestues = {
      model: model,
      messages: messages
    }

const response = await openAI.createChatCompletion(request)

const replyMessage = response.data.choices[0].message?.content || ''

これでめでたしめでたし。

生成AIの成果物ばかりが溢れたら

今後、世間には生成AIでつくった文章ばかりがあふれることになるでしょう。そうすると生成AIの性能は頭打ちにならないのか?

地べたを這ってつくったデータベースの価値は今後、見直されるような気がしています。分野や内容に関わらず生成AIを介していないというだけで。

埋もれちゃってもったいないと思っているデータベースがあったらぜひ教えてください。活かし方、考えたいです。



この記事が気に入ったらサポートをしてみませんか?