65.9K
CodeProject 正在变化。 阅读更多。
Home

F# 语言的 Eliza 式聊天机器人,供娱乐

starIconstarIconstarIconstarIcon
emptyStarIcon
starIcon

4.33/5 (2投票s)

2010年7月8日

CPOL

4分钟阅读

viewsIcon

33675

downloadIcon

530

Eliza 聊天机器人(用 F# 编写,用于学习函数式编程语言,随 Visual Studio 2010 一起提供)。

Sample chat bot applicaction.

引言

这是一个非常简单的 Eliza 式聊天机器人。我称之为 Meliza Sharp。我编写它是为了好玩,同时学习 Visual Studio 2010 附带的 F# 语言。市面上有一些用 LISP 编写的非常好的 Eliza 聊天机器人实现,如果你想自己做一个聊天机器人,可以搜索一下。

Meliza 思考代码

Meliza 算法基于规则和模式匹配。这是 F# 的强大功能之一。

以下函数定义了模式标识符:WishPositiveNegativeNone,以及 input 字符串何时会匹配这些模式标识符。

如果 input 字符串与 "want""desire""need" 匹配,则 input 将匹配 Wish 模式标识符。

如果 input 字符串与 "certainly""yes""ok""right" 匹配,则 input 将匹配 Positive 模式标识符。其余模式标识符以此类推。

这就是 F# 开发者所说的“主动识别器”。主动识别器充当一种判别器,将输入分成不同的类别,在这种情况下,分成不同的“对话主题”。

// Define an active recognizer for keywords
// that express desire, positive and negative statements.
let (|Wish|Positive|Negative|None|) input =
    match input with
        | "want" | "desire" | "need"
                -> Wish
        | "certainly" | "yes" | "true" | "ok" | "right"
                -> Positive
        | "not" | "no" | "don't" | "false" | "wrong"
                -> Negative
        | _ -> None

在这个另一个函数中,异常处理 try ... with 结构充当一个条件。只有当转换 Convert.ToDouble(input) 成功时,才可能匹配 input 字符串和 Number 模式标识符。

// Define an active recognizer for numbers
// If the conversion suceeds it is a Number
// else it is None
let (|Number|None|) (input:string) =
    try let value = Convert.ToDouble(input) 
        Number
    with 
       | _ -> None

一旦定义了所有我们希望用于匹配字符串标记的主动识别器,我们就创建递归的 response 函数,该函数将字符串的第一个 token 和其余部分作为参数。

我们搜索 token 与上述主动识别器是否匹配。也就是说,我们找出 token falls into 哪个已定义的类别或“主题”。

如果我们发现 token 属于预定义的类别之一,则通过调用相应的响应函数来返回该类别的响应。这将结束递归过程。

如果与 | None when (str.IndexOf(" ") > 0) 匹配,我们则递归地将下一个 token 和字符串的其余部分传递给 response 函数。也就是说,我们还没有找到当前 token 的类别,并且字符串中还有更多的 token,因此我们使用下一个 token 和剩余的字符串 str 调用 response 函数,以进行递归处理。

如果与 | None when (str.IndexOf(" ") < 0) 匹配,也就是说,我们还没有找到当前 token 的类别,并且字符串中没有更多的 token 了,我们使用下一个 token 和空字符串的其余部分调用 response 函数。

when 语句设置了一个守卫或条件,以限制 tokenNone 匹配的可能性。

// main recursive response function
// find the first match with a key token
// and return a response acordingly 
let rec response (token: string) (str: string) =
   match token with
     | Hello
            -> hello_response ()
     | Bye
            -> good_bye_response ()
     | Personal
            -> personal_response str
     | Question
            -> question_response str
     | Answer
            -> answer_response str
     | Wish 
            -> wish_response str
     | Negative 
            -> negative_response str
     | Positive 
            -> positive_response str
     | Math
            -> math_response str
     | "" 
            -> none_response str
     | None when (str.IndexOf(" ") > 0) 
            -> response (str.Substring(0,str.IndexOf(" "))) 
                        (str.Substring(str.IndexOf(" ")+1))
     | None when (str.IndexOf(" ") < 0) 
            -> response str ""
     | None 
            -> math_response str

最后,我们创建一组函数,这些函数会随机选择响应,这些响应基于 response 函数和主动模式所识别的“主题”。

这里有两个例子

// Select possible responses based on random number for hello 'subject'
let hello_response () =
    let n = rand.Next(10) 
    match n with
        | 0 -> "How do you do."
        | 1 -> "Is nice talking to you."
        | 2 -> "Tell me something new."
        | 3 -> "Nice to meet you."
        | 4 -> "My pleasure."
        | 5 -> "Hi."
        | 6 -> "Hello."
        | 7 -> "Good day."
        | 8 -> "Salutation!"
        | 9 -> "Welcome!"

// Select possible responses based on random number for Good bye 'subject'
let good_bye_response () =
    let n = rand.Next(10) 
    match n with
        | 0 -> "Talk to you soon."
        | 1 -> "It was nice talking to you."
        | 2 -> "Good bye."
        | 3 -> "Stay a bit longer."
        | 4 -> "Adios amigo."
        | 5 -> "Bye."
        | 6 -> "Adios."
        | 7 -> "See you."
        | 8 -> "Please don't go"
        | 9 -> "Why are you leaving me alone?"

如何创建 Visual F# 应用程序和 Windows 窗体

  1. 文件 -> 新建 -> 项目

    创建新的 Eliza Visual F# 应用程序。

添加 Windows 组件引用

  1. 在解决方案资源管理器中,右键单击“引用” -> “添加引用...”
  2. 单击“.NET”选项卡,然后从列表中选择 System.DrawingSystem.Windows.Form
  3. 单击“确定”按钮。

设计窗体

Visual Studio 中没有 F# 的窗体设计器,所以我建议使用其他 .NET 语言(如 VB.NET)的设计器。

  1. 关闭解决方案,或打开另一个 Visual Studio 实例。
  2. 文件 -> 新建 -> 项目

    创建一个新的临时 Visual Basic Windows 窗体应用程序。

  3. 从工具箱将一个 TextBox 拖到窗体上。
  4. 在窗体上右键单击 TextBox -> “属性”。
  5. Name 属性设置为 text_box
  6. Dock 属性设置为 Bottom
  7. 将另一个 TextBox 从工具箱拖到窗体上。
  8. 在窗体上右键单击 TextBox -> “属性”。
  9. Name 属性设置为 conversation_box
  10. Dock 属性设置为 Fill
  11. Multiline 属性设置为 True
  12. 保存临时项目。

将代码翻译成 F#

  1. 打开 Eliza 项目。
  2. 转到“文件”->“打开”->“文件...”
  3. 浏览到项目文件夹,临时项目,打开 Form1.Designer.vb 文件。
  4. 浏览到 Private Sub InitializeComponent();在 Form1.Designer.vb 中,有我们必须为窗体设置的属性。

添加创建窗体的代码

// Create a main form, you can create a form using
// the form designer, in another language like Vb .Net
// then open the file Form1.Designer.vb and voila!
// there is the code you can translate into F#
let main_form title =
  // text box
  let text_box = new TextBox()
  text_box.Dock <- DockStyle.Bottom 
  // conversation box
  let conversation_text = new TextBox()
  conversation_text.Dock <- DockStyle.Fill
  conversation_text.Multiline <- true
  conversation_text.WordWrap <- false
  conversation_text.Font <- new Font(string("Arial"),float32(10))
  conversation_text.ReadOnly <- true
  // main form
  let form = new Form(Text=title, Visible=true)
  form.Size <- new Size(512, 512)
  form.Controls.Add(conversation_text)
  form.Controls.Add(text_box)
  // Message handler for Key Down event
  text_box.KeyDown.Add(enter_message text_box conversation_text)
  //
  let gotfocus = text_box.Focus()
  //
  form.KeyDown.Add(fun e -> if e.KeyCode = Keys.Escape then form.Close());
  form

构建并运行应用程序。

  1. 打开 Eliza 项目。
  2. 转到“项目”->“Eliza 属性...”
  3. 在“应用程序”选项卡中,将“输出类型”设置为“Windows 应用程序”。
  4. 按 F5 键 ;-)

关注点

就是这样!

历史

刚刚发布。

© . All rights reserved.