Discourse AI - 网页构件

什么是 AI 工件?

AI 工件是强大的工具,允许用户在 Discourse 帖子中直接创建、嵌入和交互动态 Web 组件。这些组件可以包含自定义的 HTMLCSSJavaScript,支持多种用例,例如:

  • 嵌入交互式测验或表单。
  • 通过丰富的图形和动画可视化数据。
  • 集成轻量级 Web 应用程序或工具。
  • 学习 Web 框架、JavaScript 库等的工具。

AI 工件通过增加交互性无缝增强 Discourse 帖子,同时确保安全的浏览体验。


站点设置

管理员可以配置多项设置:

1. 启用功能

  • 设置discourse_ai_enabled
    • 确保此全局设置已启用,以便 AI 工件能够正常运行。

2. 安全模式

  • 设置ai_artifact_security
    • 选项:
      • disabled:禁用工件系统。
      • lax:工件自动出现在帖子中,无需用户交互。
      • hybrid:默认情况下,工件需要点击才能运行,但帖子作者可以在嵌入标记中添加 data-ai-artifact-autorun,使特定工件立即运行。
      • strict:用户必须通过在浏览器中点击“查看”或“运行”按钮来明确激活工件。此设置推荐用于注重安全的环境。(默认)

3. 工件创建者访问权限

  • 默认情况下,工件创建者代理限制为工作人员用户。此限制确保只有受信任的个人才能创建工件,从而最大限度地减少不当或恶意使用的风险。
  • 如果需要更广泛的访问权限,站点管理员需要手动配置权限。

在帖子中使用 AI 工件

工件由工件创建者代理按需自动生成。

上述工件是使用 GPT-4o 和 anime.js 库生成的

一旦创建,它们仅对您和工件创建者代理私有。能够共享 AI 对话的用户(属于 ai bot public sharing allowed groups 的用户)也可以通过共享对话使工件公开。

共享后,您可以使用以下 HTML 标记在帖子中渲染它:

<div class="ai-artifact" data-ai-artifact-version="3" data-ai-artifact-id="71"></div>

(其中版本和工件 ID 是您的版本化工件)

安全考虑

由于 AI 工件可以执行自定义编写的 HTML、CSS 和 JavaScript,Discourse 已实施了强大的保护措施:

1. 在 iFrames 中沙箱化

  • 工件在隔离的 iframe 容器中渲染,并带有 sandbox 属性,以限制潜在的不安全操作,例如:
    • 跨站脚本攻击。
    • 访问外部站点或 API。

2. 内容安全策略 (CSP)

3. 安全模式

  • 严格模式:推荐用于工件不完全可信的环境。用户需要在浏览器中手动激活工件,然后才能渲染。

4. 访问和权限

  • 工件仅对以下人员可见:
    • 其创建者。
    • 具有查看相关帖子权限的用户(例如,私人消息)。
  • 公开工件必须通过共享 AI 对话明确标记为公开。

5. 长度限制

  • 工件中的 HTML、CSS 和 JavaScript 大小各限制为 64 KB。这确保组件保持轻量级,不会给用户或系统带来负担。

工件存储

Web 工件可以选择性地存储每个用户的数据。为此,请向工件创建者提示“使用用户存储”或类似内容。

此系统允许存储键值对:

  • 私有(仅管理员和特定用户可见)
  • 公开(所有用户包括匿名用户可见)

键值对针对工件来源的帖子进行保护,但如果您公开共享工件,则所有人都可以添加键。

要控制存储,您可以使用隐藏设置:

  • ai_artifact_kv_value_max_length(默认项长度最多为 5000 个字符或更短)
  • ai_artifact_max_keys_per_user_per_artifact(默认值为 100)

常见问题解答

谁可以创建 AI 工件?

默认情况下,只有工作人员用户(例如管理员或版主)可以通过工件创建者代理创建工件。该代理简化了使用 HTML、CSS 和 JavaScript 设计交互式 Web 小部件的过程。

如果我点击工件会发生什么?

  • 宽松模式下,工件会自动出现。
  • 混合模式下,工件默认需要点击,但如果嵌入包含 data-ai-artifact-autorun,则可以自动运行。
  • 严格模式下,点击“运行”按钮会激活工件并允许其在您的浏览器中加载。

AI 工件安全吗?

