Expression の組み込み関数
Asgard の Expression には、対話履歴の扱い、データ変換、エンコードのための関数が 8 つ用意されています。
関数の一覧
対話履歴
history
指定した索引の範囲で対話履歴を返します。
構文:
history(start, end)
引数:
start(number): 開始位置。0 から始まり、負の値は末尾からの数え方ですend(number): 終了位置。その位置を含みます。負の値は末尾からの数え方です
戻り値:
string: 対話履歴のプレーンテキスト。1 行が 1 件の対話にあたります
例:
// 索引 0、1、2 の 3 件
history(0, 2)
// 末尾から 3 件
history(-3, -1)
// すべて
history(0, -1)
戻り値の形式:
bot: Hi, how can I help you?
user: Hello, I need assistance with my order.
bot: Okay, please provide your order number.
historySize
チャネルの対話履歴の件数を返します。
構文:
historySize()
戻り値:
number: 対話の件数
例:
// 数値を返します。たとえば 5
historySize()
データ処理
urlEncode
文字列を URL エンコードします。
構文:
urlEncode(val)
引数:
val(string): エンコードする文字列
戻り値:
string: エンコードした結果
例:
// "hello%20world"
urlEncode('hello world')
// "%E6%90%9C%E5%B0%8B%E9%97%9C%E9%8D%B5%E5%AD%97"
urlEncode('搜尋關鍵字')
// 直前のメッセージを URL エンコードする
urlEncode(prevMessage)
vecToStr
ベクトルの配列を文字列に変換します。
構文:
vecToStr(vector, prefix, suffix, delimiter)
引数:
vector(array<number>): ベクトルの配列prefix(string): 先頭の文字suffix(string): 末尾の文字delimiter(string): 区切り文字
戻り値:
string: 変換した文字列
例:
// "{1,2,3}"
vecToStr([1, 2, 3], '{', '}', ',')
// "[0.1|0.5|0.8]"
vecToStr([0.1, 0.5, 0.8], '[', ']', '|')
xpathExtract
XPath で XML 文書から値を取り出します。
構文:
xpathExtract(xml, path)
引数:
xml(string): XML 文書path(string): XPath のクエリ
戻り値:
string: 一致したすべての要素の内容を、改行で区切って返します
例:
const xml = '<root><item>1</item><item>2</item></root>'
// "1\n2"
xpathExtract(xml, '/root/item')
// すべての結果の見出しを取得する
xpathExtract(responseXml, '//result/title')
日付と時刻
isoNow
指定したタイムゾーンの現在の日時を RFC3339 形式の文字列で返します。
構文:
isoNow(timezone)
引数:
timezone(string): IANA のタイムゾーン名
戻り値:
string: RFC3339 形式の現在の日時
例:
// "2025-05-27T01:08:44+08:00"
isoNow('Asia/Taipei')
// "2025-05-26T17:08:44Z"
isoNow('UTC')
// "2025-05-26T13:08:44-04:00"
isoNow('America/New_York')
isoToday
指定したタイムゾーンの現在の日付を RFC3339 形式の文字列で返します。
構文:
isoToday(timezone)
引数:
timezone(string): IANA のタイムゾーン名
戻り値:
string: RFC3339 形式の現在の日付
例:
// "2025-05-27"
isoToday('Asia/Taipei')
// "2025-05-26"
isoToday('UTC')
// "2025-05-26"
isoToday('America/New_York')
応用例
対話の分析と要約
// 対話の傾向を見る
(() => {
const totalMessages = historySize();
if (totalMessages === 0) return '対話の記録がありません';
// 分析のために直近の対話を取得する
const recentCount = Math.min(10, totalMessages);
const recentHistory = history(-recentCount, -1);
const lines = recentHistory.split('\n');
const userMessages = lines.filter(line => line.startsWith('user:')).length;
const botMessages = lines.filter(line => line.startsWith('bot:')).length;
return `直近 ${recentCount} 件のうち、ユーザー ${userMessages} 件、ボット ${botMessages} 件`;
})()
API との連携
// 照会用の URL を組み立てる
(() => {
const keyword = prevMessage || '';
const encodedQuery = urlEncode(keyword);
const timestamp = isoNow('UTC');
// クエリ文字列を組み立てる
const params = [`q=${encodedQuery}`, `timestamp=${timestamp}`, `channel=${customChannelId || 'default'}`].join('&');
return `https://api.example.com/search?${params}`;
})()
XML の解析
// 複雑な XML の応答を扱う
(() => {
if (!xmlResponse) return 'XML データがありません';
try {
const titles = xpathExtract(xmlResponse, '//result/title');
const prices = xpathExtract(xmlResponse, '//result/price');
if (!titles) return '検索結果がありません';
const titleList = titles.split('\n');
const priceList = prices ? prices.split('\n') : [];
let result = '検索結果:\n';
titleList.forEach((title, index) => {
const price = priceList[index] || '価格不明';
result += `${index + 1}. ${title} - ${price}\n`;
});
return result;
} catch (e) {
return 'XML の解析エラー';
}
})()
ベクトルの扱い
// 複数の形式に整える
(() => {
const userVector = [0.1, 0.5, 0.8, 0.2];
const systemVector = [0.2, 0.4, 0.7, 0.3];
const formats = {
json: vecToStr(userVector, '[', ']', ','),
csv: vecToStr(userVector, '', '', ','),
sql: vecToStr(userVector, '(', ')', ','),
};
return `整形の結果:
JSON: ${formats.json}
CSV: ${formats.csv}
SQL: ${formats.sql}`;
})()
時刻付きのログ
// タイムスタンプ付きのログ行を作る
(() => {
const timezone = 'Asia/Taipei';
const now = isoNow(timezone);
const today = isoToday(timezone);
const messageCount = historySize();
const hasError = prevError ? true : false;
const logEntry = {
date: today,
timestamp: now,
messages: messageCount,
hasError: hasError,
channel: customChannelId || 'unknown',
};
return `[${now}] ログ: チャネル ${logEntry.channel}、${logEntry.messages} 件のメッセージ${hasError ? '、エラーあり' : ''}`;
})()
性能について
呼び出した値を持ち回す
// ✅ 再利用する値は変数に置き、同じ関数を何度も呼ばない
(() => {
const messageCount = historySize(); // 一度だけ呼ぶ
const timezone = 'Asia/Taipei';
const currentTime = isoNow(timezone); // 一度だけ呼ぶ
if (messageCount === 0) {
return `[${currentTime}] 新しい対話の開始`;
}
const recentHistory = messageCount > 5 ? history(-5, -1) : history(0, -1);
return `[${currentTime}] 対話の記録: ${messageCount} 件\n${recentHistory}`;
})()
条件付きで呼ぶ
// ✅ 不要な呼び出しを避ける
(() => {
// まず基本の条件を確認する
if (!prevMessage) return '処理するメッセージがありません';
// エンコードが必要なときだけ呼ぶ
const needsEncoding = /[^\w\s]/.test(prevMessage);
const processedMessage = needsEncoding ? urlEncode(prevMessage) : prevMessage;
return `処理結果: ${processedMessage}`;
})()
これらの関数により、Expression の中で対話の論理と形式変換に必要なデータ処理を行えます。