ProductReadyProductReady

Ask AI 智能问答

AI 驱动的文档问答组件,搜索文档并回答用户问题

Ask AI 智能问答

Why — 为什么需要

用户访问网站时经常有问题,但不想翻阅大量文档页面。Ask AI 组件提供即时的对话式问答体验 — 基于你现有的 Fumadocs 文档内容。

用户只需输入问题,即可获得基于实际文档的 AI 生成答案。

What — 是什么

一个紧凑的浮动组件(右下角),工作流程:

  1. 提取关键词 — 用快速模型(gpt-5-nano)从用户问题中提取搜索关键词
  2. 搜索文档 — 通过 Fumadocs /api/search 端点搜索相关文档
  3. 流式回答 — 用 gpt-5-mini 基于搜索结果生成答案

组件作为共享包(share-domains/ask-ai)提供:

  • components/ — 客户端聊天组件,基于 KUI AI elements + AI SDK v6
  • logic/ — 服务端工具函数(关键词提取、文档搜索、提示词构建)

UI 行为

状态外观
收起迷你输入框 + 💬 图标 + "Ask AI" 占位符
聚焦输入框展开至 320px,空聊天面板出现
对话中聊天面板显示对话,输入框保持展开
Escape / 关闭收回迷你输入框

How — 怎么用

1. 环境变量

.env 中添加:

# 必需:启用组件
ENABLE_ASK_AI=true

# 必需:OpenAI API 访问
OPENAI_API_KEY=sk-...
OPENAI_BASE_URL=https://api.openai.com/v1  # 可选,用于代理

# 可选:覆盖默认模型
ASK_AI_MODEL=gpt-5-mini          # 答案生成(默认:gpt-5-mini)
ASK_AI_FAST_MODEL=gpt-5-nano     # 关键词提取(默认:gpt-5-nano)

# 必需:应用 URL,用于内部搜索 API 调用
NEXT_PUBLIC_APP_URL=http://localhost:3000

2. 添加 Tailwind Source

在应用的 global.css 中添加:

@source "../../../../packages/share-domains";

3. 创建 API 路由

创建 src/app/api/search/ai/route.ts

import { createOpenAI } from "@ai-sdk/openai";
import { streamText } from "ai";
import { buildSystemPrompt, extractKeywords, searchDocs } from "share-domains/ask-ai/logic";

export async function POST(req: Request) {
  const { messages } = await req.json();
  const lastUserMessage = [...messages].reverse().find((m) => m.role === "user");
  const question = lastUserMessage?.content || "";

  const openai = createOpenAI({
    apiKey: process.env.OPENAI_API_KEY,
    baseURL: process.env.OPENAI_BASE_URL || undefined,
  });

  const baseUrl = process.env.NEXT_PUBLIC_APP_URL || "http://localhost:3000";
  const keywords = await extractKeywords(openai(process.env.ASK_AI_FAST_MODEL || "gpt-5-nano"), question);
  const docsContext = await searchDocs(baseUrl, keywords);

  const result = streamText({
    model: openai(process.env.ASK_AI_MODEL || "gpt-5-mini"),
    system: buildSystemPrompt(docsContext),
    messages,
  });

  return result.toUIMessageStreamResponse();
}

4. 在 Layout 中添加组件

在根 layout.tsx(Server Component)中:

import { AskAIWidget } from "share-domains/ask-ai/components";

export default function RootLayout({ children }) {
  return (
    <html lang="en">
      <body>
        {children}
        {process.env.ENABLE_ASK_AI === "true" && (
          <AskAIWidget
            endpoint="/api/search/ai"
            title="Ask MyApp"
            placeholder="Ask AI"
            welcomeMessage="有什么可以帮你的?"
          />
        )}
      </body>
    </html>
  );
}

配置属性

属性类型默认值说明
endpointstring/api/search/aiAPI 路由路径
placeholderstringAsk AI输入框占位文本
titlestringAI Assistant聊天面板标题
welcomeMessagestring""面板为空时显示的消息
maxHeightstring480px聊天面板最大高度

架构流程

用户输入问题
  → [客户端] AskAIWidget (useChat + DefaultChatTransport)
  → [服务端] POST /api/search/ai
      → extractKeywords(gpt-5-nano, 问题)    →  "i18n 配置 多语言"
      → searchDocs(baseUrl, 关键词)           →  fumadocs /api/search
      → streamText(gpt-5-mini, 文档上下文)    →  流式答案
  → [客户端] MessageResponse 渲染 Markdown

前置条件

  • Fumadocs 已配置 /api/search 路由
  • 已安装 @ai-sdk/openaiai
  • share-domains 作为 workspace 依赖
  • kui 作为 workspace 依赖(用于 AI elements)

On this page