fix: 修复 AI 工具调用的两个问题

问题1: AI 生成的参数格式与工具期望不一致
- 改进工具 description,添加 commit 操作的三元组格式说明和示例
- 完善 input_schema,详细描述 triplets 的 subject/relation/object 字段
- 在 description 中明确说明必填字段

问题2: 工具名称格式不符合 API 要求
- OpenAI/DeepSeek API 要求工具名称符合 ^[a-zA-Z0-9_-]+$
- 内部 ID "builtin:graph_memory" 含冒号,不符合要求
- 添加 apiName 属性提供 API 兼容名称 "graph_memory"
- 添加 mapToolIdToApiName/mapApiNameToToolId 映射函数

同时修正 import 路径:waterflow/... -> waterflow-ts/dist/...
This commit is contained in:
root
2026-04-17 13:08:18 +08:00
parent 16327dec72
commit 53d6940994
4 changed files with 89 additions and 33 deletions

View File

@ -1,5 +1,5 @@
import initSqlJs, { type Database as SqlJsDatabase } from 'sql.js';
import type { Platform } from 'waterflow/platform/types';
import type { Platform } from 'waterflow-ts/dist/platform/types.js';
import type { Entity, Relation, RecallParams, CommitParams, PurgeParams, RecallResult, CommitResult, PurgeResult, MemoryStats } from './types';
import { getConfig } from './config';
@ -16,7 +16,7 @@ export class GraphDatabase {
private async initDatabase(): Promise<void> {
const SQL = await initSqlJs();
const { getPlatform } = await import('waterflow/platform');
const { getPlatform } = await import('waterflow-ts/dist/platform/index.js');
this._platform = getPlatform();
try {

View File

@ -1,22 +1,73 @@
import type { Tool, ToolCategory, PermissionLevel, ToolInputSchema, ToolOutput, ToolInput, ToolExecutionContext } from 'waterflow/runtime/core/tools/tool_interface';
import type { Tool, ToolCategory, PermissionLevel, ToolInputSchema, ToolOutput, ToolInput, ToolExecutionContext } from 'waterflow-ts/dist/runtime/core/tools/tool_interface.js';
import { GraphDatabase } from '../../graph_memory/graph_database';
import { MemoryService } from '../../graph_memory/memory_service';
const GRAPH_MEMORY_TOOL_ID = 'builtin:graph_memory';
const GRAPH_MEMORY_TOOL_API_NAME = 'graph_memory'; // API 兼容名称(不含冒号,符合 ^[a-zA-Z0-9_-]+$ 要求)
/**
* 工具名称映射工具 - 用于处理 API 对工具名称格式的限制
* OpenAI/DeepSeek API 要求工具名称符合 ^[a-zA-Z0-9_-]+$ 正则表达式
* 而 TrulyMEM 的内部 ID 使用 "builtin:xxx" 格式(含冒号)
*/
/**
* 将内部工具 ID 映射为 API 兼容名称
* @param toolId 内部工具 ID如 "builtin:graph_memory"
* @returns API 兼容名称,如 "graph_memory"
*/
export function mapToolIdToApiName(toolId: string): string {
// 移除 "builtin:" 前缀
if (toolId.startsWith('builtin:')) {
return toolId.slice(8);
}
// 其他前缀也移除(如 "mcp:", "plugin:"
const colonIndex = toolId.indexOf(':');
if (colonIndex > 0) {
return toolId.slice(colonIndex + 1);
}
return toolId;
}
/**
* 将 API 返回的工具名称映射回内部 ID
* @param apiName API 返回的工具名称,如 "graph_memory"
* @param prefix 内部 ID 前缀,默认 "builtin:"
* @returns 内部工具 ID如 "builtin:graph_memory"
*/
export function mapApiNameToToolId(apiName: string, prefix = 'builtin:'): string {
// 如果已经是完整 ID 格式,直接返回
if (apiName.includes(':')) {
return apiName;
}
return `${prefix}${apiName}`;
}
const GRAPH_MEMORY_TOOL_DESCRIPTION = `图记忆工具 - 让 AI 拥有真正的长期记忆能力
操作:
- recall: 检索记忆
- commit: 写入记忆
- purge: 删除记忆
- introspect: 查看状态
- recall: 检索记忆 - 提供 queryIntent (搜索意图) 和可选的 seedEntities
- commit: 写入记忆 - 必须使用 triplets 数组格式,每个三元组包含 subject, relation, object
- purge: 删除记忆 - 提供 criteria 指定删除条件
- introspect: 查看状态 - 无参数
- persona_update/clear: 人设管理
- task_create/set_state/delete: 任务管理`;
- task_create/set_state/delete: 任务管理
【commit 操作的三元组格式】
triplets 必须是数组,每个元素是 {subject, relation, object, confidence} 格式:
示例: {"action":"commit","params":{"triplets":[{"subject":"Alice","relation":"is a","object":"engineer","confidence":0.95}]}}
- subject: 实体名称 (如用户名、技术名称)
- relation: 关系描述 (如 "is a", "likes", "knows")
- object: 目标实体 (如职业、爱好、技术)
- confidence: 置信度 0-1 (可选默认0.9)
【recall 操作】
示例: {"action":"recall","params":{"queryIntent":"用户的学习偏好","seedEntities":["Alice"]}}`;
export class GraphMemoryTool implements Tool {
readonly id = GRAPH_MEMORY_TOOL_ID;
readonly name = 'GraphMemory';
readonly apiName = GRAPH_MEMORY_TOOL_API_NAME;
readonly description = GRAPH_MEMORY_TOOL_DESCRIPTION;
readonly category: ToolCategory = 'analysis';
readonly permissionLevel: PermissionLevel = 'safe';
@ -44,17 +95,17 @@ export class GraphMemoryTool implements Tool {
sessionFilter: { type: 'string', description: '会话ID过滤' },
triplets: {
type: 'array',
description: '知识三元组数组。每个三元组描述 subject-relation-object 关系,用于存储记忆知识。',
items: {
type: 'object',
description: '三元组',
description: '三元组: {subject, relation, object, confidence} - subject/relation/object 必填',
properties: {
subject: { type: 'string', description: '主体' },
relation: { type: 'string', description: '关系' },
object: { type: 'string', description: '客体' },
confidence: { type: 'number', description: '置信度' }
subject: { type: 'string', description: '主体实体,如人名、技术名称等' },
relation: { type: 'string', description: '关系描述,如 "is a", "likes", "knows", "uses" 等' },
object: { type: 'string', description: '客体实体,如职业、爱好、技术名称等' },
confidence: { type: 'number', description: '置信度 (0-1),默认 0.9', default: 0.9 }
}
},
description: '三元组数组'
}
},
sessionId: { type: 'string', description: '会话ID' },
turnId: { type: 'number', description: '轮次ID' },

View File

@ -1,8 +1,9 @@
import type { Tool } from 'waterflow/runtime/core/tools/tool_interface';
import type { Platform } from 'waterflow/platform/types';
import { GraphMemoryTool, createGraphMemoryTool } from './graph_memory_tool';
import type { Tool } from 'waterflow-ts/dist/runtime/core/tools/tool_interface.js';
import type { Platform } from 'waterflow-ts/dist/platform/types.js';
import type { ToolRegistry } from 'waterflow-ts/dist/runtime/core/tools/tool_registry.js';
import { GraphMemoryTool, createGraphMemoryTool, mapToolIdToApiName, mapApiNameToToolId } from './graph_memory_tool';
export { GraphMemoryTool, createGraphMemoryTool };
export { GraphMemoryTool, createGraphMemoryTool, mapToolIdToApiName, mapApiNameToToolId };
export function registerGraphMemoryTool(
registry: { register: (tool: Tool) => void },
@ -11,8 +12,8 @@ export function registerGraphMemoryTool(
registry.register(createGraphMemoryTool(sessionId));
}
export async function installTrulyMEM(platform: Platform, sessionId?: string) {
const { initializeToolRegistry } = await import('waterflow/runtime/core/tools/builtin');
export async function installTrulyMEM(platform: Platform, sessionId?: string): Promise<ToolRegistry> {
const { initializeToolRegistry } = await import('waterflow-ts/dist/runtime/core/tools/builtin/index.js');
const registry = initializeToolRegistry(platform);
registerGraphMemoryTool(registry, sessionId);
return registry;

View File

@ -1,5 +1,5 @@
declare module 'waterflow/platform' {
import type { Platform, CreatePlatformOptions, PlatformCapabilities } from 'waterflow/platform/types';
import type { Platform, CreatePlatformOptions, PlatformCapabilities } from 'waterflow-ts/platform/types';
export function getPlatform(): Platform;
export function hasCapability(capability: keyof PlatformCapabilities): boolean;
export function initPlatform(options?: CreatePlatformOptions): Platform;
@ -259,6 +259,7 @@ declare module 'waterflow/platform/types' {
export interface Tool {
readonly id: string;
readonly name: string;
readonly apiName?: string;
readonly description: string;
readonly category: ToolCategory;
readonly inputSchema: ToolInputSchema;
@ -346,6 +347,7 @@ declare module 'waterflow/platform/types' {
export interface BuiltinTool {
readonly id: string;
readonly name: string;
readonly apiName?: string;
readonly description: string;
readonly category: ToolCategory;
readonly inputSchema: ToolInputSchema;
@ -355,13 +357,13 @@ declare module 'waterflow/platform/types' {
}
declare module 'waterflow/runtime/core/tools/tool_interface' {
import type { PlatformAbortController } from 'waterflow/platform/types';
import type { AgentId } from 'waterflow/shared/types/agent';
import type { WorkflowRunner } from 'waterflow/runtime/core/workflow/types';
import type { WorkflowRegistryImpl } from 'waterflow/runtime/core/workflow/workflow_registry';
import type { AgentRegistryImpl } from 'waterflow/runtime/core/workflow/agent_registry';
import type { AgentExecutor } from 'waterflow/runtime/core/agent/agent_executor';
import type { MCPClient } from 'waterflow/runtime/core/tools/mcp/mcp_client';
import type { PlatformAbortController } from 'waterflow-ts/platform/types';
import type { AgentId } from 'waterflow-ts/shared/types/agent';
import type { WorkflowRunner } from 'waterflow-ts/runtime/core/workflow/types';
import type { WorkflowRegistryImpl } from 'waterflow-ts/runtime/core/workflow/workflow_registry';
import type { AgentRegistryImpl } from 'waterflow-ts/runtime/core/workflow/agent_registry';
import type { AgentExecutor } from 'waterflow-ts/runtime/core/agent/agent_executor';
import type { MCPClient } from 'waterflow-ts/runtime/core/tools/mcp/mcp_client';
export type ToolCategory =
| 'file'
@ -403,6 +405,7 @@ declare module 'waterflow/runtime/core/tools/tool_interface' {
suggestedSource?: 'context' | 'literal' | 'file';
items?: SchemaProperty;
properties?: Record<string, SchemaProperty>;
required?: string[];
additionalProperties?: boolean | SchemaProperty;
}
@ -503,6 +506,7 @@ declare module 'waterflow/runtime/core/tools/tool_interface' {
export interface Tool {
readonly id: string;
readonly name: string;
readonly apiName?: string;
readonly description: string;
readonly category: ToolCategory;
readonly inputSchema: ToolInputSchema;
@ -564,9 +568,9 @@ declare module 'waterflow/runtime/core/tools/tool_interface' {
}
declare module 'waterflow/runtime/core/tools/builtin' {
import type { Platform } from 'waterflow/platform/types';
import type { Tool } from 'waterflow/runtime/core/tools/tool_interface';
import { ToolRegistry } from 'waterflow/runtime/core/tools/tool_registry';
import type { Platform } from 'waterflow-ts/platform/types';
import type { Tool } from 'waterflow-ts/runtime/core/tools/tool_interface';
import { ToolRegistry } from 'waterflow-ts/runtime/core/tools/tool_registry';
export const FRAMEWORK_TOOLS: Tool[];
export function initializeToolRegistry(platform: Platform): ToolRegistry;
@ -574,7 +578,7 @@ declare module 'waterflow/runtime/core/tools/builtin' {
}
declare module 'waterflow/runtime/core/tools/tool_registry' {
import type { Tool, ToolCategory, ToolInput } from 'waterflow/runtime/core/tools/tool_interface';
import type { Tool, ToolCategory, ToolInput } from 'waterflow-ts/runtime/core/tools/tool_interface';
export interface ValidationResult {
valid: boolean;