New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
OpenAI Embeddings API #982
Labels
Projects
Comments
サンプルコード # include <Siv3D.hpp> // OpenSiv3D v0.6.8
struct Text
{
String text;
Array<float> embedding;
float cosineSimilarity = 0.0f;
};
void Init(const String API_KEY, Array<Text>& texts)
{
for (auto& text : texts)
{
// OpenAI Embeddings API で文章の埋め込みベクトルを取得
text.embedding = OpenAI::Embedding::Create(API_KEY, text.text);
}
}
void Main()
{
Window::Resize(1280, 720);
Scene::SetBackground(ColorF{ 0.92 });
const String API_KEY = EnvironmentVariable::Get(U"MY_OPENAI_API_KEY");
const Font font{ FontMethod::MSDF, 48, Typeface::Medium };
Array<Text> texts =
{
{ U"公園。市街地などに設けられた公共施設としての庭園や遊園地。" },
{ U"天気。ある場所の、ある時刻の気象状態。気温・湿度・風・雲量などを総合した状態。" },
{ U"会議。関係者が集まって相談をし、物事を決定すること。" },
{ U"水泳。スポーツや娯楽として水中を泳ぐこと。" },
{ U"寿司。酢飯に生鮮魚介の切り身を乗せた料理。" },
{ U"携帯電話。無線を用いて長距離通信のできる小型の移動電話。" },
{ U"医者。病人の診察・治療を職業とする人。" },
{ U"電車。駆動用電動機を装置し、架線あるいは軌道から得る電気を動力源として走行する鉄道車両。" },
{ U"森林。樹木、特に高木が群生して大きな面積を占めている所。" },
{ U"火曜日。月曜日と水曜日の間にある週の1日。" },
{ U"大使館。特命全権大使が駐在国において公務を執行する公館。" },
{ U"窃盗。人の物をぬすむこと。また、その人。" },
{ U"地震。地球内部の急激な変動による振動が四方に伝わり大地が揺れる現象。" },
{ U"手紙。用事などを記して、人に送る文書。" },
{ U"睡眠。ねむること。ねむり。" },
};
AsyncTask initTask = Async(Init, String{ API_KEY }, std::ref(texts));
TextEditState textEditState;
float maxCosineSimilarity = 0.0f, minCosineSimilarity = 1.0f;
AsyncHTTPTask task;
while (System::Update())
{
if (initTask.isValid())
{
Circle{ Scene::Center(), 40 }.drawArc(Scene::Time() * 90_deg, 270_deg, 5);
font(U"テキストの埋め込みベクトルを計算しています。事前に計算しておくことで実行時の処理を省略できます。").drawAt(22, Scene::Center().movedBy(0, 100), ColorF{ 0.11 });
if (initTask.isReady())
{
initTask.get();
}
continue;
}
SimpleGUI::TextBox(textEditState, Vec2{ 40, 40 }, 1000);
if (SimpleGUI::Button(U"検索", Vec2{ 1060, 40 }, 80, (not textEditState.text.isEmpty()) && (not task.isDownloading())))
{
task = OpenAI::Embedding::CreateAsync(API_KEY, textEditState.text);
}
if (task.isReady() && task.getResponse().isOK())
{
const Array<float> inputEmbedding = OpenAI::Embedding::GetVector(task.getAsJSON());
maxCosineSimilarity = 0.0f; minCosineSimilarity = 1.0f;
for (auto& text : texts)
{
text.cosineSimilarity = OpenAI::Embedding::CosineSimilarity(inputEmbedding, text.embedding);
maxCosineSimilarity = Max(maxCosineSimilarity, text.cosineSimilarity);
minCosineSimilarity = Min(minCosineSimilarity, text.cosineSimilarity);
}
}
if (not task.isDownloading())
{
for (int32 i = 0; i < texts.size(); ++i)
{
const float cosineSimilarity = texts[i].cosineSimilarity;
const Rect rect{ 40, (100 + i * 38), 1180, 36 };
// 最も類似度が高いものを強調表示
rect.draw((cosineSimilarity == maxCosineSimilarity) ? ColorF{ 1.0, 1.0, 0.75 } : ColorF{ 1.0 });
// コサイン類似度を 0.0 ~ 1.0 に変換
const double t = Math::Map(cosineSimilarity, minCosineSimilarity, maxCosineSimilarity, 0.0, 1.0);
RectF{ rect.pos, (50 * t), rect.h }.stretched(0, -2).draw(Colormap01F(t, ColormapType::Turbo));
// 文章とコサイン類似度を表示
font(texts[i].text).draw(22, Arg::leftCenter = rect.leftCenter().movedBy(80, 0), ColorF{ 0.11 });
font(cosineSimilarity).draw(18, Arg::leftCenter = rect.leftCenter().movedBy(1080, 0), ColorF{ 0.11 });
}
}
}
if (initTask.isValid())
{
initTask.wait();
}
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The text was updated successfully, but these errors were encountered: