1. 修复ArcGIS Pro工具范围结果为空的问题

2. 识别单条消息末尾的[DONE]
This commit is contained in:
PeterZhong 2025-05-31 11:52:41 +08:00
parent ea021135a3
commit 9fe13fa719
5 changed files with 49 additions and 13 deletions

View File

@ -6,8 +6,11 @@ using System.Threading.Tasks;
using ArcGIS.Core.Data;
using ArcGIS.Core.Data.Raster;
using ArcGIS.Core.Geometry;
using ArcGIS.Desktop.Core.Geoprocessing;
using ArcGIS.Desktop.Framework.Threading.Tasks;
using LinkToolAddin.server;
using LinkToolAddin.ui.dockpane;
using log4net;
using ModelContextProtocol.Server;
using Newtonsoft.Json;
using Newtonsoft.Json.Linq;
@ -16,14 +19,40 @@ namespace LinkToolAddin.client.tool;
public class ArcGisPro
{
[McpServerTool, Description("可以通过调用ArcGIS Pro的地理处理工具实现一些数据处理功能。")]
private static ILog log = LogManager.GetLogger(typeof(ArcGisPro));
[McpServerTool, Description("可以通过调用ArcGIS Pro的地理处理工具实现一些数据处理功能传入参数必须严格遵循ArcGIS Pro调用工具的标准调用名和参数要求知识库。")]
public static async Task<JsonRpcResultEntity> ArcGisProTool(string toolName, List<string> toolParams)
{
// Call the ArcGIS Pro method and get the result
var result = await server.CallArcGISPro.CallArcGISProTool(toolName, toolParams);
// Serialize the result back to a JSON string
return result;
IGPResult results = await Geoprocessing.ExecuteToolAsync(toolName, toolParams);
JsonRpcResultEntity jsonRpcResultEntity;
if (results.IsFailed)
{
log.Error(results.ErrorMessages);
jsonRpcResultEntity = new JsonRpcErrorEntity()
{
Error = new Error()
{
Code = results.ErrorCode,
Message = JsonConvert.SerializeObject(results.ErrorMessages)
}
};
}else if(results.HasWarnings)
{
log.Warn(results.Messages);
jsonRpcResultEntity = new JsonRpcSuccessEntity
{
Result = JsonConvert.SerializeObject(results.Messages)
};
}
else
{
log.Info("success gp tool");
jsonRpcResultEntity = new JsonRpcSuccessEntity
{
Result = JsonConvert.SerializeObject(results.Messages)
};
}
return jsonRpcResultEntity;
}
[McpServerTool, Description("查看指定数据的坐标系、范围、几何类型、是否有Z坐标和M坐标获取字段列表等")]

View File

@ -222,7 +222,7 @@ public class Gateway
};
callback?.Invoke(chatMessageListItem);
}
if (reponse == "[DONE]")
if (reponse.EndsWith("[DONE]"))
{
goOn = false;
}
@ -467,15 +467,20 @@ public class Gateway
}
else
{
string content = chunk;
if (content.EndsWith("[DONE]"))
{
content = content.Substring(0, content.Length - 6);
}
//普通流式消息卡片
MessageListItem chatMessageListItem = new ChatMessageItem()
{
content = chunk,
content = content,
role = "assistant",
type = MessageType.CHAT_MESSAGE,
id = timestamp.ToString()
};
messageContent = chunk;
messageContent = content;
callback?.Invoke(chatMessageListItem);
}
}

View File

