Skip to content

Instantly share code, notes, and snippets.

@kujirahand
Last active December 4, 2024 02:19
Show Gist options
  • Select an option

  • Save kujirahand/86e6f182d1ed0232f5c1c9fdeff7ea79 to your computer and use it in GitHub Desktop.

Select an option

Save kujirahand/86e6f182d1ed0232f5c1c9fdeff7ea79 to your computer and use it in GitHub Desktop.
FPC for ChatGPT Simple Unit (for Windows) プロジェクト全体はこちら→ https://kujirahand.com/blog/go.php?822
unit ChatGPTUnit;
{$mode ObjFPC}{$H+}
interface
uses
fpjson, jsonparser, Process, Classes, SysUtils;
function CallChatGPTAPI(const Prompt: string): string;
function ParseChatGPTResponse(const json: string): string;
function ProcessExecuteHide(const AExecutable: string; const AParameters: array of string): Integer;
function LoadFromFile(FName: string): string;
procedure SaveToFile(FName: string; Body: string);
implementation
const
API_URL = 'https://api.openai.com/v1/chat/completions';
ENV_API_KEY = 'OPENAI_API_KEY'; // 環境変数の名前
MODEL_NAME = 'gpt-4o-mini'; // 使用するモデル
// テキストファイルを読む
function LoadFromFile(FName: string): string;
var sl: TStringList;
begin
sl := TStringList.Create;
sl.LoadFromFile(FName);
Result := sl.Text;
sl.Free;
end;
// テキストファイルに書き込む
procedure SaveToFile(FName: string; Body: string);
var sl: TStringList;
begin
sl := TStringList.Create;
sl.Text := Body;
sl.SaveToFile(Fname);
sl.Free;
end;
// ChatGPTへ問い合わせる
function CallChatGPTAPI(const Prompt: string): string;
var
APIKey, cmd, curl, apppath: string;
ctype, auth, body, batfile, jsonfile: string;
JsonRequest: TJSONObject;
resfile, response: string;
begin
// 環境変数からAPIキーを取得
APIKey := GetEnvironmentVariable(ENV_API_KEY);
if APIKey = '' then
begin
Result := '環境変数でAPIキーを設定してください';
Exit;
end;
// バッチファイルを生成するために一時ファイルのパスを決める
apppath := ExtractFilePath(ParamStr(0));
curl := ConcatPaths([apppath, 'curl.exe']);
batfile := ConcatPaths([apppath, 'request.bat']);
resfile := ConcatPaths([apppath, 'response.txt']);
jsonfile := ConcatPaths([apppath, 'request.json']);
if not FileExists(curl) then curl := 'curl'; // デフォルトのcurlを使う
try
// リクエストJSON作成
JsonRequest := TJSONObject.Create;
try
JsonRequest.Add('model', MODEL_NAME);
JsonRequest.Add('messages', TJSONArray.Create([
TJSONObject.Create(['role', 'user', 'content', Prompt])
]));
JsonRequest.Add('temperature', 0.7);
SaveToFile(jsonfile, JsonRequest.AsJSON);
finally
JsonRequest.Free;
end;
ctype := 'Content-Type: application/json';
auth := 'Authorization: Bearer ' + APIKey;
cmd := Format('"%s" %s -H "%s" -H "%s" -d @"%s" > "%s"', [
curl, API_URL, ctype, auth, jsonfile, resfile]);
// バッチファイルに保存
SaveToFile(batfile, cmd);
// 実行
ProcessExecuteHide(batfile, []);
// 実行結果を読みだす
body := LoadFromFile(resfile);
Result := ParseChatGPTResponse(body);
except
Result := '[ERROR]';
end;
// 作成したファイルを削除する
DeleteFile(batfile);
Deletefile(jsonfile);
DeleteFile(resfile);
end;
// ChatGPTの応答を解析して文字列で返す
function ParseChatGPTResponse(const json: string): string;
var
JSONData: TJSONData;
JSONObject, MessageObject: TJSONObject;
ChoicesArray: TJSONArray;
begin
Result := ''; // 初期値を空文字に設定
try
// JSON文字列を解析
JSONData := GetJSON(json);
// JSONDataがオブジェクトであることを確認
if not (JSONData is TJSONObject) then
raise Exception.Create('Invalid JSON format');
JSONObject := TJSONObject(JSONData);
// "choices" 配列を取得
if not (JSONObject.Find('choices') is TJSONArray) then
raise Exception.Create('"choices" is not a JSON array');
ChoicesArray := TJSONArray(JSONObject.Find('choices'));
// 最初の配列要素を確認
if not (ChoicesArray.Items[0] is TJSONObject) then
raise Exception.Create('First item in "choices" is not a JSON object');
// "message" オブジェクトを取得
MessageObject := TJSONObject(TJSONObject(ChoicesArray.Items[0]).Find('message'));
// "content" を取得
if not (MessageObject.Find('content') is TJSONString) then
raise Exception.Create('"content" is not a JSON string');
Result := MessageObject.Find('content').AsString; // "content" の値を取得
except
on E: Exception do
begin
Writeln('エラー: ', E.Message);
Result := ''; // エラーが発生した場合は空文字を返す
end;
end;
end;
// バッチファイルを静かに実行する
function ProcessExecuteHide(const AExecutable: string; const AParameters: array of string): Integer;
var
AProcess: TProcess;
I: Integer;
begin
AProcess := TProcess.Create(nil);
try
AProcess.Executable := AExecutable;
for I := Low(AParameters) to High(AParameters) do
AProcess.Parameters.Add(AParameters[I]);
AProcess.Options := [poWaitOnExit];
AProcess.ShowWindow := swoHIDE;
AProcess.Execute;
Result := AProcess.ExitStatus;
finally
AProcess.Free;
end;
end;
end.
@kujirahand
Copy link
Author

プロジェクト全体は、以下よりダウンロードできます。
https://kujirahand.com/blog/go.php?822

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment