Discourse AI 角色,上传支持

您现在可以在 AI 角色中包含大段文本了!

这提供了多项优势:

  1. 您可以将大段文本引入到自定义 AI 机器人中,而这些文本在模型的训练数据中是缺失的(例如:内部培训文档、内部报告)。

  2. 您可以使用具体数据更好地固定角色的基础(即使这些数据存在于模型的训练集中),这有助于模型正确引用特定信息并提高结果的质量。

要添加上传内容:

  1. 使用 /admin/plugins/discourse-ai/ai-personas/ 界面创建新角色。

  2. 上传您希望包含在角色中的文本文件。

:information_source: 上传文件之前,请通过站点设置 authorized extensions 添加相关扩展名(.md.txt),以便角色可以使用。

  1. 根据需要调整索引选项。

先决条件

要使该选项运行,您需要配置 ai_embeddings_enabledai_embeddings_model

Discourse AI 支持大量的嵌入模型。

我们的托管客户可以免费使用最先进的 bge-large-en 模型。

自托管者或希望有更多选择的人可以自托管嵌入模型,或使用 OpenAI、Google (Gemini) 等的模型。

这是 RAG 吗?

我们的上传支持的实现确实是 检索增强生成

从高层次来看,每次我们要让 LLM 回答用户的问题时,我们都会根据您输入的文本查找高度相关的信息,并将其注入系统提示。

解释各种索引选项

什么是 token?token 是大型语言模型用来分割文本的基本单位。一个很好的可视化解释可以在这里找到:https://platform.openai.com/tokenizer

Discourse AI 上传实现附带以下切换:

Upload Chunk Tokens:文件上传后,我们会将其分割成小块。这允许您控制小块的大小。如果小块对于您的嵌入模型来说太大了,嵌入就会被截断(只有部分 token 会被处理)。

Upload Chunk Overlap Tokens:这是当前小块中包含的上一个块的 token 数量。这个数字越大,您的索引中存储的重复信息就越多。

Search Conversation Chunks:这控制着根据相关性无条件包含在完成提示中的“块”的数量。数字越大,LLM 获得的上下文就越多(并且调用成本就越高)。例如:如果设置为 10,而 Upload Chunk Tokens 设置为 200,那么每次完成都会有额外的 2000 个 token 开销。

Discourse AI 如何分割大段文本?

Discourse 使用递归字符文本分割器,它在分割时会尝试将段落、然后是行、最后是单词保留在一起。

此外,Discourse 还为您提供了对文本分割方式的额外控制。

[[metadata YOUR METADATA HERE]] 分隔符可用于分割大段文本并正确突出显示每个部分的内容。

例如:

[[metadata about cats]]
a long story about cats
[[metadata about dogs]]
a long story about dogs

这使得单个文本文档可以涵盖各种内容,并保护您免受“块污染”。您可以确保只有关于猫的数据包含在猫的块中,狗的数据包含在狗的块中。

听起来很复杂,我该如何调试?

Discourse AI 附带站点设置 ai bot debugging enabled groups,该组中的用户可以访问 AI 调试:

AI 调试屏幕可以帮助您了解我们发送给 AI 的信息。

:warning: 垃圾进 - 垃圾出 如果您向 LLM 提供无用或模糊的信息,它无法神奇地将其转换为有用信息。

此屏幕可以帮助您更好地决定块的大小,或者您包含的块是太多还是太少。

这真的有用吗?

一个实际的例子是将 HAProxy 文档分割并输入到角色中:

System Prompt:

您是一个专门回答有关 HAProxy 问题 的机器人。

您生活在一个 Discourse 论坛上,并且渲染 Discourse markdown。

在提供答案时,请始终尝试包含指向 HAProxy 文档的链接。

例如,这是您如何链接到 10.1.1 部分,请记住您可以链接到部分或其中的一个选项。

[fcgi-app](https://www.haproxy.com/documentation/haproxy-configuration-manual/latest/#10.1.1-fcgi-app)

链接要慷慨,它们非常有帮助。

上传内容:
processed-haproxy-2.txt (1.2 MB)

这是使用以下脚本生成的:

file_content = File.read("configuration.txt")

title = nil
body = nil
last_line = nil

sections = []

file_content.each_line do |line|
  if line.strip.match?(/^[-]+$/)
    section_number, title = title.to_s.split(" ", 2)
    sections << {
      section_number: section_number,
      title: title,
      body: body.to_s.strip
    }

    title = last_line
    body = nil
    last_line = nil
  else
    body = body.to_s + last_line.to_s
    last_line = line
  end
end

section_number, title = title.to_s.split(" ", 2)
sections << { section_number: section_number, title: title, body: body }

section_names =
  sections.map { |section| [section[:section_number], section[:title]] }.to_h

sections[4..-1].each do |section|
  title = []
  current = +" "
  section_number = section[:section_number]
  section_number
    .split(".")
    .each do |number|
      current << number
      current << "."
      title << section_names[current].to_s.strip
    end
  title = title.join(" - ")

  body = section[:body]

  next if body.strip.empty?
  puts "[[metadata section=\"#{section_number}\" title=\"#{title.strip}\"]]"
  puts body
end

Claude Opus 和 GPT-4 在处理复杂问题时都可能表现不佳。这是可以理解的,因为它们依赖于互联网上的所有 token,所以 50 个不同版本的 HAProxy 文档以及关于它的所有讨论都会进入它们的大脑,这可能会让它们非常困惑:

GPT-4 和 Claude 3 Opus 混淆的例子

两者客观上都不如 Discourse RAG 提供的精调答案:

GPT-4 和 Claude Opus 混淆较少的例子

未来

我们期待您的反馈,未来的一些想法可能是:

  • 支持 PDF/DOCX/XLS 等格式,这样您就不需要转换为文本了
  • 对源代码/HTML 进行更智能的块分割
  • 在索引前对传入数据进行智能转换

请告诉我们您的想法!

非常感谢 @Roman 实现了这个功能 :hugs:

24 个赞

除了手动上传的文本之外,是否还可以包含符合所选条件的论坛帖子?

例如:

  • 在给定类别中
  • 具有特定标签(或不具有)
  • 是已解决主题的一部分(或者,专门是解决方案帖子)
  • 是主题的 OP,而不是回复
  • 由给定组中的用户发布
  • 在特定日期之前或之后

或者,是否可以用“是给定论坛搜索的前 N 个主题之一”来代替这些选项的复选框?

1 个赞

所有这些今天都可以通过自定义搜索命令完成:

  • 可以在过滤器中选择给定类别
  • 标签
  • 已解决
  • 仅发帖人(我认为可以做到)
  • 给定组
  • 日期之前和之后

:hugs:

5 个赞

嗯,也许是我误解了。将其提供给 Persona 是否也能达到相同的效果?

我试过了,但大多数时候只是让 Mistral 凭空捏造主题标题并链接到完全随机的帖子编号。:slight_smile:

1 个赞

Mistral 真的足以胜任这些任务吗?我认为这可能会导致幻觉。Sam 说得对,通过更改基础查询,你可以完成 OP 中提到的所有事情。

1 个赞

而且,我在想完之前就发帖了。问题是:提供搜索命令和参数是否与提供上传文件效果相同?

但是的,Mistral 可能还不够好。

1 个赞

在此稍微扩展一下:

https://chat.lmsys.org/?leaderboard

Mistral 有多种版本……有 Mistral 7b、Mixtral 8x7b(您拥有的那个),以及全新的 mistralai/Mixtral-8x22B-Instruct-v0.1 · Hugging Face - 这个以及他们发布的另外 5/6 个模型,包括一些闭源模型。

“Mistral 不够好”的说法需要谨慎,并且要始终澄清。

我认为 Mixtral-8x7b 根本不适合工具支持,它偏离得太远了。

我认为它:

  1. 在“上传”支持方面相当不错
  2. 在自定义个性支持方面非常好
  3. 在工具支持方面较弱

我们正在尝试看看是否可以升级到 8x22b(它自带良好的工具支持),问题是内存需求相当高,我们需要量化模型才能很好地适应我们的服务器。

但说实话……如果您与亚马逊有数据隐私协议,我强烈建议使用 Bedrock,它将使您能够访问 Claude 3 Opus 和 Haiku。

我理解开源模型与闭源模型之间的矛盾。这很棘手,目前闭源模型确实领先不少。

2 个赞

你说得对,我本该更好地措辞。我确实是在暗示闭源模型总体上更好。

2 个赞

一次上传多个 .txt 文件时出现错误:它们会快速显示,但之后只显示一个,之后“添加文件”按钮不再响应。

另外,我认为支持 .md 文件将是一个很好的补充。

1 个赞

哦,糟糕……抓得好,罗马人@Roman 会看看的。

这应该没问题,它已经支持了,你只需要启用扩展。

3 个赞

我为多文件 bug 推送了一个修复程序:

4 个赞

2 篇帖子已拆分到一个新主题:改进 Discourse AI 中搜索过滤器的质量

嘿 Sam,我想知道这具体是如何工作的。它会告诉 AI 这是关于猫或狗的数据,但如果分块已设置为固定数量的 token(例如 2000),它将如何影响分块?当它看到像 [[metadata about dogs]] 这样的行时,它会截断一个分块并开始一个新的分块吗?

1 个赞

是的,它会提前结束

2 个赞

哦,糟糕,我之前使用的是 \u003cmeta\u003econtent\u003c/meta\u003e 格式,这对于大多数大型语言模型来说是有效的,你们为什么选择 [[brackets]] 这种方式呢?\u003ctags\u003e 仍然有效,还是在 Discourse 中使用括号方法更好?

1 个赞

这根本不会被大型语言模型消耗(我们解析和消耗元数据),想要一个不太可能出现在索引数据中的分隔符。

2 个赞

添加了这部分到副本中

1 个赞

这些为 AI Personas 创建的嵌入是否位于同一个向量数据库中?实际上,为 Discourse 生成的所有嵌入都存储在同一个向量数据库中吗?

1 个赞

全部在 Postgres 中使用同一个数据库

2 个赞

有人能告诉我,如果从上传文件列表中删除的文本文件在 personas 中会发生什么吗?我明白它们用于 RAG,但如果我删除文件,它会从已索引的内容中删除吗?我想知道是否可以通过删除文本文件、进行调整然后重新上传来编辑已索引的内容?

1 个赞