工具
工具(Tools)是Chaite为LLM提供的Agent功能的核心组成部分。通过工具,LLM可以获取外部信息、执行特定操作,从而扩展其能力边界,实现更加强大和实用的功能。
工具的定义与编写
Section titled “工具的定义与编写”Chaite中的工具需要继承CustomTool
抽象类并实现相关方法。以下是编写和使用工具的基本步骤:
工具需要定义以下内容:
name
: 工具名称function
: 工具元数据,包含名称、描述和参数run
: 实际执行的方法
每个工具需要导出一个工具实例,而非类定义。
JavaScript示例
Section titled “JavaScript示例”import { CustomTool } from 'chaite'
class WeatherTool extends CustomTool { name = 'getWeather' function = { name: 'getWeather', description: 'Get the current weather in a given location', parameters: { type: 'object', properties: { location: { type: 'string', description: '城市或地区名称' }, unit: { type: 'string', enum: ['celsius', 'fahrenheit'], description: '温度单位,celsius或fahrenheit' } }, required: ['location'] } }
async run(args) { const { location, unit = 'celsius' } = args
try { // 这里是实际获取天气的逻辑 // 示例返回 return `${location}的天气: 晴天, 温度25°${unit === 'celsius' ? 'C' : 'F'}` } catch (e) { return `获取天气失败: ${e.message}` } }}
export default new WeatherTool()
import fetch from 'node-fetch'import { CustomTool } from 'chaite'
class SearchMusicTool extends CustomTool { name = 'searchMusic' function = { name: 'searchMusic', description: 'Useful when you want to search music by keyword.', parameters: { type: 'object', properties: { keyword: { type: 'string', description: '音乐的标题或关键词, 可以是歌曲名或歌曲名+歌手名的组合' } }, required: ['keyword'] } }
async run(args) { let { keyword } = args try { let result = await searchMusic163(keyword) return `search result: ${result}` } catch (e) { return `music search failed: ${e}` } }}
export async function searchMusic163(name) { let response = await fetch(`http://music.163.com/api/search/get/web?s=${name}&type=1&offset=0&total=true&limit=6`) let json = await response.json() if (json.result?.songCount > 0) { return json.result.songs.map(song => { return `id: ${song.id}, name: ${song.name}, artists: ${song.artists.map(a => a.name).join('&')}, alias: ${song.alias || 'none'}` }).join('\n') } return null}
export default new SearchMusicTool()
import { asyncLocalStorage, CustomTool } from 'chaite'
class SendMusicTool extends CustomTool { name = 'sendMusic' function = { name: 'sendMusic', description: 'Useful when you want to share music. You must use searchMusic first to get the music id.', parameters: { type: 'object', properties: { id: { type: 'string', description: '音乐的id' }, targetGroupIdOrQQNumber: { type: 'string', description: 'Fill in the target user_id or groupId when you need to send music to specific group or user, otherwise leave blank' } }, required: ['id'] } }
async run(args) { const context = (/** @type {AsyncLocalStorage<import('chaite').ChaiteContext>} **/asyncLocalStorage).getStore() const e = context.getEvent() let { id, targetGroupIdOrQQNumber } = args // 非法值则发送到当前群聊 const defaultTarget = e.isGroup ? e.group_id : e.sender.user_id const target = isNaN(targetGroupIdOrQQNumber) || !targetGroupIdOrQQNumber ? defaultTarget : parseInt(targetGroupIdOrQQNumber) === e.bot.uin ? defaultTarget : parseInt(targetGroupIdOrQQNumber) try { let group = await e.bot.pickGroup(target) // 检查是否支持 shareMusic 方法 if (typeof group.shareMusic === 'function') { await group.shareMusic('163', id) } else { // 构建音乐分享消息 const musicMsg = { type: 'music', data: { type: '163', id: id, jumpUrl: `https://music.163.com/#/song?id=${id}` } } await e.reply(musicMsg) } return `the music has been shared to ${target}` } catch (e) { return `music share failed: ${e}` } }}
export default new SendMusicTool()
在工具中,你可以通过asyncLocalStorage
获取当前上下文信息:
import { asyncLocalStorage, CustomTool } from 'chaite'
class MyTool extends CustomTool { // ...
async run(args) { // 获取上下文 const context = asyncLocalStorage.getStore() // 获取事件对象 const e = context.getEvent()
// 现在你可以访问事件信息 // 工具逻辑... }}
export default new MyTool()
编写完工具后,需要通过管理面板的工具管理页面添加才能使用。你可以将工具文件放在指定目录下,Chaite会自动加载它们。
- 明确的功能边界:每个工具应该有明确的功能
- 详细的描述:提供清晰的描述和参数说明,帮助LLM正确调用
- 健壮的错误处理:妥善处理可能出现的错误
- 合理的参数设计:使用适当的参数类型和必填项设置
- 工具组合管理:工具过多可能会影响AI的理解甚至造成冲突,建议通过配置不同的工具组,给不同的预设搭配不同的工具组。例如,为写作助手预设配置文本处理相关工具,为旅游顾问预设配置地图和天气相关工具,这样能更有针对性地增强AI能力,提高AI调用工具的精准度和效率。