using System; using System.Collections.Generic; using System.Text.RegularExpressions; using System.Threading; using System.Xml.Linq; using LinkToolAddin.client; using LinkToolAddin.client.prompt; using LinkToolAddin.host.llm; using LinkToolAddin.host.llm.entity; using LinkToolAddin.host.mcp; using LinkToolAddin.host.prompt; using LinkToolAddin.message; using ModelContextProtocol.Protocol.Types; using Newtonsoft.Json; namespace LinkToolAddin.host; public class Gateway { public static async void SendMessage(string message, string model, string gdbPath, Action callback) { Llm bailian = new Bailian { api_key = "sk-db177155677e438f832860e7f4da6afc" }; List messages = new List(); messages.Add(new Message { Role = "system", Content = SystemPrompt.SysPromptTemplate }); messages.Add(new Message { Role = "user", Content = message }); bool goOn = true; string pattern = "[\\s\\S]*?<\\/tool_use>"; string promptPattern = "[\\s\\S]*?<\\/prompt>"; Dictionary servers = new Dictionary(); while (goOn) { string reponse = await bailian.SendChatAsync(new LlmJsonContent() { Model = model, Messages = messages, Temperature = 0.7, TopP = 1, MaxTokens = 1000, }); messages.Add(new Message { Role = "assistant", Content = reponse }); if (Regex.IsMatch(reponse, pattern)) { //工具类型的消息 XElement toolUse = XElement.Parse(reponse); 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 = servers[serverName]; if (mcpServer is SseMcpServer) { SseMcpServer sseMcpServer = mcpServer as SseMcpServer; SseMcpClient client = new SseMcpClient(sseMcpServer.BaseUrl); CallToolResponse toolResponse = await client.CallToolAsync(toolName,toolParams); MessageListItem toolMessageItem = new ToolMessageItem { toolName = toolName, toolParams = toolParams, type = MessageType.TOOL_MESSAGE, status = toolResponse.IsError ? "fail" : "success", content = toolResponse.Content.ToString() }; messages.Add(new Message { Role = "user", Content = toolResponse.IsError ? SystemPrompt.ErrorPromptTemplate : SystemPrompt.ContinuePromptTemplate }); messages.Add(new Message { Role = "user", Content = JsonConvert.SerializeObject(toolResponse) }); callback?.Invoke(toolMessageItem); }else if (mcpServer is StdioMcpServer) { StdioMcpServer stdioMcpServer = mcpServer as StdioMcpServer; StdioMcpClient client = new StdioMcpClient(stdioMcpServer.Command, stdioMcpServer.Args); CallToolResponse toolResponse = await client.CallToolAsync(toolName,toolParams); MessageListItem toolMessageItem = new ToolMessageItem { toolName = toolName, toolParams = toolParams, type = MessageType.TOOL_MESSAGE, status = toolResponse.IsError ? "fail" : "success", content = toolResponse.Content.ToString() }; messages.Add(new Message { Role = "user", Content = toolResponse.IsError ? SystemPrompt.ErrorPromptTemplate : SystemPrompt.ContinuePromptTemplate }); messages.Add(new Message { Role = "user", Content = JsonConvert.SerializeObject(toolResponse) }); callback?.Invoke(toolMessageItem); } } else if (Regex.IsMatch(reponse, promptPattern)) { XElement prompt = XElement.Parse(reponse); string fullPromptName = prompt.Element("name")?.Value; string promptArgs = prompt.Element("arguments")?.Value; 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); messages.Add(new Message { Role = "user", Content = promptRes }); } else { MessageListItem chatMessageListItem = new ChatMessageItem() { content = reponse, role = "assistant", type = MessageType.CHAT_MESSAGE }; callback?.Invoke(chatMessageListItem); } if (reponse == "[DONE]") { goOn = false; } } } public static async void TestChatMessage(string message, string model, string gdbPath, Action callback) { MessageListItem chatListItem = new ChatMessageItem { content = message, role = "assistant", type = MessageType.CHAT_MESSAGE, id = "testmsg12345" }; callback?.Invoke(chatListItem); } public static async void TestToolMessage(string message, string model, string gdbPath, Action callback) { MessageListItem toolListItem = new ToolMessageItem { content = message, type = MessageType.TOOL_MESSAGE, toolName = "arcgis_pro.executeTool", toolParams = new Dictionary { {"gp_name","analysis.Buffer"}, {"gp_params","[\"C:\\test.gdb\\river\",\"30 Meters\"]"} }, id = "testtool123456", status = "success", role = "user", result = "成功创建缓冲区" }; callback?.Invoke(toolListItem); } public static async void TestWOrkflow(string message, string model, string gdbPath, Action callback) { Thread.Sleep(2000); MessageListItem chatListItem = new ChatMessageItem { content = message, role = "assistant", type = MessageType.CHAT_MESSAGE, id = "testid12345" }; callback?.Invoke(chatListItem); Thread.Sleep(1500); MessageListItem toolListItem = new ToolMessageItem { content = message, type = MessageType.TOOL_MESSAGE, toolName = "arcgis_pro.executeTool", toolParams = new Dictionary { {"gp_name","analysis.Buffer"}, {"gp_params","[\"C:\\test.gdb\\river\",\"30 Meters\"]"} }, id = "testtool123456", status = "success", role = "user", result = "成功创建缓冲区" }; callback?.Invoke(toolListItem); } }