LangChainのJSONToolkitで、CloudFromationのJSONを読ませてみようとした覚書
JSONToolkitを使用してCloudFormationのJSONを読み込むために、JSONファイルを利用しました。読み込んだJSONファイルの内容を理解するために、JsonToolkitのサンプルコードをベースにしました。また、intermediateStepsを使用してデバッグしながら調整することもできました。ToolKitの処理の内部を確認するために、intermediateStepsの結果を表示していました。これにより、どのようなデータを渡すべきかがわかるかもしれません。
広告ここから
広告ここまで
目次
JSONToolkitともう少し格闘したくなったので、今度はCloudFormationのJSONを読ませてみました。
読ませてみたJSONファイル
AWSがGitHubに公開しているCloudFormationファイルを利用します。
LangChain経由で構成について聞いてみる
今回もJSONToolKitのサンプルコードをベースにします。JSONファイルを渡して、その内容が理解できるかを試してみました。
import { Hono } from "hono";
import * as fs from "fs";
import { OpenAI } from "langchain/llms/openai";
import { JsonSpec, JsonObject } from "langchain/tools";
import { JsonToolkit, createJsonAgent } from "langchain/agents";
import path from 'path';
export const jsonApp = new Hono()
jsonApp.get('load', async c => {
let data: JsonObject;
try {
const json = fs.readFileSync(path.join(__dirname, '../data/EC2-Domain-Join.json'), "utf8");
data = JSON.parse(json) as JsonObject;
if (!data) {
throw new Error("Failed to load OpenAPI spec");
}
} catch (e) {
console.error(e);
return;
}
const toolkit = new JsonToolkit(new JsonSpec(data));
const model = new OpenAI({
temperature: 0,
openAIApiKey: c.env.openaiApiKey
});
const executor = createJsonAgent(model, toolkit);
const input = `このCloudFormationでは、どんなインフラがデプロイされますか?`;
console.log(`Executing with input "${input}"...`);
const result = await executor.invoke({ input });
console.log(`Got output ${result.output}`);
console.log(
`Got intermediate steps ${JSON.stringify(
result.intermediateSteps,
null,
2
)}`
);
return c.json(result)
})
実行したところ、エラーが発生しました。。。
Got output Agent stopped due to max iterations.
Got intermediate steps [
{
"action": {
"tool": "json_list_keys",
"toolInput": "",
"log": "Action: json_list_keys\nAction Input: \"\""
},
"observation": "AWSTemplateFormatVersion, Description, Parameters, Resources"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources",
"log": " I should look at the Resources key to see what resources are being deployed.\nAction: json_list_keys\nAction Input: /Resources"
},
"observation": "myssmdocument, myEC2InstanceSSM, myInstanceProfile, myEC2SSMRole, InstanceSecurityGroup"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/~1myEC2InstanceSSM",
"log": " I should look at the myEC2InstanceSSM key to see what resources are being deployed.\nAction: json_list_keys\nAction Input: /Resources/~1myEC2InstanceSSM"
},
"observation": "Error: Value at /Resources/~1myEC2InstanceSSM is not a dictionary, get the value directly instead."
},
{
"action": {
"tool": "json_get_value",
"toolInput": "/Resources/~1myEC2InstanceSSM",
"log": " I should use the 'json_get_value' tool to see the value at the myEC2InstanceSSM key.\nAction: json_get_value\nAction Input: /Resources/~1myEC2InstanceSSM"
},
"observation": "Error: Value at /Resources/~1myEC2InstanceSSM is null or undefined."
},
パラメータについて聞いてみた
質問がToolkitに向いていなかったのかもしれないので、別の質問を投げてみました。
Executing with input "このCloudFormationは、どんなパラメータが必要ですか?"...
Got output: Active Directory Name. Eg. my.ad.com
「Active Directory Nameが必要」と回答がありましたが、実際のスタックに設定されている値はこのように複数あります。
"Parameters": {
"AMI": {
"Type": "String",
"Description" : "Windows 2016 AMI available in your region"
},
"KeyPair": {
"Type": "AWS::EC2::KeyPair::KeyName",
"Description" : "KeyPair for EC2 Instance"
},
"PublicSubnet": {
"Type": "AWS::EC2::Subnet::Id",
"Description" : "Subnet to place instance in"
},
"VPC": {
"Type": "AWS::EC2::VPC::Id",
"Description" : "VPC to place instance in"
},
"InstanceType": {
"Type": "String",
"Default": "t2.small",
"AllowedValues" : [ "t1.micro", "t2.micro", "t2.small", "t2.medium", "m1.small", "m1.medium", "m1.large", "m1.xlarge", "m2.xlarge", "m2.2xlarge", "m2.4xlarge", "m3.medium", "m3.large", "m3.xlarge", "m3.2xlarge", "c1.medium", "c1.xlarge", "c3.large", "c3.xlarge", "c3.2xlarge", "c3.4xlarge", "c3.8xlarge", "c4.large", "c4.xlarge", "c4.2xlarge", "c4.4xlarge", "c4.8xlarge", "g2.2xlarge", "r3.large", "r3.xlarge", "r3.2xlarge", "r3.4xlarge", "r3.8xlarge", "i2.xlarge", "i2.2xlarge", "i2.4xlarge", "i2.8xlarge", "d2.xlarge", "d2.2xlarge", "d2.4xlarge", "d2.8xlarge", "hi1.4xlarge", "hs1.8xlarge", "cr1.8xlarge", "cc2.8xlarge", "cg1.4xlarge"],
"ConstraintDescription" : "Must be a valid EC2 instance type."
},
"ADDirectoryId": {
"Type": "String",
"Description" : "Active DirectoryId. Eg. d-12345679a"
},
"ADDirectoryName": {
"Type": "String",
"Description" : "Active Directory Name. Eg. my.ad.com"
},
"ADDnsIpAddresses1": {
"Type": "String",
"Description" : "Active Directory DNS 1. Eg. 10.0.0.142"
},
"ADDnsIpAddresses2": {
"Type": "String",
"Description" : "Active Directory DNS 2. Eg. 10.0.0.143"
}
},
intermediaeSteps
でデバッグしながら調整するイメージかもしれない
Toolkitが色々と内部的に処理を入れている様子なので、invoke
の戻り値に含まれるintermediateSteps
を見ると、内部的にどんな処理が走っているかが見れます。
"intermediateSteps": [
{
"action": {
"tool": "json_list_keys",
"toolInput": "",
"log": "Action: json_list_keys\nAction Input: \"\""
},
"observation": "AWSTemplateFormatVersion, Description, Parameters, Resources"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Parameters",
"log": " I should look at the keys that exist under the Parameters key.\nAction: json_list_keys\nAction Input: /Parameters"
},
"observation": "AMI, KeyPair, PublicSubnet, VPC, InstanceType, ADDirectoryId, ADDirectoryName, ADDnsIpAddresses1, ADDnsIpAddresses2"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources",
"log": " I should look at the keys that exist under the Resources key.\nAction: json_list_keys\nAction Input: /Resources"
},
"observation": "myssmdocument, myEC2InstanceSSM, myInstanceProfile, myEC2SSMRole, InstanceSecurityGroup"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument",
"log": " I should look at the keys that exist under the myssmdocument key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument"
},
"observation": "Type, Properties"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties",
"log": " I should look at the keys that exist under the Properties key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties"
},
"observation": "Content"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content",
"log": " I should look at the keys that exist under the Content key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content"
},
"observation": "schemaVersion, description, parameters, runtimeConfig"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content/parameters",
"log": " I should look at the keys that exist under the parameters key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content/parameters"
},
"observation": "directoryId, directoryName, dnsIpAddresses"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content/runtimeConfig",
"log": " I should look at the keys that exist under the runtimeConfig key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content/runtimeConfig"
},
"observation": "aws:domainJoin"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin",
"log": " I should look at the keys that exist under the aws:domainJoin key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin"
},
"observation": "properties"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties",
"log": " I should look at the keys that exist under the properties key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties"
},
"observation": "directoryId, directoryName, dnsIpAddresses"
},
{
"action": {
"tool": "json_list_keys",
"toolInput": "/Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties/directoryId",
"log": " I should look at the keys that exist under the directoryId key.\nAction: json_list_keys\nAction Input: /Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties/directoryId"
},
"observation": "Error: Value at /Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties/directoryId is not a dictionary, get the value directly instead."
},
{
"action": {
"tool": "json_get_value",
"toolInput": "/Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties/directoryId",
"log": " I should use the 'json_get_value' tool to get the value at this path.\nAction: json_get_value\nAction Input: /Resources/myssmdocument/Properties/Content/runtimeConfig/aws:domainJoin/properties/directoryId"
},
"observation": "{{ directoryId }}"
}
]
このあたりのログを読み解いていくことで、どんなデータを渡すのが良いかなどが見えてくるかもしれません。