「Big Front-end Private Kitchen」のWeChat公式アカウントをフォローし、パスワード[面接ガイド]を入力すると、フロントエンド面接の質問107ページを無料で受け取ることができます。
現在、人工知能は日々発展しており、大規模な言語モデルはますます強力になっています。AI ツールを活用して仕事を進めると、作業効率が大幅に向上します。数文字を入力して Tab キーを押すだけで、コードがインテリジェントに完成します。
コード補完に加えて、AI を利用して関数を自動化し、必要な JSON データを返すこともできます。
まず例を見てみましょう。
// index.ts
interface Height {
meters: number;
feet: number;
}
interface Mountain {
name: string;
height: Height;
}
// @ts-ignore
// @magic
async function getHighestMountain(): Promise<Mountain> {
// Return the highest mountain
}
(async () => {
console.log(await getHighestMountain());
})();
上記コードでは世界最高峰の情報を取得する非同期関数getHighestMountainを定義しており、その戻り値はMountainインターフェースで定義されたデータ構造となっています。関数内に特定の実装はありません。関数が何を行う必要があるかをコメントを通じて記述するだけです。
上記のコードをコンパイルして実行すると、コンソールに次の結果が出力されます。
{ name: 'Mount Everest', height: { meters: 8848, feet: 29029 } }
世界で一番高い山はエベレストで、ヒマラヤ山脈の主峰であり、標高8848.86メートルの世界最高峰です。
次に、getHighestMountain 関数の秘密を公開します。
getHighestMountain 非同期関数内で何が行われているかを理解するために、コンパイルされた JS コードを見てみましょう。
const { fetchCompletion } = require("@jumploops/magic");
// @ts-ignore
// @magic
function getHighestMountain() {
return __awaiter(this, void 0, void 0, function* () {
return yield fetchCompletion("{\n // Return the highest mountain\n}", {
schema: "{\"type\":\"object\",\"properties\":{\"name\":{\"type\":\"string\"},\"height\":{\"$ref\":\"#/definitions/Height\"}},\"required\":[\"height\",\"name\"],\"definitions\":{\"Height\":{\"type\":\"object\",\"properties\":{\"meters\":{\"type\":\"number\"},\"feet\":{\"type\":\"number\"}},\"required\":[\"feet\",\"meters\"]}},\"$schema\":\"http://json-schema.org/draft-07/schema#\"}"
});
});
}
上記のコードからわかるように、@jumploops/magic ライブラリの fetchCompletion 関数は getHighestMountain 関数内で呼び出されます。
この関数のパラメータから、前の TS 関数の関数アノテーションがわかり、また、スキーマ属性を含むオブジェクトもわかります。この属性の値は、Mountain インターフェイスに対応する JSON Schema オブジェクトです。
次に、@jumploops/magic ライブラリの fetchCompletion 関数の分析に焦点を当てます。この関数は fetchCompletion.ts ファイルで定義されており、その内部処理フローは 3 つのステップに分かれています。
-
Chat Completions API を組み立てる際のヒント。
-
Chat Completions API を呼び出して応答結果を取得します。
-
応答結果を解析し、JSON スキーマを使用して応答オブジェクトを検証します。
// fetchCompletion.ts
export async function fetchCompletion(
existingFunction: string,
{ schema }: { schema: any }) {
let completion;
// (1)
const prompt = `
You are a robotic assistant. Your only language is code. You only respond with valid JSON. Nothing but JSON.
For example, if you're planning to return:
{ "list": [ { "name": "Alice" }, { "name": "Bob" }, { "name": "Carol"}] }
Instead just return:
[ { "name": "Alice" }, { "name": "Bob" }, { "name": "Carol"}]
...
Prompt: ${existingFunction.replace('{', '')
.replace('}', '').replace('//', '').replace('\n', '')}
JSON Schema:
\`\`\`
${JSON.stringify(JSON.parse(schema), null, 2)}
\`\`\`
`;
// (2)
try {
completion = await openai.createChatCompletion({
model: process.env.OPENAI_MODEL ?
process.env.OPENAI_MODEL : 'gpt-3.5-turbo',
messages: [{ role: 'user', content: prompt }],
});
} catch (err) {
console.error(err);
return;
}
const response = JSON.parse(completion.data.choices[0].message.content);
// (3)
if (!validateAPIResponse(response, JSON.parse(schema))) {
throw new Error("Invalid JSON response from LLM");
}
return JSON.parse(completion.data.choices[0].message.content);
}
Prompt では、AI のロールを設定し、有効な JSON 形式を返すように AI がガイドできるようにいくつかのサンプルを準備しました。
Chat Completions API を呼び出して応答結果を取得し、openai ライブラリが提供する createChatCompletion API を直接使用します。
応答結果を解析した後、validateAPIResponse 関数が呼び出され、応答オブジェクトが検証されます。この関数の実装も比較的簡単です。ajv ライブラリは、JSON スキーマに基づいたオブジェクト検証を実装するために内部で使用されます。
export function validateAPIResponse(
apiResponse: any, schema: object): boolean {
const ajvInstance = new Ajv();
ajvFormats(ajvInstance);
const validate = ajvInstance.compile(schema);
const isValid = validate(apiResponse);
if (!isValid) {
console.log("Validation errors:", validate.errors);
}
return isValid;
}
次に、TS コードを fetchCompletion 関数を呼び出す JS コードにコンパイルする方法を分析したいと思います。
ttypescript ライブラリは @jumploops/magic によって内部的に使用され、tsconfig.json ファイルでカスタム コンバータを構成できるようにします。
トランスフォーマーの内部には、typescript によって提供される API があり、これを使用して AST を解析および操作し、必要なコードを生成します。変圧器内部の主な処理フローも 3 つのステップに分けることができます。
-
// @magicannotation; を含む AI 関数のソース コードをスキャンします。
-
AI関数の戻り値の型に応じて、対応するJSON Schemaオブジェクトを生成します。
-
AI関数本体から関数アノテーションを抽出し、fetchCompletion関数を呼び出すコードを生成します。
この記事の焦点は、TypeScript コンパイラによって生成された AST オブジェクトを解析して操作する方法ではありません。興味がある場合は、@jumploops/magic プロジェクトのtransformer.ts ファイルを読むことができます。AI 機能を実際に体験したい場合は、この記事の例にある package.json と tsconfig.json の構成を参照してください。
パッケージ.json
{
"name": "magic",
"scripts": {
"start": "ttsc && cross-env OPENAI_API_KEY=sk-*** node src/index.js"
},
"keywords": [],
"author": "",
"license": "ISC",
"devDependencies": {
"@jumploops/magic": "^0.0.6",
"cross-env": "^7.0.3",
"ts-patch": "^3.0.0",
"ttypescript": "^1.5.15",
"typescript": "4.8.2"
}
}
tsconfig.json ファイル
{
"compilerOptions": {
"target": "es2016",
"module": "commonjs",
"esModuleInterop": true,
"allowSyntheticDefaultImports": true,
"strict": true,
"skipLibCheck": true,
"plugins": [{ "transform": "@jumploops/magic" }]
},
"include": ["src/**/*.ts"],
"exclude": [ "node_modules"],
}
チャット完了 API は、常に有効な JSON オブジェクトを予期した形式で返すとは限らないため、実際には適切な例外処理ロジックを追加する必要があることに注意してください。
現在、@jumploops/magic ライブラリは単純な例のみを提供しており、関数パラメーターの設定はまだサポートしていません。この部分については、Marvin ライブラリの AI 関数に関するドキュメントを読むことができます。
大規模な言語モデルが要件に従って構造化データを制御可能に出力できるかどうか。そうすれば、いろいろなことができるようになります。
現在、多くのローコード プラットフォームまたは RPA (ロボティック プロセス オートメーション) プラットフォームは、対応する JSON スキーマ オブジェクトを取得できます。
@jumploops/magic のソリューションを使用すると、ローコード プラットフォームや RPA プラットフォームをよりスマートにすることができます。たとえば、フォーム ページをすばやく作成したり、さまざまなタスクを自然言語で投稿したりできます。
最後に、@jumploops/magic ライブラリの背後にある作業をまとめます。このライブラリは、TypeScript コンバータを使用して関数の戻り値の型を取得し、その型を JSON スキーマ オブジェクトに変換して、関数の本体を次のソース コードで置き換えます。 // @magic アノテーション付き関数。その後、チャット完了 API を呼び出し、JSON スキーマに対して応答を検証します。
今日の記事はこれで終わります。お役に立てば幸いです。