pythonでbardを使う

ChatGPT対抗手段として、とうとうリリースされたのがGoogleの大規模言語AI「Bard(吟遊詩人?)」である。どうやってPythonから使うのかな?・・・なんかBardに教えてもらった方法で、できないんだけど・・・

PythonでBardを使う例(230516)
BardAPIて?
あ、こちらでも解説されていますね
BardAPI本家 すばらしい・・・
GPTとBardで意思決定 自己採点のアイデアが良い。互いに採点もできるの!?
GPTとBardに概念を考えてもらう プロンプトが参考になる

・・・そして完成するBradとの会話プログラム。BradAPIを使っています。APIkeyは、ブラウザのクッキーから取得するという手順。これでいいんだろうか?・・・やはり現在の情報が参照できるのはアドバンテージありますね。しかし、推論の妥当さなどはGPT3.5や4にアドバンテージがあるように思う。どのような実装にすべきか、悩みますね。Unityから呼び出す方法は、まだ解説されていないようだし。

from bardapi import Bard
import os

os.environ['_BARD_API_KEY']="hogehoge."
 
 
def main():
  
    print("チャットをはじめます。q または quit で終了します。")
    print("-"*50)
    while True:
        user = input("<あなた>\n")
        if user == "q" or user == "quit":
            print(f"トークン数は{amount_tokens}でした。")
            break
        else:
            #chat.append({"role": "user", "content": user})
            msg=Bard().get_answer(user)['content']
 
        print("<Bart>")
        print(msg)
 
 
if __name__ == "__main__":
    main()

現状・・・調べ物にはBardがいいけど、人格ドライブにはGPT3.5がいいように思える。Bardに協力してもらおう!

#サイト上のcommandをチェックしBardでanswerに問い合わせ結果を書き込むスクリプト
from bardapi import Bard
import os
import time
import requests

os.environ['_BARD_API_KEY']="ほげ"

command_url = "http://kodamalab.sakura.ne.jp/AIchat/Bard1/command.txt"
response_url = "http://kodamalab.sakura.ne.jp/AIchat/Bard1/response.php"

#ファイルサイズを得る
def get_file_size(file_url):
    response = requests.head(file_url)
    try:
        return int(response.headers['Content-Length'])
    except KeyError:
        return None


#コマンドの内容を得る
def get_command(file_url):
    response = requests.get(file_url)
    response.encoding = 'utf-8'
    return response.text.strip()

#Bardからの回答を保存する
def write_response(response_url, response_text):
    data = {'response': response_text}
    requests.post(response_url, data=data)


answer=""
last_size = get_file_size(command_url) or 0
while True:
    current_size = get_file_size(command_url) or 0
    print("." , end=' ')
    if current_size != last_size:
        command = get_command(command_url)
        print(f"<COMMAND>{command}")
        answer = Bard().get_answer(command)['content']
        print(f"<ANSWER>{answer}")
        write_response(response_url, answer)
        last_size = current_size
    time.sleep(2)  # wait for 5 seconds before checking again

c#から呼び出す方法
解説されているが、アラビア語で理解できないという。コードを見れば・・・わかるよね?

・・・このコードは、UnityではないC#用で、LinqやThreadingなどの新しい手法を用いており、いまいち何をしているのか理解できない。エラーも出ているようだし・・・。とりあえずすべて打ち込んで、GPT4に解説してもらう。

コード1(Bard_Serviceクラス)とコード2(BardResponseModelおよびResultクラス)は、Googleの大規模言語モデルBardのAPIに接続して問い合わせを行うためのクラスです。

コード3は、これらのクラスを使用して実際に問い合わせを行うためのコードです。具体的には、エジプトの面積について問い合わせています。

以下に、各コードの詳細な説明をします。

コード1(Bard_Serviceクラス)

このクラスは、Googleの大規模言語モデルBardのAPIに接続し、問い合わせを行うためのサービスクラスです。

    apikeyとendpointは、Bard APIへの接続情報を保持します。
    Bard_Service(string apikey, string endpoint)は、コンストラクタで、APIキーとエンドポイントをセットします。
    AskBard(string prompt)メソッドは、引数として渡されたプロンプト(問い合わせ)を用いてBard APIにPOSTリクエストを送信し、その応答を返します。成功した場合は応答の内容を返すべきですが、現状では成功した場合の処理が不足していて何も返していません。失敗した場合は例外をスローします。

コード2(BardResponseModelおよびResultクラス)

このクラスは、Bard APIからの応答をデシリアライズ(文字列からオブジェクトへの変換)するためのモデルクラスです。しかし、コード1の現在の状態では、このモデルクラスは使われていません。

