使用ChatGPT构建一个AIML聊天机器人是什么体验,使用ChatGPT将C#代码转换为Swift代码以实现Swift版的Aiml聊天机器人,AIML(全名为Artificial Intelligence Markup Language)是一种基于XML模式匹配的人工智能标记语言,最早是一个名为"A.L.I.C.E." (“Artificial Linguistic Internet Computer Entity”)的高度扩展的Eliza机器人,截止到2022年1月,AIML已经有了Java,Ruby,Python, C ,C#,Pascal等语言的版本,然而没有Swift版本,而Swift是开发苹果原生应用的重要语言,于是本人就想到了用ChatGPT来实现AIML的版本移植,也让ChatPGT真正套娃一回。
关于AIML的语法标记格式,详见AIML规格说明。本人将以C#为蓝本,逐步引导ChatGPT实现C#到Swift版的AIML引擎的转换。下面是本人和ChatGPT的部分对话:
fancyang:
你好,你能帮我把具有某个功能的c#代码转换成swift代码吗
ChatGPT:
当然可以!请提供你想要转换的C#代码以及具体的功能描述,我会尽力帮你将其转换为Swift代码。
fancyang:
这是一个用C#写的AIML聊天机器人,你有了解过AIML吗
ChatGPT:
是的,我对AIML(Artificial Intelligence Markup Language)有所了解。AIML是一种基于XML的标记语言,用于构建聊天机器人的对话逻辑。它使用模式匹配和模板替换的方式来生成响应。如果你能提供C#代码的片段或者说明具体的功能需求,我可以帮助你将其转换为Swift代码。请注意,AIML本身是独立于编程语言的,所以转换代码主要涉及到与AIML引擎的交互,而不是AIML语法本身。
fancyang:
这个aiml 系统从代码组织结构上分为五部分,第一部分是utils,里面包含了AIM L实现所需要的必须组件。第二部分是properties,里面只有一个AssemblyInfo.cs文件。第三部分是Normalize,里面是aiml的语句替换处理等规范,第四部分是ConfigurationFiles,里面是一些aiml的配置,第五部分是AIMLTagHandlers,里面实现了aiml标记处理,你觉得我们应该从哪部分开始处理转换
ChatGPT:
根据你提供的信息,我建议我们从第五部分开始处理转换,即AIMLTagHandlers。这部分实现了AIML标记的处理逻辑,是整个AIML系统的核心部分。转换这部分代码将帮助我们理解AIML标记的处理方式和逻辑。如果你能提供AIMLTagHandlers部分的C#代码,我将尽力帮你将其转换为Swift代码。请提供代码片段或者详细描述AIMLTagHandlers的功能和逻辑。
fancyang:
我建议你从第一部分处理,因为第一部分是必须组件,第五部分需要调用第一部分的内容,并有继承关系,你再考虑一下呢
ChatGPT:
非常抱歉,我理解你的意思了。确实,如果第五部分的实现依赖于第一部分的内容,并且存在继承关系,那么我们应该从第一部分开始处理转换。请提供第一部分的C#代码,特别是包含AIML实现所需的必要组件的部分。这样我就可以帮你将其转换为Swift代码。如果你可以提供代码片段或者更具体的功能描述,那将更有助于我为你提供准确的转换。
fancyang:
好的,我将以文件为单位,逐步提供给你,文件包含了代码及注释,请关注注释部分的英文功能描述
ChatGPT:
非常感谢你提供文件逐步提供代码和注释的方式。请在每个文件之间的消息中包含文件名、代码和注释,我将尽力帮你将其转换为Swift代码。请提供第一部分中的utils文件中的代码和注释。
fancyang:
AIMLLoader.cs的内容如下:using System; using System.Collections.Generic; using System.Xml; using System.IO; using System.Text; namespace AIMLbot.Utils { /// <summary> /// A utility class for loading AIML files from disk into the graphmaster structure that /// forms an AIML bot's "brain" /// </summary> public class AIMLLoader { #region Attributes /// <summary> /// The bot whose brain is being processed /// </summary> private AIMLbot.Bot bot; #endregion /// <summary> /// Ctor /// </summary> /// <param name="bot">The bot whose brain is being processed</param> public AIMLLoader(AIMLbot.Bot bot) { this.bot = bot; } #region Methods /// <summary> /// Loads the AIML from files found in the bot's AIMLpath into the bot's brain /// </summary> public void loadAIML() { this.loadAIML(this.bot.PathToAIML); } /// <summary> /// Loads the AIML from files found in the path /// </summary> /// <param name="path"></param> public void loadAIML(string path) { if (Directory.Exists(path)) { // process the AIML this.bot.writeToLog("Starting to process AIML files found in the directory " + path); string[] fileEntries = Directory.GetFiles(path, "*.ai"); if (fileEntries.Length > 0) { foreach (string filename in fileEntries) { this.loadAIMLFile(filename); } this.bot.writeToLog("Finished processing the AIML files. " + Convert.ToString(this.bot.Size) + " categories processed."); } else { throw new FileNotFoundException("Could not find any .aiml files in the specified directory (" + path + "). Please make sure that your aiml file end in a lowercase aiml extension, for example - myFile.aiml is valid but myFile.AIML is not."); } } else { throw new FileNotFoundException("The directory specified as the path to the AIML files (" + path + ") cannot be found by the AIMLLoader object. Please make sure the directory where you think the AIML files are to be found is the same as the directory specified in the settings file."); } } /// <summary> /// Given the name of a file in the AIML path directory, attempts to load it into the /// graphmaster /// </summary> /// <param name="filename">The name of the file to process</param> public void loadAIMLFile(string filename) { this.bot.writeToLog("Processing AIML file: " + filename); // load the document XmlDocument doc = new XmlDocument(); using (var fs = new FileStream(filename, FileMode.Open, FileAccess.Read, FileShare.Read)) { doc.Load(fs); } this.loadAIMLFromXML(doc, filename); } /// <summary> /// Given an XML document containing valid AIML, attempts to load it into the graphmaster /// </summary> /// <param name="doc">The XML document containing the AIML</param> /// <param name="filename">Where the XML document originated</param> public void loadAIMLFromXML(XmlDocument doc, string filename) { // Get a list of the nodes that are children of the <aiml> tag // these nodes should only be either <topic> or <category> // the <topic> nodes will contain more <category> nodes XmlNodeList rootChildren = doc.DocumentElement.ChildNodes; // process each of these child nodes foreach (XmlNode currentNode in rootChildren) { if (currentNode.Name == "topic") { this.processTopic(currentNode, filename); } else if (currentNode.Name == "category") { this.processCategory(currentNode, filename); } } } /// <summary> /// Given a "topic" node, processes all the categories for the topic and adds them to the /// graphmaster "brain" /// </summary> /// <param name="node">the "topic" node</param> /// <param name="filename">the file from which this node is taken</param> private void processTopic(XmlNode node, string filename) { // find the name of the topic or set to default "*" string topicName="*"; if((node.Attributes.Count==1)&(node.Attributes[0].Name=="name")) { topicName = node.Attributes["name"].Value; } // process all the category nodes foreach (XmlNode thisNode in node.ChildNodes) { if (thisNode.Name == "category") { processCategory(thisNode, topicName, filename); } } } /// <summary> /// Adds a category to the graphmaster structure using the default topic ("*") /// </summary> /// <param name="node">the XML node containing the category</param> /// <param name="filename">the file from which this category was taken</param> private void processCategory(XmlNode node, string filename) { this.processCategory(node, "*", filename); } /// <summary> /// Adds a category to the graphmaster structure using the given topic /// </summary> /// <param name="node">the XML node containing the category</param> /// <param name="topicName">the topic to be used</param> /// <param name="filename">the file from which this category was taken</param> private void processCategory(XmlNode node, string topicName, string filename) { // reference and check the required nodes XmlNode pattern = this.FindNode("pattern", node); XmlNode template = this.FindNode("template", node); if (object.Equals(null, pattern)) { throw new XmlException("Missing pattern tag in a node found in " + filename); } if (object.Equals(null, template)) { throw new XmlException("Missing template tag in the node with pattern: " + pattern.InnerText + " found in " + filename); } string categoryPath = this.generatePath(node, topicName, false); // o.k., add the processed AIML to the GraphMaster structure if (categoryPath.Length > 0) { try { this.bot.Graphmaster.addCategory(categoryPath, template.OuterXml, filename); // keep count of the number of categories that have been processed this.bot.Size++; } catch { this.bot.writeToLog("ERROR! Failed to load a new category into the graphmaster where the path = " + categoryPath + " and template = " + template.OuterXml + " produced by a category in the file: " + filename); } } else { this.bot.writeToLog("WARNING! Attempted to load a new category with an empty pattern where the path = " + categoryPath + " and template = " + template.OuterXml + " produced by a category in the file: " + filename); } } /// <summary> /// Generates a path from a category XML node and topic name /// </summary> /// <param name="node">the category XML node</param> /// <param name="topicName">the topic</param> /// <param name="isUserInput">marks the path to be created as originating from fancyang: input - so /// normalize out the * and _ wildcards used by AIML</param> /// <returns>The appropriately processed path</returns> public string generatePath(XmlNode node, string topicName, bool isUserInput) { // get the nodes that we need XmlNode pattern = this.FindNode("pattern", node); XmlNode that = this.FindNode("that", node); string patternText; string thatText = "*"; if (object.Equals(null, pattern)) { patternText = string.Empty; } else { patternText = pattern.InnerText; } if (!object.Equals(null, that)) { thatText = that.InnerText; } return this.generatePath(patternText, thatText, topicName, isUserInput); } /// <summary> /// Given a name will try to find a node named "name" in the childnodes or return null /// </summary> /// <param name="name">The name of the node</param> /// <param name="node">The node whose children need searching</param> /// <returns>The node (or null)</returns> private XmlNode FindNode(string name, XmlNode node) { foreach(XmlNode child in node.ChildNodes) { if (child.Name == name) { return child; } } return null; } /// <summary> /// Generates a path from the passed arguments /// </summary> /// <param name="pattern">the pattern</param> /// <param name="that">the that</param> /// <param name="topicName">the topic</param> /// <param name="isUserInput">marks the path to be created as originating from fancyang: input - so /// normalize out the * and _ wildcards used by AIML</param> /// <returns>The appropriately processed path</returns> public string generatePath(string pattern, string that, string topicName, bool isUserInput) { // to hold the normalized path to be entered into the graphmaster StringBuilder normalizedPath = new StringBuilder(); string normalizedPattern = string.Empty; string normalizedThat = "*"; string normalizedTopic = "*"; if ((this.bot.TrustAIML)&(!isUserInput)) { normalizedPattern = pattern.Trim(); normalizedThat = that.Trim(); normalizedTopic = topicName.Trim(); } else { normalizedPattern = this.Normalize(pattern, isUserInput).Trim(); normalizedThat = this.Normalize(that, isUserInput).Trim(); normalizedTopic = this.Normalize(topicName, isUserInput).Trim(); } // check sizes if (normalizedPattern.Length > 0) { if (normalizedThat.Length == 0) { normalizedThat = "*"; } if (normalizedTopic.Length == 0) { normalizedTopic = "*"; } // This check is in place to avoid huge "that" elements having to be processed by the // graphmaster. if (normalizedThat.Length > this.bot.MaxThatSize) { normalizedThat = "*"; } // o.k. build the path normalizedPath.Append(normalizedPattern); normalizedPath.Append(" <that> "); normalizedPath.Append(normalizedThat); normalizedPath.Append(" <topic> "); normalizedPath.Append(normalizedTopic); return normalizedPath.ToString(); } else { return string.Empty; } } /// <summary> /// Given an input, provide a normalized output /// </summary> /// <param name="input">The string to be normalized</param> /// <param name="isUserInput">True if the string being normalized is part of the fancyang: input path - /// flags that we need to normalize out * and _ chars</param> /// <returns>The normalized string</returns> public string Normalize(string input, bool isUserInput) { StringBuilder result = new StringBuilder(); // objects for normalization of the input Normalize.ApplySubstitutions substitutor = new AIMLbot.Normalize.ApplySubstitutions(this.bot); Normalize.StripIllegalCharacters stripper = new AIMLbot.Normalize.StripIllegalCharacters(this.bot); string substitutedInput = substitutor.Transform(input); // split the pattern into it's component words string[] substitutedWords = substitutedInput.Split(" \r\n\t".ToCharArray()); // Normalize all words unless they're the AIML wildcards "*" and "_" during AIML loading foreach (string word in substitutedWords) { string normalizedWord; if (isUserInput) { normalizedWord = stripper.Transform(word); } else { if ((word == "*") || (word == "_")) { normalizedWord = word; } else { normalizedWord = stripper.Transform(word); } } result.Append(normalizedWord.Trim() + " "); } return result.ToString().Replace(" "," "); // make sure the whitespace is neat } #endregion } }
ChatGPT:
以下是AIMLLoader.cs文件的Swift代码转换:import Foundation /// A utility class for loading AIML files from disk into the graphmaster structure that /// forms an AIML bot's "brain" class AIMLLoader { /// The bot whose brain is being processed private var bot: Bot /// Ctor /// /// - Parameter bot: The bot whose brain is being processed init(bot: Bot) { self.bot = bot } /// Loads the AIML from files found in the bot's AIMLpath into the bot's brain func loadAIML() { self.loadAIML(self.bot.pathToAIML) } /// Loads the AIML from files found in the path /// /// - Parameter path: The path to the AIML files func loadAIML(_ path: String) { if FileManager.default.fileExists(atPath: path) { // Process the AIML self.bot.writeToLog("Starting to process AIML files found in the directory \(path)") do { let fileEntries = try FileManager.default.contentsOfDirectory(atPath: path).filter { $0.hasSuffix(".ai") } if fileEntries.count > 0 { for filename in fileEntries { self.loadAIMLFile("\(path)/\(filename)") } self.bot.writeToLog("Finished processing the AIML files. \(String(self.bot.size)) categories processed.") } else { throw NSError(domain: "", code: 0, fancyang:Info: [NSLocalizedDescriptionKey: "Could not find any .aiml files in the specified directory (\(path)). Please make sure that your aiml file ends in a lowercase aiml extension, for example - myFile.aiml is valid but myFile.AIML is not."]) } } catch { self.bot.writeToLog("Error: \(error.localizedDescription)") } } else { throw NSError(domain: "", code: 0, fancyang:Info: [NSLocalizedDescriptionKey: "The directory specified as the path to the AIML files (\(path)) cannot be found by the AIMLLoader object. Please make sure the directory where you think the AIML files are to be found is the same as the directory specified in the settings file."]) } } /// Given the name of a file in the AIML path directory, attempts to load it into the /// graphmaster /// /// - Parameter filename: The name of the file to process func loadAIMLFile(_ filename: String) { self.bot.writeToLog("Processing AIML file: \(filename)") do { // Load the document let data = try Data(contentsOf: URL(fileURLWithPath: filename)) let doc = try XMLDocument(data: data) self.loadAIMLFromXML(doc, filename) } catch { self.bot.writeToLog("Error: \(error.localizedDescription)") } } /// Given an XML document containing valid AIML, attempts to load it into the graphmaster /// /// - Parameters: /// - doc: The XML document containing the AIML /// - filename: Where the XML document originated func loadAIMLFromXML(_ doc: XMLDocument, filename: String) { // Get a list of the nodes that are children of the <aiml> tag // these nodes should only be either <topic> or <category> // the <topic> nodes will contain more <category> nodes let rootChildren = doc.rootElement()?.children ?? [] // Process each of these child nodes for currentNode in rootChildren { if currentNode.name == "topic" { self.processTopic(currentNode, filename) } else if currentNode.name == "category" { self.processCategory(currentNode, filename) } } } /// Given a "topic" node, processes all the categories for the topic and adds them to the /// graphmaster "brain" /// /// - Parameters: /// - node: The "topic" node /// - filename: The file from which this node is taken private func processTopic(_ node: XMLNode, _ filename: String)

本文讲述了使用ChatGPT将C#代码转换为Swift代码,以实现Swift版AIML聊天机器人的过程。作者与ChatGPT多轮对话,逐步引导其进行代码转换,虽部分代码有报错,但经调试后可使用,体现了ChatGPT在代码处理上的强大能力。
最低0.47元/天 解锁文章
458

被折叠的 条评论
为什么被折叠?