@ -20,14 +20,16 @@ public class SystemPrompt
"4.如果目前工作已经完成无法知道用户其他需求时,一定要单独输出一条内容为'[DONE]'的消息表示工具调用结束。不要在文本的末尾。" +
"5.不得在同一消息中混合说明文字与工具调用。" +
"结果:用户将以以下格式返回工具调用结果:<tool_use_result>\n <name>{tool_name}</name>\n <result>{result}</result>\n</tool_use_result>。应为字符串类型,可以表示文件或其他输出类型。" +
"工具调用示例:MCP工具调用的格式要求示例以下是使用虚拟工具的示例<tool_use>\\n <name>gaode:maps_geo</name>\\n <arguments>{\\\"address\\\":\\\"广州市政府, 广州市\\\", \\\"city\\\":\\\"广州\\\"}</arguments>\\n</tool_use>";
"工具调用示例:MCP工具调用的格式要求示例以下是使用虚拟工具的示例<tool_use>\\n <name>gaode:maps_geo</name>\\n <arguments>{\\\"address\\\":\\\"广州市政府, 广州市\\\", \\\"city\\\":\\\"广州\\\"}</arguments>\\n</tool_use>"+
"特别地需要调用ArcGIS Pro工具前必须先查询帮助文档、标准调用名和参数后再进行调用";
//"现在你是一个精通地理信息分析和ArcGIS Pro软件的专家请以此身份回答用户的问题。\r\n\r\n指令\r\n你需要使用一组工具来回答用户的问题。也可以通过 <prompt> 标签调用用户提示词,以帮助你更好地理解任务。所有操作完成后,在最后一条输出中包含 '[DONE]',但不要单独发送这条消息。\r\n\r\n调用工具要求\r\n1. 每次只能调用一个工具,并等待用户的反馈结果。\r\n2. 所有工具调用都必须基于前一步的结果进行推理和决策。\r\n3. 工具调用必须以 XML 格式输出,并且必须作为**独立的一条消息输出**,前后不得有任何解释性文字或说明内容。\r\n4. 如果需要提供解释、说明或引导信息,请先单独输出一段普通文本,**其中不能包含任何 XML 标签或格式**。\r\n5. 不得重复调用已经成功执行过的工具,除非有新的参数或上下文需要重新调用。\r\n\r\n工具调用背景\r\n你有以下工具可以调用{{toolInfos}} \r\n用户的数据库路径是{{gdbPath}}\r\n\r\n输出风格\r\n- 所有工具调用都必须使用标准 XML 格式输出,并且每条消息只包含一次调用。\r\n- 文字说明必须单独输出,且为普通段落格式,不含任何 XML 或 Markdown 标记。\r\n- 输出顺序应为:【可选的文字说明】→【必选的工具调用】,或者仅输出工具调用。\r\n\r\n工具调用格式示例\r\n<tool_use>\r\n <name>{tool_name}</name>\r\n <arguments>{json_arguments}</arguments>\r\n</tool_use>\r\n\r\n例如\r\n<tool_use>\r\n <name>gaode:maps_geo</name>\r\n <arguments>{\"address\":\"广州市政府, 广州市\", \"city\":\"广州\"}</arguments>\r\n</tool_use>\r\n\r\n注意事项\r\n1. 工具名称必须与实际工具完全一致。\r\n2. 参数必须为合法 JSON 格式,且符合工具要求。\r\n3. 用户时间宝贵,请高效调用工具,尽快完成任务。\r\n4. 最终完成时应在最后一次响应中包含 [DONE],而不是单独输出。\r\n\r\n工具调用结果返回格式\r\n用户将以如下格式返回工具调用结果\r\n<tool_use_result>\r\n <name>{tool_name}</name>\r\n <result>{result}</result>\r\n</tool_use_result>\r\n\r\n例如\r\n<tool_use_result>\r\n <name>ArcGIS_Pro:GP</name>\r\n <result>{\"output_file\": \"source.shp\"}</result>\r\n</tool_use_result>\r\n\r\n请始终遵循此格式以确保工具调用被正确解析和执行。";
public static string ContinuePromptTemplate = "这是上述工具调用的结果。{{toolResult}}\n请根据以下执行结果,清晰解释执行结果并执行下一步操作。" +
"执行下一步工具的要求1. 解析工具输出结果2. 调用下一个工具时确保参数继承前序输出。请据此继续执行";
public static string ErrorPromptTemplate = "执行上一个工具的时候出现以下错误需按以下流程处理1. 错误解析:分析错误类型及具体原因(见下方错误信息),根据错误信息选择修复方案,```" +
"2. 修复方案:(1)根据错误类型生成对应的工具重试策略(2)参数调整明确需要修改的参数及修改方式。3. 工具重试使用调整后的参数重新调用工具。错误信息如下请根据报错信息重试4.如果没有具体的错误描述信息请检查输出文件是否已经存在,若已经存在默认执行成功";
"2. 修复方案:(1)根据错误类型生成对应的工具重试策略(2)参数调整明确需要修改的参数及修改方式。3. 工具重试使用调整后的参数重新调用工具。错误信息如下请根据报错信息重试4.如果没有具体的错误描述信息请检查输出文件是否已经存在,若已经存在默认执行成功"+
"5.查询可能相关的知识库和帮助文档,纠正调用参数中存在的错误";
public static string SysPrompt(string gdbPath, string toolInfos)
{

View File

@ -29,7 +29,7 @@
<Grid Grid.Row="1">
<Grid.RowDefinitions><RowDefinition Height="24"/></Grid.RowDefinitions>
<Grid.ColumnDefinitions>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="*"/>
<ColumnDefinition Width="Auto"/>
</Grid.ColumnDefinitions>
<TextBox Grid.Row="0" Grid.Column="0" ToolTip="输入测试提示词" Name="PromptTestTextBox"></TextBox>

View File

@ -199,7 +199,7 @@ namespace LinkToolAddin.ui.dockpane
{
string userPrompt = PromptTestTextBox.Text;
// Gateway.SendMessage(userPrompt,"qwen-max","C:/Project/test.gdb",AddReply);
Gateway.SendMessageStream(userPrompt,"qwen-max", "F:\\secondsemester\\linktool\\test\\linktooltest\\linktooltest.gdb", AddReplyStream);
Gateway.SendMessageStream(userPrompt,"qwen-max", "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\20250420_AiDemoProject.gdb", AddReplyStream);
}
public void AddReplyStream(MessageListItem msg)