diff --git a/host/Gateway.cs b/host/Gateway.cs index 5b59879..a3e76a2 100644 --- a/host/Gateway.cs +++ b/host/Gateway.cs @@ -239,17 +239,25 @@ public class Gateway api_key = "sk-db177155677e438f832860e7f4da6afc" }; List messages = new List(); - string toolInfos = await GetToolInfos(new McpServerList()); - messages.Add(new Message + string toolInfos = ""; + try { - Role = "system", - Content = SystemPrompt.SysPrompt(gdbPath, toolInfos) - }); - messages.Add(new Message + toolInfos = await GetToolInfos(new McpServerList()); + messages.Add(new Message + { + Role = "system", + Content = SystemPrompt.SysPrompt(gdbPath, toolInfos) + }); + messages.Add(new Message + { + Role = "user", + Content = message + }); + }catch (Exception ex) { - Role = "user", - Content = message - }); + log.Error(ex); + MessageBox.Show(ex.Message,"获取MCP列表失败"); + } 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]*?)([\\s\\S]*?)<\\/arguments>([\\s\\S]*?)<\\/prompt>"; @@ -282,56 +290,106 @@ public class Gateway { //如果本次回复不包含任何工具的调用或提示词的调用,则不再请求 goOn = false; - MessageListItem endMessageListItem1 = new ChatMessageItem + MessageListItem endMessageListItem1 = new ChatMessageItem { type = MessageType.END_TAG, content = "", - id = (timestamp+3).ToString(), + id = (timestamp + 3).ToString(), role = "assistant" }; callback?.Invoke(endMessageListItem1); break; } - await foreach(LlmStreamChat llmStreamChat in bailian.SendChatStreamAsync(jsonContent)) - { - if (!goOn) - { - MessageListItem endMessageListItem2 = new ChatMessageItem - { - type = MessageType.END_TAG, - content = "", - id = (timestamp+3).ToString(), - role = "assistant" - }; - callback?.Invoke(endMessageListItem2); - break; - } - try + try + { + await foreach(LlmStreamChat llmStreamChat in bailian.SendChatStreamAsync(jsonContent)) { - string chunk = llmStreamChat.Choices[0].Delta.Content; - MessageListItem reasonMessageListItem = new ChatMessageItem() + if (!goOn) { - content = llmStreamChat.Choices[0].Delta.ResoningContent, - role = "assistant", - type = MessageType.REASON_MESSAGE, - id = (timestamp+2).ToString() - }; - Application.Current.Dispatcher.Invoke(() => - { - callback?.Invoke(reasonMessageListItem); - }); - messageContent = chunk; - var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern); - if (matched == "") - { - var (matchedPrompt, remainingPrompt) = ExtractMatchedPart(chunk, promptPattern); - if (matchedPrompt == "") + MessageListItem endMessageListItem2 = new ChatMessageItem { - //普通消息文本 + type = MessageType.END_TAG, + content = "", + id = (timestamp+3).ToString(), + role = "assistant" + }; + callback?.Invoke(endMessageListItem2); + break; + } + + try + { + string chunk = llmStreamChat.Choices[0].Delta.Content; + MessageListItem reasonMessageListItem = new ChatMessageItem() + { + content = llmStreamChat.Choices[0].Delta.ResoningContent, + role = "assistant", + type = MessageType.REASON_MESSAGE, + id = (timestamp+2).ToString() + }; + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(reasonMessageListItem); + }); + messageContent = chunk; + var (matched, remaining) = ExtractMatchedPart(chunk, toolPattern); + if (matched == "") + { + var (matchedPrompt, remainingPrompt) = ExtractMatchedPart(chunk, promptPattern); + if (matchedPrompt == "") + { + //普通消息文本 + MessageListItem chatMessageListItem = new ChatMessageItem() + { + content = remainingPrompt, + role = "assistant", + type = MessageType.CHAT_MESSAGE, + id = timestamp.ToString() + }; + Application.Current.Dispatcher.Invoke(() => + { + callback?.Invoke(chatMessageListItem); + }); + } + else + { + //包含Prompt调用请求的消息 + MessageListItem chatMessageListItem = new ChatMessageItem() + { + content = remainingPrompt, + role = "assistant", + type = MessageType.CHAT_MESSAGE, + id = timestamp.ToString() + }; + callback?.Invoke(chatMessageListItem); + XElement promptUse = XElement.Parse(matchedPrompt); + string promptKey = promptUse.Element("name")?.Value; + 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 + { + //包含工具调用请求的消息 + XElement toolUse = XElement.Parse(matched); + string fullToolName = toolUse.Element("name")?.Value; + string toolArgs = toolUse.Element("arguments")?.Value; + Dictionary toolParams = JsonConvert.DeserializeObject>(toolArgs); + string serverName = fullToolName.Contains(":") ? fullToolName.Split(':')[0] : fullToolName; + string toolName = fullToolName.Contains(":") ? fullToolName.Split(':')[1] : fullToolName; + McpServer mcpServer = mcpServerList.GetServer(serverName); + //将工具调用请求添加至列表中待一次回答完整后再统一进行调用 MessageListItem chatMessageListItem = new ChatMessageItem() { - content = remainingPrompt, + content = remaining, role = "assistant", type = MessageType.CHAT_MESSAGE, id = timestamp.ToString() @@ -340,84 +398,43 @@ public class Gateway { callback?.Invoke(chatMessageListItem); }); - } - else - { - //包含Prompt调用请求的消息 - MessageListItem chatMessageListItem = new ChatMessageItem() + MessageListItem toolMessageListItem = new ToolMessageItem() { - content = remainingPrompt, - role = "assistant", - type = MessageType.CHAT_MESSAGE, - id = timestamp.ToString() + content = "", + result = "", + toolName = toolName, + toolParams = toolParams, + role = "user", + type = MessageType.TOOL_MESSAGE, + id = (timestamp+1).ToString(), + status = "loading" }; - callback?.Invoke(chatMessageListItem); - XElement promptUse = XElement.Parse(matchedPrompt); - string promptKey = promptUse.Element("name")?.Value; - string promptArgs = promptUse.Element("arguments")?.Value; - Dictionary promptParams = JsonConvert.DeserializeObject>(promptArgs); - promptRequests = new List(); - promptRequests.Add(new PromptRequest() + Application.Current.Dispatcher.Invoke(() => { - PromptName = promptKey, - PromptArgs = promptParams, - PromptServer = promptServerList.GetPromptServer(promptKey) + callback?.Invoke(toolMessageListItem); }); + mcpToolRequests = new List(); + McpToolRequest mcpToolRequest = new McpToolRequest() + { + McpServer = mcpServer, + ToolName = toolName, + ToolArgs = toolParams, + }; + mcpToolRequests.Add(mcpToolRequest); } } - else + catch (Exception e) { - //包含工具调用请求的消息 - XElement toolUse = XElement.Parse(matched); - string fullToolName = toolUse.Element("name")?.Value; - string toolArgs = toolUse.Element("arguments")?.Value; - Dictionary toolParams = JsonConvert.DeserializeObject>(toolArgs); - string serverName = fullToolName.Contains(":") ? fullToolName.Split(':')[0] : fullToolName; - string toolName = fullToolName.Contains(":") ? fullToolName.Split(':')[1] : fullToolName; - McpServer mcpServer = mcpServerList.GetServer(serverName); - //将工具调用请求添加至列表中待一次回答完整后再统一进行调用 - MessageListItem chatMessageListItem = new ChatMessageItem() - { - content = remaining, - role = "assistant", - type = MessageType.CHAT_MESSAGE, - id = timestamp.ToString() - }; - Application.Current.Dispatcher.Invoke(() => - { - callback?.Invoke(chatMessageListItem); - }); - MessageListItem toolMessageListItem = new ToolMessageItem() - { - content = "", - result = "", - toolName = toolName, - toolParams = toolParams, - role = "user", - type = MessageType.TOOL_MESSAGE, - id = (timestamp+1).ToString(), - status = "loading" - }; - Application.Current.Dispatcher.Invoke(() => - { - callback?.Invoke(toolMessageListItem); - }); - mcpToolRequests = new List(); - McpToolRequest mcpToolRequest = new McpToolRequest() - { - McpServer = mcpServer, - ToolName = toolName, - ToolArgs = toolParams, - }; - mcpToolRequests.Add(mcpToolRequest); + Console.WriteLine(e); + log.Error(e.Message); } } - catch (Exception e) - { - Console.WriteLine(e); - log.Error(e.Message); - } + }catch (Exception e) + { + log.Error(e.Message); + MessageBox.Show(e.Message, "请求大模型出错"); } + if (messageContent != "") { messages.Add(new Message @@ -616,85 +633,97 @@ public class Gateway StringBuilder toolInfos = new StringBuilder(); foreach (McpServer mcpServer in mcpServerList.GetAllServers()) { - log.Info($"正在列出{mcpServer.Name}中的工具"); - if (mcpServer is InnerMcpServer) + try { - InnerMcpServer innerMcpServer = (InnerMcpServer)mcpServer; - Type type = Type.GetType("LinkToolAddin.client.tool." + innerMcpServer.Name); - MethodInfo[] methods = type.GetMethods(); - foreach (MethodInfo method in methods) + if (mcpServer is InnerMcpServer) { - if (method.IsPublic && method.IsStatic) + InnerMcpServer innerMcpServer = (InnerMcpServer)mcpServer; + Type type = Type.GetType("LinkToolAddin.client.tool." + innerMcpServer.Name); + MethodInfo[] methods = type.GetMethods(); + foreach (MethodInfo method in methods) { - string methodName = method.Name; - string methodDescription = method.GetCustomAttribute()?.Description; - string methodParamSchema = LinkToolAddin.common.JsonSchemaGenerator.GenerateJsonSchema(method); + if (method.IsPublic && method.IsStatic) + { + string methodName = method.Name; + string methodDescription = method.GetCustomAttribute()?.Description; + string methodParamSchema = LinkToolAddin.common.JsonSchemaGenerator.GenerateJsonSchema(method); + McpToolDefinition toolDefinition = new McpToolDefinition + { + Tool = new Tool + { + Name = innerMcpServer.Name + ":" + methodName, + Description = methodDescription, + Arguments = methodParamSchema + } + }; + XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)); + toolInfos.AppendLine(node.ToString()); + toolInfos.AppendLine(); + } + } + } + else if(mcpServer is SseMcpServer) + { + SseMcpClient client = new SseMcpClient((mcpServer as SseMcpServer).BaseUrl); + IList tools = await client.GetToolListAsync(); + foreach (McpClientTool tool in tools) + { + string toolName = (mcpServer as SseMcpServer).Name + ":" + tool.Name; + string toolDescription = tool.Description; + string toolParamSchema = tool.JsonSchema.ToString(); McpToolDefinition toolDefinition = new McpToolDefinition { Tool = new Tool { - Name = innerMcpServer.Name + ":" + methodName, - Description = methodDescription, - Arguments = methodParamSchema + Name = toolName, + Description = toolDescription, + Arguments = toolParamSchema } }; - XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)); - toolInfos.AppendLine(node.ToString()); + toolInfos.AppendLine(JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)).ToString()); + toolInfos.AppendLine(); + } + }else if (mcpServer is StdioMcpServer) + { + StdioMcpClient client = new StdioMcpClient((mcpServer as StdioMcpServer).Command, (mcpServer as StdioMcpServer).Args); + IList tools = await client.GetToolListAsync(); + foreach (McpClientTool tool in tools) + { + string toolName = (mcpServer as StdioMcpServer).Name + ":" + tool.Name;; + string toolDescription = tool.Description; + string toolParamSchema = tool.JsonSchema.ToString(); + McpToolDefinition toolDefinition = new McpToolDefinition + { + Tool = new Tool + { + Name = toolName, + Description = toolDescription, + Arguments = CompressJson(toolParamSchema) + } + }; + toolInfos.AppendLine(JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)).ToString()); toolInfos.AppendLine(); } } - } - else if(mcpServer is SseMcpServer) + }catch (Exception e) { - SseMcpClient client = new SseMcpClient((mcpServer as SseMcpServer).BaseUrl); - IList tools = await client.GetToolListAsync(); - foreach (McpClientTool tool in tools) - { - string toolName = (mcpServer as SseMcpServer).Name + ":" + tool.Name; - string toolDescription = tool.Description; - string toolParamSchema = tool.JsonSchema.ToString(); - McpToolDefinition toolDefinition = new McpToolDefinition - { - Tool = new Tool - { - Name = toolName, - Description = toolDescription, - Arguments = toolParamSchema - } - }; - toolInfos.AppendLine(JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)).ToString()); - toolInfos.AppendLine(); - } - }else if (mcpServer is StdioMcpServer) - { - StdioMcpClient client = new StdioMcpClient((mcpServer as StdioMcpServer).Command, (mcpServer as StdioMcpServer).Args); - IList tools = await client.GetToolListAsync(); - foreach (McpClientTool tool in tools) - { - string toolName = (mcpServer as StdioMcpServer).Name + ":" + tool.Name;; - string toolDescription = tool.Description; - string toolParamSchema = tool.JsonSchema.ToString(); - McpToolDefinition toolDefinition = new McpToolDefinition - { - Tool = new Tool - { - Name = toolName, - Description = toolDescription, - Arguments = CompressJson(toolParamSchema) - } - }; - toolInfos.AppendLine(JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(toolDefinition)).ToString()); - toolInfos.AppendLine(); - } + log.Error(e.Message); } } List prompts = DynamicPrompt.GetAllPrompts(); foreach (UserPrompt userPrompt in prompts) { - XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(new PromptDefinition(){UserPrompt = userPrompt})); - toolInfos.AppendLine(node.ToString()); - toolInfos.AppendLine(); + try + { + XNode node = JsonConvert.DeserializeXNode(JsonConvert.SerializeObject(new PromptDefinition(){UserPrompt = userPrompt})); + toolInfos.AppendLine(node.ToString()); + toolInfos.AppendLine(); + } + catch (Exception e) + { + log.Error(e.Message); + } } return toolInfos.ToString(); } diff --git a/host/McpServerList.cs b/host/McpServerList.cs index 0e062e2..b925a40 100644 --- a/host/McpServerList.cs +++ b/host/McpServerList.cs @@ -35,53 +35,53 @@ public class McpServerList Description = "可以调用进行查询知识库,获取相关参考信息。", IsActive = true }); - //servers.Add("filesystem", new StdioMcpServer() - //{ - // Name = "filesystem", - // Type = "stdio", - // Command = "npx", - // Args = new List() - // { - // "-y", - // "@modelcontextprotocol/server-filesystem", - // "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\TestData" - // } - //}); - //servers.Add("fetch", new StdioMcpServer() - //{ - // Name = "fetch", - // Type = "stdio", - // Command = "uvx", - // Args = new List() - // { - // "mcp-server-fetch" - // } - //}); - //servers.Add("bing-search", new StdioMcpServer() - //{ - // Name = "bing-search", - // Type = "stdio", - // Command = "npx", - // Args = new List() - // { - // "bing-cn-mcp" - // } - //}); - //servers.Add("mcp-python-interpreter", new StdioMcpServer() - //{ - // Name = "mcp-python-interpreter", - // Type = "stdio", - // Command = "uvx", - // Args = new List() - // { - // "--native-tls", - // "mcp-python-interpreter", - // "--dir", - // "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\TestData", - // "--python-path", - // "C:\\Program Files\\ArcGIS\\Pro\\bin\\Python\\envs\\custom\\python.exe" - // } - //}); + servers.Add("filesystem", new StdioMcpServer() + { + Name = "filesystem", + Type = "stdio", + Command = "npxh", + Args = new List() + { + "-y", + "@modelcontextprotocol/server-filesystem", + "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\TestData" + } + }); + servers.Add("fetch", new StdioMcpServer() + { + Name = "fetch", + Type = "stdio", + Command = "uvx", + Args = new List() + { + "mcp-server-fetch" + } + }); + servers.Add("bing-search", new StdioMcpServer() + { + Name = "bing-search", + Type = "stdio", + Command = "npx", + Args = new List() + { + "bing-cn-mcp" + } + }); + servers.Add("mcp-python-interpreter", new StdioMcpServer() + { + Name = "mcp-python-interpreter", + Type = "stdio", + Command = "uvx", + Args = new List() + { + "--native-tls", + "mcp-python-interpreter", + "--dir", + "D:\\01_Project\\20250305_LinkTool\\20250420_AiDemoProject\\TestData", + "--python-path", + "C:\\Program Files\\ArcGIS\\Pro\\bin\\Python\\envs\\custom\\python.exe" + } + }); } public McpServer GetServer(string name)