diff --git a/LinkToolAddin.csproj b/LinkToolAddin.csproj
index a4143cc..c53da32 100644
--- a/LinkToolAddin.csproj
+++ b/LinkToolAddin.csproj
@@ -98,7 +98,6 @@
-
diff --git a/client/prompt/DynamicPrompt.cs b/client/prompt/DynamicPrompt.cs
index 52d695c..c63c9fa 100644
--- a/client/prompt/DynamicPrompt.cs
+++ b/client/prompt/DynamicPrompt.cs
@@ -1,29 +1,41 @@
using System.Collections.Generic;
+using LinkToolAddin.host;
+using LinkToolAddin.host.prompt;
namespace LinkToolAddin.client.prompt;
public class DynamicPrompt
{
- public static string GetPrompt(string name,Dictionary args = null)
+ public static string GetPrompt(string name,Dictionary args = null)
{
- PromptTemplates promptTemplate = new PromptTemplates();
- string template = promptTemplate.GetPrompt(name);
+ PromptServerList promptServerList = new PromptServerList();
+ string template = promptServerList.GetPromptServer(name).Content;
if (args == null)
{
return template;
}
- foreach (KeyValuePair pair in args)
+ foreach (KeyValuePair pair in args)
{
string replaceKey = "{{"+pair.Key+"}}";
- template.Replace(replaceKey, pair.Value.ToString());
+ template = template.Replace(replaceKey, pair.Value.ToString());
}
return template;
}
- public static Dictionary GetAllPrompts()
+ public static List GetAllPrompts()
{
- PromptTemplates promptTemplate = new PromptTemplates();
- Dictionary template = promptTemplate.GetPromptsDict();
- return template;
+ PromptServerList promptServerList = new PromptServerList();
+ List prompts = new List();
+ Dictionary promptDefinitions = promptServerList.GetPromptsDict();
+ foreach (KeyValuePair pair in promptDefinitions)
+ {
+ prompts.Add(new UserPrompt()
+ {
+ Name = pair.Value.Name,
+ Description = pair.Value.Description,
+ Arguments = pair.Value.Arguments
+ });
+ }
+ return prompts;
}
}
\ No newline at end of file
diff --git a/client/prompt/PromptTemplates.cs b/client/prompt/PromptTemplates.cs
index 7e0e18f..6f9eaa1 100644
--- a/client/prompt/PromptTemplates.cs
+++ b/client/prompt/PromptTemplates.cs
@@ -1,4 +1,5 @@
using System.Collections.Generic;
+using LinkToolAddin.host.prompt;
namespace LinkToolAddin.client.prompt;
diff --git a/doc/TodoList.md b/doc/TodoList.md
new file mode 100644
index 0000000..fd0ae5a
--- /dev/null
+++ b/doc/TodoList.md
@@ -0,0 +1,15 @@
+# 待办事项
+
+本文档用于记录和跟踪当前阶段待办事项及完成进度
+
+## 核心程序
+
+- [ ] 提示词调用完整实现:以面向对象形式取代字典形式,加入参数和描述
+- [ ] 接入本地文件系统等基础性MCP服务
+- [ ] Python代码执行的实现
+- [ ] 适配qwen3、deepseek等推理模型并迁移
+- [ ] 工具执行错误消息合并为一条
+
+## 提示词工程
+
+## 前端交互
\ No newline at end of file
diff --git a/host/Gateway.cs b/host/Gateway.cs
index f59cea8..8eb71ad 100644
--- a/host/Gateway.cs
+++ b/host/Gateway.cs
@@ -204,7 +204,7 @@ public class Gateway
Dictionary promptParams = JsonConvert.DeserializeObject>(promptArgs);
string serverName = fullPromptName.Contains(":") ? fullPromptName.Split(':')[0] : fullPromptName;
string promptName = fullPromptName.Contains(":") ? fullPromptName.Split(':')[1] : fullPromptName;
- string promptRes = DynamicPrompt.GetPrompt(promptName, promptParams);
+ string promptRes = DynamicPrompt.GetPrompt(promptName, null);
messages.Add(new Message
{
Role = "user",
@@ -271,8 +271,9 @@ public class Gateway
});
goOn = true;
string toolPattern = "([\\s\\S]*?)([\\s\\S]*?)<\\/name>([\\s\\S]*?)([\\s\\S]*?)<\\/arguments>([\\s\\S]*?)<\\/tool_use>";
- string promptPattern = "([\\s\\S]*?)([\\s\\S]*?)<\\/name>([\\s\\S]*?)<\\/prompt>";
+ string promptPattern = "([\\s\\S]*?)([\\s\\S]*?)<\\/name>([\\s\\S]*?)([\\s\\S]*?)<\\/arguments>([\\s\\S]*?)<\\/prompt>";
McpServerList mcpServerList = new McpServerList();
+ PromptServerList promptServerList = new PromptServerList();
int loop = 0;
string messageContent = ""; //一次请求下完整的response
while (goOn)
@@ -293,7 +294,7 @@ public class Gateway
};
long timestamp = DateTimeOffset.UtcNow.ToUnixTimeMilliseconds();
List mcpToolRequests = new List();
- List promptKeys = new List();
+ List promptRequests = new List();
var (toolMatched, toolRemaining) = ExtractMatchedPart(messageContent, toolPattern);
var (promptMatched, promptRemaining) = ExtractMatchedPart(messageContent, promptPattern);
if (toolMatched == "" && promptMatched == "" && messageContent != "")
@@ -338,7 +339,15 @@ public class Gateway
callback?.Invoke(chatMessageListItem);
XElement promptUse = XElement.Parse(matchedPrompt);
string promptKey = promptUse.Element("name")?.Value;
- promptKeys.Add(promptKey);
+ string promptArgs = promptUse.Element("arguments")?.Value;
+ Dictionary promptParams = JsonConvert.DeserializeObject>(promptArgs);
+ promptRequests = new List();
+ promptRequests.Add(new PromptRequest()
+ {
+ PromptName = promptKey,
+ PromptArgs = promptParams,
+ PromptServer = promptServerList.GetPromptServer(promptKey)
+ });
}
}
else
@@ -489,9 +498,9 @@ public class Gateway
}
}
/*统一处理本次请求中的Prompt调用需求*/
- foreach (string promptKey in promptKeys)
+ foreach (PromptRequest promptRequest in promptRequests)
{
- string promptContent = DynamicPrompt.GetPrompt(promptKey);
+ string promptContent = DynamicPrompt.GetPrompt(promptRequest.PromptName, promptRequest.PromptArgs);
messages.Add(new Message
{
Role = "user",
@@ -503,7 +512,7 @@ public class Gateway
toolParams = null,
type = MessageType.TOOL_MESSAGE,
status = "success",
- content = "成功调用提示词:"+promptKey,
+ content = "成功调用提示词:"+promptRequest.PromptName,
id = (timestamp+1).ToString()
};
callback?.Invoke(toolMessageItem);
@@ -588,17 +597,10 @@ public class Gateway
}
}
- Dictionary prompts = DynamicPrompt.GetAllPrompts();
- foreach (KeyValuePair prompt in prompts)
+ List prompts = DynamicPrompt.GetAllPrompts();
+ foreach (UserPrompt userPrompt in prompts)
{
- McpPromptDefinition promptDefinition = new McpPromptDefinition
- {
- Prompt = new LinkToolAddin.host.mcp.Prompt
- {
- Name = prompt.Key
- }
- };
- XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(promptDefinition));
+ XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(new PromptDefinition(){UserPrompt = userPrompt}));
toolInfos.AppendLine(node.ToString());
toolInfos.AppendLine();
}
diff --git a/host/PromptServerList.cs b/host/PromptServerList.cs
new file mode 100644
index 0000000..e4a5cd5
--- /dev/null
+++ b/host/PromptServerList.cs
@@ -0,0 +1,40 @@
+using System.Collections.Generic;
+using LinkToolAddin.host.prompt;
+
+namespace LinkToolAddin.host;
+
+public class PromptServerList
+{
+ Dictionary promptServers = new Dictionary();
+
+ public PromptServerList()
+ {
+ promptServers.Add("plan", new PromptServer("plan",
+ "根据用户描述的问题推断出需要使用的ArcGIS Pro工具调用名称列表",
+ "请根据用户所提问题进行工具规划,输出格式为'1.工具2.工具’,如果是ArcGIS Pro的工具,根据用户的具体需求和提供的数据类型," +
+ "判断并列出所有必要的分析步骤和工具,同时严格遵守知识库中“ArcGIS Pro工具调用大全”里“工具调用名称”一列的工具命名规则(例如:analysis.Erase)," +
+ "确保工具名的准确无误,工具与所属工具箱的对应关系正确无误,严格遵循文档规定的格式和大小写。工具的组合顺序优先参考知识库中“ArcGIS Pro的帮助文档”。" +
+ "有一些与分析无关的数据能够进行排除,在选择工具时不受其干扰。"));
+ promptServers.Add("param", new PromptServer("param",
+ "填写ArcGIS Pro工具调用参数,生成规范的可执行的工具调用请求",
+ "根据帮助文档填写工具参数,请你根据“所需调用工具”,参照知识库“ArcGIS Pro工具调用大全”里工具所需的参数顺序进行陈列。" +
+ "列出所需调用工具的名称及其按照“ArcGIS Pro工具调用大全”里“的该工具所需的参数顺序陈列对应的参数。如果跳过了可选参数需要用空字符表示。" +
+ "不能更改所需调用工具的名称。例如:arcpy.analysis.Buffer,不能只写成Buffer。确保格式、参数的完整性和准确性,避免任何遗漏或错误。" +
+ "特别注意,所有参数均应视为字符串类型,即使它们可能代表数字或文件路径。例如问题为:使用地理处理中的\"擦除分析\"工具(Erase),将圆形要素(circle.shp)与方形要素(square.shp)进行空间叠加运算。" +
+ "输出: \"in_features\":\"circle.shp\",\r\n \"erase_features\":\"sqaure.shp\",\r\n \"out_feature_class\":\"res.shp\",\r\n \"cluster_tolerance\":\"1\""));
+ promptServers.Add("code", new PromptServer("code",
+ "生成可运行的arcpy代码",
+ "根据你在多种编程语言、框架、设计模式和最佳实践方面拥有的广泛知识。现在需要根据用户需求生成高质量的代码,并确保语法正确。" +
+ "编写Arcpy代码时必须符合ArcGIS官方文档要求。参考官方文档的方法参数,确保编写正确。"));
+ }
+
+ public Dictionary GetPromptsDict()
+ {
+ return promptServers;
+ }
+
+ public PromptServer GetPromptServer(string key)
+ {
+ return promptServers[key];
+ }
+}
\ No newline at end of file
diff --git a/host/prompt/PromptDefinition.cs b/host/prompt/PromptDefinition.cs
new file mode 100644
index 0000000..59f93fd
--- /dev/null
+++ b/host/prompt/PromptDefinition.cs
@@ -0,0 +1,9 @@
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.host.prompt;
+
+public class PromptDefinition
+{
+ [JsonProperty("prompt")]
+ public UserPrompt UserPrompt { get; set; }
+}
\ No newline at end of file
diff --git a/host/prompt/PromptRequest.cs b/host/prompt/PromptRequest.cs
new file mode 100644
index 0000000..ffbb966
--- /dev/null
+++ b/host/prompt/PromptRequest.cs
@@ -0,0 +1,10 @@
+using System.Collections.Generic;
+
+namespace LinkToolAddin.host.prompt;
+
+public class PromptRequest
+{
+ public PromptServer PromptServer { get; set; }
+ public string PromptName { get; set; }
+ public Dictionary PromptArgs { get; set; }
+}
\ No newline at end of file
diff --git a/host/prompt/PromptServer.cs b/host/prompt/PromptServer.cs
new file mode 100644
index 0000000..709c4a7
--- /dev/null
+++ b/host/prompt/PromptServer.cs
@@ -0,0 +1,32 @@
+using System.Text;
+using System.Text.RegularExpressions;
+
+namespace LinkToolAddin.host.prompt;
+
+public class PromptServer
+{
+ public string Name { get; set; }
+ public string Description { get; set; }
+ public string Arguments { get; set; }
+ public string Content { get; set; }
+
+ public PromptServer(string name, string description, string content)
+ {
+ Name = name;
+ Description = description;
+ Content = content;
+ string pattern = "{{([\\s\\S]*?)}}";
+ var matches = Regex.Matches(content, pattern);
+ StringBuilder args = new StringBuilder();
+ foreach (var match in matches)
+ {
+ string variableName = match.ToString().Replace("{{","").Replace("}}","");
+ string arg = "{ \"" + variableName + "\" : \"type\" : \" string \" }";
+ args.Append(arg);
+ }
+ if (args.ToString() != string.Empty)
+ {
+ Arguments = "{\"type\":\"object\",\"properties\":" + args.ToString() + "}";
+ }
+ }
+}
\ No newline at end of file
diff --git a/host/prompt/UserPrompt.cs b/host/prompt/UserPrompt.cs
index 128de5b..00c1cd8 100644
--- a/host/prompt/UserPrompt.cs
+++ b/host/prompt/UserPrompt.cs
@@ -1,6 +1,13 @@
-namespace LinkToolAddin.host.prompt;
+using Newtonsoft.Json;
+
+namespace LinkToolAddin.host.prompt;
public class UserPrompt
{
-
+ [JsonProperty("name")]
+ public string Name { get; set; }
+ [JsonProperty("description")]
+ public string Description { get; set; }
+ [JsonProperty("arguments")]
+ public string Arguments { get; set; }
}
\ No newline at end of file