2024年10月31日木曜日
Graph Visualization Plug-inのサンプル・アプリケーションをOracle Database 23aiのAPEXにインストールする
2024年10月29日火曜日
OpenAIのChat Completions APIでStructured Outputsを指定する
上記の記事で作成したAPEXアプリケーションを、Structured Outputsの指定ができるように改変しました。API呼び出しを実装しているパッケージUTL_OPENAI_CHAT_APIも、Structured Outputsに対応するために変更しています。ただしFunction Callingを実装していたので、改変部分は非常に少ないです。
「You are a helpful math tutor. Guide the user through the solution step by step.」
ユーザー・メッセージ
「how can I solve 8x + 7 = -23」
{
"steps" :
[
{
"explanation" : "Start with the original equation: 8x + 7 = -23",
"output" : "8x + 7 = -23"
},
{
"explanation" : "To isolate the term with x, subtract 7 from both sides of the equation.",
"output" : "8x + 7 - 7 = -23 - 7"
},
{
"explanation" : "Simplifying both sides gives us: 8x = -30",
"output" : "8x = -30"
},
{
"explanation" : "Next, divide both sides by 8 to solve for x.",
"output" : "x = -30 / 8"
},
{
"explanation" : "Simplifying -30/8 gives us -15/4 or -3.75.",
"output" : "x = -3.75 or x = -15/4"
}
],
"final_answer" : "x = -15/4 or x = -3.75"
}
Structured Outputsに対応したAPEXアプリケーションのエクスポートを以下に置きました。# prefix: openai
response_formats
format_name vc80 /nn
format_type vc20 /check text,json_object,json_schema
json_schema json
description vc4000
{
"name" : "math_reasoning",
"schema" :
{
"type" : "object",
"properties" :
{
"steps" :
{
"type" : "array",
"items" :
{
"type" : "object",
"properties" :
{
"explanation" :
{
"type" : "string"
},
"output" :
{
"type" : "string"
}
},
"required" :
[
"explanation",
"output"
],
"additionalProperties" : false
}
},
"final_answer" :
{
"type" : "string"
}
},
"required" :
[
"steps",
"final_answer"
],
"additionalProperties" : false
},
"strict" : true
}
To solve for x, we need to isolate the variable x on one side of the equation.
Here's our starting point:
8x + 7 = -23
Step 1: Subtract 7 from both sides of the equation to get rid of the constant term on the left-hand side.
This will give us a new equation with no constant terms on the left-hand side:
8x = -23 - 7
= -30
Now we have:
8x = -30
Step 2: Divide both sides of the equation by 8 to isolate x. This is called "inverse operations".
Dividing by 8 will cancel out the coefficient (the number multiplied by the variable) on the left-hand side.
(-30) ÷ 8 = ?
= -3.75
And that's our solution for x!
Now you know: x = -3.75
2024年10月28日月曜日
Microsoft AI Chat Protocolのクライアントを使ってブラウザよりローカルLLMを呼び出す
Oracle APEXのページにMicrosoft AI Chat Protocolのクライアントを読み込んで、ローカルLLMをブラウザから直接呼び出してみます。
作成したAPEXアプリケーションは以下のように動作します。
macOSのLM Studioに、モデルとしてmmnga/Llama-3-ELYZA-JP-8B-gguf/Llama-3-ELYZA-JP-8B-Q8_0.ggufをロードしてローカルLLM(ローカル・サーバー)を実行しています。
Oracle APEXのアプリケーションは別のホストよりロードしているため、localhostで動作しているLLMを呼び出そうとするとCORSのエラーが発生します。そのため、LM Studioの設定のCross-Origin-Resource-Sharing (CORS)をONにしています。
const response = await asStream(
this.client.path(`${this.basePath}/stream`).post(request),
);
var client; /* Microsoft AI Chat Protocolのクライアント */
var messages; /* 送信するメッセージの配列 */
const contentDiv = document.getElementById("content"); /* チャット履歴を表示する要素 */
/* 表示されたチャット履歴を初期化 */
function removeAllChildren(element) {
while (element.firstChild) {
element.removeChild(element.firstChild);
}
}
.bubble-left {
max-width: 70%; /* 吹き出しの幅 */
padding: 10px 15px; /* 内側の余白 */
margin: 10px 0; /* 吹き出しの上下の間隔 */
background-color: #e1f5fe; /* 吹き出しの背景色 */
text-align: left; /* 文字を左寄せ */
position: relative; /* 吹き出しの位置を相対的に */
border-radius: 15px 15px 15px 15px; /* 角を丸める */
}
.bubble-right {
max-width: 70%; /* 吹き出しの幅 */
padding: 10px 15px; /* 内側の余白 */
margin: 10px 0; /* 吹き出しの上下間隔 */
background-color: #c8e6c9; /* 吹き出しの背景色(薄い緑色) */
text-align: left; /* 文字は左寄せ */
position: relative; /* 吹き出しの位置を相対的に */
margin-left: auto; /* 吹き出しを右寄せ */
border-radius: 15px 15px 15px 15px; /* 角を丸める */
}
/* AI Chat Protocolのクライアントを作成する */
client = new ChatProtocol.AIChatProtocolClient(
"http://localhost:8080/v1/chat/completions",
{
"allowInsecureConnection": true
}
);
/* メッセージとチャット履歴を表示するDIV要素も初期化。 */
messages = [];
removeAllChildren(contentDiv);
2024年10月25日金曜日
マウス・エンターのイベントを拾ってレポートをリフレッシュする
const tre = this.triggeringElement;
const tde = tre.querySelector("span[data-deptno]");
const deptno = tde ? tde.dataset.deptno : null;
if ( deptno ) {
apex.item("P1_DEPTNO").setValue(deptno);
}
select sql_id, sql_text from v$sql where sql_text like '%CHECK_FOR_EXECUTIONS%';
クラシック・レポートが発行するSELECT文は、ページ送りなどを可能にするために、実際のソースであるSELECT文をインライン・ビューにしています。
SQL> select sql_id, sql_text from v$sql where sql_text like '%CHECK_FOR_EXECUTIONS%';
SQL_ID SQL_TEXT
________________ __________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________________
fykf2n6mxnw57 select /*+qb_name(apex$112_1)*/* from(select a.*,row_number()over(order by null)apx$rownum from(select i.* from (select "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" from(select /*+ qb_name(apex$inner) */d."EMPNO",d."ENAME",d."JOB",d."MGR",d."HIREDATE",d."SAL",d."COMM",d."DEPTNO" from(select x.* from "EMP" x where(deptno = :P1_DEPTNO /* CHECK_FOR_EXECUTIONS */ ) )d )i )i where 1=1 order by "EMPNO" asc nulls last )a )where apx$rownum<=:p$_max_rows
fykf2n6mxnw57 select /*+qb_name(apex$112_1)*/* from(select a.*,row_number()over(order by null)apx$rownum from(select i.* from (select "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" from(select /*+ qb_name(apex$inner) */d."EMPNO",d."ENAME",d."JOB",d."MGR",d."HIREDATE",d."SAL",d."COMM",d."DEPTNO" from(select x.* from "EMP" x where(deptno = :P1_DEPTNO /* CHECK_FOR_EXECUTIONS */ ) )d )i )i where 1=1 order by "EMPNO" asc nulls last )a )where apx$rownum<=:p$_max_rows
fykf2n6mxnw57 select /*+qb_name(apex$112_1)*/* from(select a.*,row_number()over(order by null)apx$rownum from(select i.* from (select "EMPNO","ENAME","JOB","MGR","HIREDATE","SAL","COMM","DEPTNO" from(select /*+ qb_name(apex$inner) */d."EMPNO",d."ENAME",d."JOB",d."MGR",d."HIREDATE",d."SAL",d."COMM",d."DEPTNO" from(select x.* from "EMP" x where(deptno = :P1_DEPTNO /* CHECK_FOR_EXECUTIONS */ ) )d )i )i where 1=1 order by "EMPNO" asc nulls last )a )where apx$rownum<=:p$_max_rows
g8b4vm8rxk618 select sql_id, sql_text from v$sql where sql_text like '%CHECK_FOR_EXECUTIONS%' and sql_text like '%P1_DEPTNO%'
2q370ccg7afva select --+qb_name(apex$4000_4500) no_merge(@apex$inner d) * from (select * from(select /*+ qb_name(apex$inner) */* from(select x.* from "EMP" x where(deptno = :P1_DEPTNO /* CHECK_FOR_EXECUTIONS */ ) )d )i )
d5yrrbtwtyquy select sql_id, sql_text from v$sql where sql_text like '%CHECK_FOR_EXECUTIONS%'
6行が選択されました。
SQL>
SQL> select executions, sql_id from v$sql where sql_id = 'fykf2n6mxnw57' and executions > 0;
EXECUTIONS SQL_ID
_____________ ________________
222 fykf2n6mxnw57
SQL>
Departmentsの列の上を3往復くらいしてみます。
SQL> /
EXECUTIONS SQL_ID
_____________ ________________
228 fykf2n6mxnw57
SQL>
SQL> /
EXECUTIONS SQL_ID
_____________ ________________
228 fykf2n6mxnw57
SQL>
SQL> /
EXECUTIONS SQL_ID
_____________ ________________
249 fykf2n6mxnw57
SQL>