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

AI 関数

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

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

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

これらの関数はTypescriptで記述されたSquid Service内に定義されているため、Squidプラットフォームが持つ全ての機能にアクセスできます。つまり、これらの関数のカスタマイズには無限の可能性があるのです。

AI関数の作成方法

AI関数では description パラメータを受け取ります。これは関数を説明する文字列であり、AIエージェントが関数をいつ使用するかを判断するために用いられるため、明確かつ情報豊富であることが重要です。

以下の例は、AIエージェントが使用できる関数を定義するために @aiFunction デコレーターを使用している例です:

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エージェントに関数を追加するには、オプションパラメータの一部として ask の呼び出しと共に関数名を渡します:

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

バックエンドをデプロイした後、追加されたAI関数はコンソールの Abilities セクションに表示され、Agent Studio内でエージェントによって直接使用可能になります。詳細については Backend deployment guide を参照してください。

データベースを更新するためのAI関数の使用

また、AIエージェントにデータベースを更新する関数を提供することも可能です。例えば、以下の関数は組み込みのNoSQL Squidデータベース内の大きなドキュメントの特定のセクションを更新します:

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エージェントはどの値が有効であるかを理解できます。

追加の @aiFunction パラメータ

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

Attributes

Attributes を使用すると、この関数と連携させたい特定のintegration type(s)を定義できます。もし、PostgreSQLデータベースで動作するAI関数を作成したい場合、以下のようにデコレーターを定義できます:

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コネクタをエージェントに追加した際、この関数も自動的にそのエージェントに追加されます。

注意

integration typeに割り当てられた関数は、コネクタの追加によってエージェントに含まれるため、Studioのエージェント用 AI Functions リストには表示されません。

Categories

Categories を使用すると、AI関数をグループ化し、AI Agent Studioでの表示を目的として整理できます。例えば:

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」カテゴリの下に表示されます。複数のカテゴリを指定することも可能で、関数は各カテゴリごとに一度ずつ表示されます。

パラメータ値の上書き

エージェントによっては、全ての params の値をAIに決定させる方が合理的な場合もあります。しかし、他のエージェントでは、いくつかのパラメータを事前定義された値で上書きしたい場合もあります。この場合、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チャットウィジェット経由で 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 が渡されます。

コンテキストを介してAI関数にパラメータを渡す

また、 @aiFunction デコレーター内で定義した params に加え、2番目のパラメータであるコンテキストオブジェクト(例では ctx)を使用して、AI関数にパラメータ値を渡すことも可能です。これは AiFunctionCallContext となります。また、attributes フィールドを介してintegration typeに関連付けられている場合、AiFunctionCallContextWithIntegration となります。

params フィールドとこのコンテキストパラメータとの違いは、params に渡される値はAIエージェントによって提供される一方で、このコンテキストパラメータを使用して、AIとは独立して必要な他の値をプログラム的に渡すことができる点にあります。

主に2つのコンテキストフィールド、agentContextfunctionContext があります。それらの違いはスコープにあります:

  • agentContext は、特定のAIエージェントのために定義したコンテキストを含み、そのエージェントが行う全てのAI関数呼び出しに渡されます。このオブジェクトは ctx.agentContext にマッピングされます。
  • functionContext は、その特定の関数に渡すために定義したコンテキストを含みます。このオブジェクトは ctx.functionContext にマッピングされます。

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

例えば、前のサンプルを拡張すると、ハードコーディングされた "my-doc" のドキュメントIDに保存している点に注目してください。これを agentContext を使用してエージェントレベルで定義されたドキュメントIDに変更できます。さらに、データベース上のドキュメントに内部コードネームが表示されないようにしたい場合もあります。これら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;
}

これらのコンテキストパラメータは、Squidチャットウィジェット経由でエージェントに渡すこともできます:

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'] }
}]
});

次のステップ

より複雑なAI関数の実例を見てみたいですか?詳細は AI home maintenance tutorial をご覧ください。