是的。AI 工件在严格控制的环境中运行:

  • 它们被沙箱化,无法直接与 Discourse 应用程序或用户上下文交互,仅能通过 iframe 消息传递。
  • 严格模式让您控制激活。
  • 工件默认是私有的,您需要主动共享才能获得全局访问权限。

我可以查看工件的源代码吗?

可以。当 Discourse AI 生成工件时,它将包含完整的标记、CSS 和 JavaScript。

支持哪些 LLM?

可以使用您配置的任何 LLM 生成工件,但各种 LLM 具有专业化特性,并且更精细地针对工件创建进行了优化。

我们在 o3、Anthropic Claude Sonnet 3.7 - 4.0、GPT-4.1、Gemini Pro 2.5 等模型上看到了良好的结果。通常,更先进的模型表现更好。

工件创建涉及大量的试错,实验是关键。

23 个赞

能够对构件隐私进行更细粒度的控制,以便它们只能与特定组共享,那将是非常棒的。这与类别权限目前的工作方式非常相似 :smiley:

我认为如果你把群组添加到机器人的私聊中,它可能会起作用?

1 个赞

我会测试一下,然后在这里汇报。我有一个特殊的用例,需要工件只能由一个私有类别中的一个组访问。

1 个赞

所以我将 Web Artifact Creator 机器人标记在一个私有类别的新主题中,该群组可以访问该类别,以便它可以创建一个仅我与该特定群组可见的工件。但是,工件 iframe 窗口仅显示当用户无法访问某个页面时弹出的默认“糟糕!该页面不存在或为私有。”

所以我创建了一个数据探索器查询来检查谁可以查看该主题,并且根据数据库,_应该能够_查看该工件的群组中的用户确实显示为可以查看它。

所以也许这是一个 bug?

我的 SQL 查询
-- [params]
-- int :artifact_id = 22

WITH artifact_info AS (
  SELECT
    a.id,
    a.user_id as creator_id,
    a.post_id,
    p.topic_id,
    t.category_id,
    t.archetype,
    c.read_restricted,
    t.title as topic_title
  FROM ai_artifacts a
  LEFT JOIN posts p ON a.post_id = p.id
  LEFT JOIN topics t ON p.topic_id = t.id
  LEFT JOIN categories c ON t.category_id = c.id
  WHERE a.id = :artifact_id
),
users_with_access AS (
  -- Creator always has access
  SELECT
    ai.creator_id as user_id,
    'Creator' as access_reason
  FROM artifact_info ai

  UNION

  -- Users with access to private messages
  SELECT
    tau.user_id,
    'Private Message Access' as access_reason
  FROM artifact_info ai
  JOIN topic_allowed_users tau ON ai.topic_id = tau.topic_id
  WHERE ai.archetype = 'private_message'

  UNION

  -- Group members with access to private messages
  SELECT
    gu.user_id,
    'Private Message Group Access' as access_reason
  FROM artifact_info ai
  JOIN topic_allowed_groups tag ON ai.topic_id = tag.topic_id
  JOIN group_users gu ON tag.group_id = gu.group_id
  WHERE ai.archetype = 'private_message'

  UNION

  -- Users with access to restricted categories
  SELECT
    gu.user_id,
    'Category Group Access' as access_reason
  FROM artifact_info ai
  JOIN category_groups cg ON ai.category_id = cg.category_id
  JOIN group_users gu ON cg.group_id = gu.group_id
  WHERE ai.read_restricted = true
    AND ai.archetype != 'private_message'
    AND cg.permission_type IN (1, 2) -- full access or create/reply/see

  UNION

  -- All users if topic is public (not restricted and not private message)
  SELECT
    u.id as user_id,
    'Public Access' as access_reason
  FROM artifact_info ai
  CROSS JOIN users u
  WHERE (ai.read_restricted = false OR ai.read_restricted IS NULL)
    AND (ai.archetype != 'private_message' OR ai.archetype IS NULL)
    AND u.active = true
)

SELECT
  u.id as user_id,
  u.username,
  u.name,
  u.trust_level,
  uwa.access_reason,
  ai.topic_title
FROM users_with_access uwa
JOIN users u ON uwa.user_id = u.id
CROSS JOIN artifact_info ai
WHERE u.active = true
ORDER BY u.username