コード3(Programクラス)

このクラスは、上記のサービスクラス(Bard_Service)を使って、Bard APIに問い合わせを行うメインのプログラムです。

    BARD_API_ENDPOINTは、Bard APIのエンドポイントを保持しています。
    Mainメソッドでは、Bard_Serviceクラスのインスタンスを作成し、そのAskBardメソッドを呼び出してBard APIに問い合わせを行い、その結果をコンソールに出力します。

ただし、現状のコードでは、問い合わせが成功した場合の処理が不足しているため、問い合わせの結果を正しく取得して出力することはできません。これを修正するには、コード1のAskBardメ

すみません、切れてしまいました。

AskBardメソッド内で、成功した場合の結果(result)を適切に返すように修正する必要があります。つまり、以下のように修正すべきです:
public async Task<string> AskBard(string prompt)
{
    var request = new HttpRequestMessage
    {
        Method = HttpMethod.Post,
        RequestUri = new Uri(endpoint),
        Content = new StringContent(prompt,Encoding.UTF8, "application/json")
    };

    var client = new HttpClient();
    client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", apikey);

    using (var response = await client.SendAsync(request))
    {
        if (response.IsSuccessStatusCode)
        {
            var result = await response.Content.ReadAsStringAsync();
            return result;  // 追加:成功した場合には結果を返す
        }
        else
        {
            throw new Exception("Request failed with status code "+ response.StatusCode);
        }
    }
}

なお、Bard APIからの応答は通常JSON形式であり、コード2に示されたBardResponseModelクラスを用いてデシリアライズすることを想定しているように見えます。したがって、より完全な実装では、応答をこのクラスにデシリアライズし、その結果を返すようにすべきでしょう。それには、たとえばSystem.Text.Json.JsonSerializerを使用することができます。

最後に、ProgramクラスのMainメソッド内では、AskBardメソッドが非同期(Taskを返す)であることを考慮し、その結果を適切に取得するようにする必要があります。具体的には、.Resultまたは.GetAwaiter().GetResult()を使用して結果を取得するか、Mainメソッド自体を非同期にしてawaitを使用することが考えられます。

ふむふむ・・・やはりコード自体も未完成のようだね。UnityでCoroutineをつかう形式に書き換えてもらおうか。・・・うーむ、そもそもこのコード呼び出し用URLもNotFoundだし、正しく動作しない気がする。一旦保留しようか。
・・・BartAPI本家に、Python他言語に移植したソースが昨日公開されていた。CSもあったが、UnityはフルCSじゃないから、GPT4にUnity対応してもらったのが下コード。コレが動けば、Bart関係の処理が盤石になるな。

using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using UnityEngine;
using UnityEngine.Networking;

public class Bard : MonoBehaviour
{
    private const string BARD_URL = "https://bard.google.com/_/BardChatUi/data/assistant.lamda.BardFrontendService/StreamGenerate";

    private string token = "your bard token";
    private int reqId;
    private string conversationId;
    private string responseId;
    private string choiceId;

    void Start()
    {
        this.reqId = new System.Random().Next(1000, 9999);
        this.conversationId = "";
        this.responseId = "";
        this.choiceId = "";
        StartCoroutine(GetAnswer("input text here"));
    }

    private IEnumerator GetAnswer(string inputText)
    {
        Dictionary<string, string> headers = new Dictionary<string, string>
        {
            { "Content-Type", "application/x-www-form-urlencoded;charset=UTF-8" }
        };
        headers.Add("Cookie", $"__Secure-1PSID={this.token}");
        WWWForm form = new WWWForm();
        form.AddField("bl", "boq_assistant-bard-web-server_20230419.00_p1");
        form.AddField("_reqid", reqId.ToString());
        form.AddField("rt", "c");
        // to be filled out with correct data serialization
        form.AddField("f.req", $"[null, []]");
        form.AddField("at", "SNlM0e"); // to be filled out with correct SNlM0e value

        using UnityWebRequest www = UnityWebRequest.Post(BARD_URL, form);
        foreach (KeyValuePair<string, string> entry in headers)
        {
            www.SetRequestHeader(entry.Key, entry.Value);
        }

        yield return www.SendWebRequest();

        if (www.result != UnityWebRequest.Result.Success)
        {
            Debug.Log(www.error);
        }
        else
        {
            // TODO: Process the response, similar to the GetAnswer method
            Debug.Log(www.downloadHandler.text);
        }
    }
}

コメントを残す