メインコンテンツまでスキップ

AI関数

AI関数は、カスタム機能によってAIエージェントを強化・拡張します

AI agents を設定する際、特定の質問には、指示だけでは設定しにくい特定の応答が必要になることがあります。たとえば、モデルが知らない業界固有の計算式がある場合です。または、データベースの更新など、特定のプロンプトに応じてエージェントにアクションを実行させたい場合もあるでしょう。

このような場合(および他の多くの場合)には、Squid の AI関数を使用できます。Squid Service の関数を @aiFunction デコレーターで拡張することで、エージェントをこれらの関数に接続でき、各エージェントが必要とする機能でカスタマイズできます。

これらの関数は Typescript の Squid Service で定義されるため、Squid プラットフォームの全機能を利用できます。つまり、これらの関数のカスタマイズは無限です。

AI関数の作り方

AI関数は description パラメータを受け取ります。これは関数を説明する文字列です。この説明をもとに AI agent がその関数をいつ使用するかを判断するため、明確で有益な内容にすることが重要です。

次の例では、@aiFunction デコレーターを使用して、AI agent が利用できる関数を定義しています。

Backend code
import { SquidService, aiFunction } from '@squidcloud/backend';

class AiService extends SquidService {
@aiFunction<{ shipName: string }>(
'This function returns the list of pirates in a ship. ' +
'Call this function whenever the user asks about the crew of a ship.',
[
{
name: 'shipName',
description: 'The name of the ship',
type: 'string',
required: true,
}
]
)
async listPiratesInAShip(params: { shipName: string }): Promise<string> {
const { shipName } = params;
if (shipName === 'Black Pearl') {
return 'Jack Sparrow';
}
else if (shipName === "Queen Anne's Revenge") {
return 'Black Beard';
}
return 'No ship found';
}
}

AI agent に関数を追加するには、ask の呼び出し時に options パラメータの一部として関数名を渡します。

const response = await squid
.ai()
.agent('AGENT_ID')
.ask('Which pirate was captain of the Black Pearl?', {
functions: ['listPiratesInAShip'],
});
Note

バックエンドをデプロイすると、追加した AI Functions はコンソールの Abilities セクションに表示され、Agent Studio 内のエージェントから直接利用できます。詳細は Backend deployment guide を参照してください。

AI Function を使ってデータベースを更新する

AI agents に、データベースを更新するための関数を提供することもできます。たとえば、次の関数は、組み込みの no-sql Squid database にある大きなドキュメントの特定セクションを更新します。

Backend code
// Assume we have the following section id definitions
export const SECTION_IDS = ['introduction', 'background', 'methodology', 'results', 'conclusion'] as const;
export type SectionId = typeof SECTION_IDS[number];

@aiFunction('Saves a section in a document', [
{
name: 'sectionId',
type: 'string',
description: 'Which section to update in the document',
required: true,
enum: [...SECTION_IDS],
},
{
name: 'content',
type: 'string',
description: 'The content of the section',
required: true,
},
])
async saveSection(
{
sectionId,
content,
}: {
sectionId: SectionId;
content: string;
},
): Promise<string> {

const docRef = this.squid.collection("documents").doc("my-doc");
await docRef.update({ [sectionId]: content });
return 'section saved: ' + sectionId;
}

ここでは、sectionId の取りうる値を制限するために enum も使用しています。これにより、AI agent はどの値が有効かを理解しやすくなります。

追加の @aiFunction パラメータ

説明(description)と入力パラメータに加えて、@aiFunctionattributescategories も受け取ります。

Attributes

Attributes を使うと、この関数と組み合わせたい特定の integration type を定義できます。PostgreSQL database と連携する AI Function を書きたい場合、次のようにデコレーターを定義できます。

Backend code
@aiFunction({
description: 'Retrieves recent orders for a customer from the PostgreSQL database',
params: [
{
name: 'customerEmail',
description: 'The email address of the customer',
type: 'string',
required: true,
}
],
attributes: {
integrationType: ['postgresql'],
},
})
async getCustomerOrders(
{ customerEmail }: { customerEmail: string },
{ integrationId }: AiFunctionCallContextWithIntegration,
): Promise<string> {
// Custom query logic.

// Squid provides "Query with AI" where the agent can write the query and execute it to
// accomplish a task, but if you want it to consistently query in a certain way, you can write
// an AI Function that you can instruct it to call instead.
}

この結果、PostgreSQL connector をエージェントに追加すると、この関数も自動的にそのエージェントへ追加されます。

Note

integration type に紐づけられた(attributed)関数は、connector の追加によってエージェントへの組み込みが処理されるため、Studio の該当エージェントの AI Functions リストには 表示されません

Categories

Categories を使うと、AI Agent Studio での閲覧を目的として、AI Functions をグルーピングできます。例:

Backend code
@aiFunction({
description: 'Get all new user reviews from the product listing on Amazon.',
params: [
{
name: 'productId',
description: 'The ID of the listing on Amazon, e.g. "B094D3JGLT" for the URL "https://www.amazon.com/dp/B094D3JGLT"',
type: 'string',
required: true,
},
{
name: 'cutoffDate',
description: 'The cutoff date. Only reviews newer than this date should be returned. Use ISO8601 format. Defaults to returning all reviews.',
type: 'string',
required: false,
}
],
categories: ['Data Gathering'],
})
async getProductReviews(
{ productId, cutoffDate }: { productId: string, cutoffDate?: string },
{ integrationId }: AiFunctionCallContextWithIntegration,
): Promise<string> {
// Your logic to gather the user reviews.
}

