使用ChatGPT构建一个AIML聊天机器人是什么体验

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

​ 使用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) 
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值