これにより、getProductReviewsAI Functions リストの「Data Gathering」カテゴリ配下に表示されます。複数のカテゴリを指定することもでき、その場合は各カテゴリ配下に 1 回ずつ(複数回)表示されます。

パラメータ値の上書き

エージェントによっては、AI にすべての params の値を決めさせるのが合理的な場合があります。一方で、事前に決めた値を使うために、一部のパラメータを上書きしたい場合もあります。この場合、AI は上書きされたパラメータの存在を知らず、その値を設定できません。

上書きは、optionsfunctions フィールドで行います。たとえば、先ほどの @aiFunction デコレーター例を再掲します。

Backend code
@aiFunction('Saves a section in a document', [
{
name: 'sectionId',
type: 'string',
description: 'Which section to update in the document',
required: true,
enum: [...SECTION_IDS],
},
{
name: 'content',
type: 'string',
description: 'The content of the section',
required: true,
},
])

たとえば、'introduction' セクション ID だけを更新する役割の別エージェントを作りたいとします。このとき、Squid chat widget から predefinedParameters を使って sectionId フィールドを上書きできます。

Client code
<squid-chat-widget
...
squid-ai-agent-chat-options={{
functions: [{
name: 'saveSection',
predefinedParameters: { sectionId: 'introduction' }
}]
}}
...
>
</squid-chat-widget>

または SDK 経由でも可能です。

Backend code
const result = await squid.ai().agent('my-agent').ask('Save that content.', {
functions: [{
name: 'saveSection',
predefinedParameters: { sectionId: 'introduction' }
}]
});

こうすると、AI ができるのは content パラメータに内容を与えることだけで、あなたの関数が受け取る sectionId は常に introduction になります。

context を介して AI Function にパラメータを渡す

@aiFunction デコレーター内で定義する params に加えて、第 2 引数の context オブジェクト(サンプルコードでは ctx)を使って、AI function にパラメータ値を渡すこともできます。これは AiFunctionCallContext です。また、attributes フィールドで integration type に関連付けられている場合は、AiFunctionCallContextWithIntegration になります。

これと前述の params フィールドの違いは、params に入る値は AI agent が提供するのに対し、この context パラメータでは、AI とは独立して、必要な別の値をプログラム側から渡せる点です。

主な context フィールドは agentContextfunctionContext の 2 つで、その違いはスコープにあります。

  • agentContext は、指定の AI agent 用に定義する context を含み、そのエージェントが行うすべての AI function 呼び出しに渡されます。このオブジェクトは ctx.agentContext に対応します。
  • functionContext は、その特定の関数に渡すために定義する context を含みます。このオブジェクトは ctx.functionContext に対応します。

関数が呼び出される際に追加情報を渡すために、これらを使用してください。

たとえば先ほどのサンプルでは、"my-doc" というドキュメント ID にハードコードして保存していました。代わりに、このドキュメント ID を agentContext によってエージェントレベルで定義できます。さらに、データベース側のドキュメントに社内コードネームが残らないように伏せ字にしたいとします。この 2 つの目的のために、documentIdcodenameList をどのように定義し利用するかを示します。

Backend code
// Assume we have the following section id definitions
export const SECTION_IDS = ['introduction', 'background', 'methodology', 'results', 'conclusion'] as const;
export type SectionId = typeof SECTION_IDS[number];

// Assume we defined agent context as the following
interface DocumentIdAgentContext {
/** The specific document in the database that the agent will modify. */
documentId: string;
}

// Assume we defined a function context as the following
interface DocumentFunctionContext {
/**
* Avoid leaking our internal codenames.
*
* If any of these strings are found in the input content, we will replace them with "REDACTED".
*/
codenameList: string[];
}

@aiFunction('Saves a section in a document', [
{
name: 'sectionId',
type: 'string',
description: 'Which section to update in the document',
required: true,
enum: [...SECTION_IDS],
},
{
name: 'content',
type: 'string',
description: 'The content of the section',
required: true,
},
])
async saveSection(
{
sectionId,
content,
}: {
sectionId: SectionId;
content: string;
},
ctx: AiFunctionCallContext<DocumentFunctionContext, DocumentIdAgentContext>,
): Promise<string> {
const docRef = this.squid.collection("documents").doc(ctx.agentContext.documentId);
let censoredContent = content;
for (const censorWord of ctx.functionContext.codenameList) {
censoredContent = censoredContent.replaceAll(censorWord, 'REDACTED');
}
await docRef.update({ [sectionId]: censoredContent });
return 'section saved: ' + sectionId;
}

これらの context パラメータは、Squid chat widget 経由でエージェントに渡せます。

Client code
<squid-chat-widget
...
squid-ai-agent-chat-options={{
agentContext: { documentId: "document_controlled_by_this_agent" },
functions: [{
name: 'saveSection',
context: { codenameList: ['LITANIA', 'LEOPARD'] }
}]
}}
...
>
</squid-chat-widget>

または SDK 経由でも可能です。

Backend code
const result = await squid.ai().agent('my-agent').ask('I want the "results" section to be "LITANIA has determined the answer to be 42".', {
agentContext: { documentId: "document_controlled_by_this_agent" },
functions: [{
name: 'saveSection',
context: { codenameList: ['LITANIA', 'LEOPARD'] }
}]
});

Next Steps

AI function のより複雑な動作例を見たいですか? AI home maintenance tutorial を参照してください。