> For AI agents: the complete documentation index is available at https://rspress.rs/zh/llms.txt, the full documentation bundle is available at https://rspress.rs/zh/llms-full.txt.

# @rspress/plugin-llms 

[源码](https://github.com/web-infra-dev/rspress/tree/main/packages/plugin-llms)

为 Rspress 站点生成 [llms.txt](https://llmstxt.org/) 相关文件，使大模型可以更好地理解你的文档站。

:::warning

`@rspress/plugin-llms` 的实现原理是使用 remark 处理 MDX 源文件，因此不支持 React Hooks、自定义组件等动态内容的渲染。

本插件仅作为由于代码不兼容 SSR，无法开启 SSG 和 SSG-MD 功能时的备选方案，建议优先使用 [SSG-MD](https://rspress.rs/zh/guide/basic/ssg-md.md) 功能。

:::

## 安装


```sh [npm]
npm add @rspress/plugin-llms -D
```

```sh [yarn]
yarn add @rspress/plugin-llms -D
```

```sh [pnpm]
pnpm add @rspress/plugin-llms -D
```

```sh [bun]
bun add @rspress/plugin-llms -D
```

```sh [deno]
deno add npm:@rspress/plugin-llms -D
```

## 使用

### 1. 安装插件

在配置文件中写入以下的配置：

```ts
// rspress.config.ts
import { defineConfig } from '@rspress/core';
import { pluginLlms } from '@rspress/plugin-llms';

export default defineConfig({
  plugins: [pluginLlms()],
});
```

之后执行 `rspress build` 命令，在生成产物的同时，会在产物目录下根据导航栏、侧边栏生成 `llms.txt` `llms-full.txt` 和对应路由的 markdown 文件。

### 2. UI 展示

如果你希望阅读文档站的用户可以更多地调用大模型来阅读文档，可以在页面顶部增加一个复制 Markdown 按钮，效果与本网站相同。

#### 使用 themeConfig（推荐）

最简单的方式是在 `themeConfig` 中启用 `llmsUI`。这将自动在所有 H1 标题下方（或大纲面板中）添加 `LlmsCopyButton` 和 `LlmsViewOptions` 组件，无需自定义主题代码：

```ts title="rspress.config.ts"
import { defineConfig } from '@rspress/core';
import { pluginLlms } from '@rspress/plugin-llms';

export default defineConfig({
  plugins: [pluginLlms()],
  themeConfig: {
    llmsUI: true,
    // 或者使用自定义选项：
    // llmsUI: {
    //   injectLlmsHint: false, // 禁用面向大语言模型的 HTML/Markdown directive hint
    //   viewOptions: ['markdownLink', 'chatgpt', 'claude'],
    //   placement: 'outline', // 在大纲面板中显示而非 H1 下方
    // },
  },
});
```

#### 使用自定义主题

如果你需要更多控制，可以通过 [自定义主题](https://rspress.rs/zh/guide/basic/custom-theme.md) 来添加复制 Markdown 按钮。

为所有页面增加顶部复制按钮，示例：

```tsx title="theme/index.tsx"
import { getCustomMDXComponent as basicGetCustomMDXComponent } from '@rspress/core/theme-original';
import {
  LlmsContainer,
  LlmsCopyButton,
  LlmsViewOptions,
} from '@rspress/plugin-llms/runtime';

function getCustomMDXComponent() {
  const { h1: H1, ...mdxComponents } = basicGetCustomMDXComponent();

  const MyH1 = ({ ...props }) => {
    return (
      <>
        <H1 {...props} />
        {/* [!code highlight:5] */}
        <LlmsContainer>
          <LlmsCopyButton />
          {/* LlmsViewOptions 组件可根据需要添加  */}
          <LlmsViewOptions />
        </LlmsContainer>
      </>
    );
  };
  return {
    ...mdxComponents,
    h1: MyH1,
  };
}

export { getCustomMDXComponent };
export * from '@rspress/core/theme-original';
```

为指定页面增加复制按钮，示例：

```mdx title="docs/hello-world.mdx"
# Hello world

<LlmsContainer>
  <LlmsCopyButton />
  <LlmsViewOptions /> {/* LlmsViewOptions 组件可根据需要添加  */}
</LlmsContainer>

这是一个示例文档。
```

## 选项

这个插件接受一个对象参数，类型如下:

- **类型**:


```ts
interface LlmsTxt {
  name: string;
  onTitleGenerate?: (context: {
    title: string | undefined;
    description: string | undefined;
  }) => string;
  onLineGenerate?: (page: PageIndexInfo) => string;
  onAfterLlmsTxtGenerate?: (llmsTxtContent: string) => string;
}

interface MdFiles {
  mdxToMd?: boolean;
  remarkPlugins?: PluggableList;
}

interface LlmsFullTxt {
  name: string;
}
export interface Options {
  llmsTxt?: false | LlmsTxt;
  mdFiles?: false | MdFiles;;
  llmsFullTxt?: false | LlmsFullTxt;
  include?: (context: { page: PageIndexInfo }) => boolean;
  exclude?: (context: { page: PageIndexInfo }) => boolean;
}
```

- **默认值**:

当未开启 [国际化](https://rspress.rs/zh/guide/basic/i18n.md) 时，默认值为:

```ts
{
  llmsTxt: { name: 'llms.txt' },
  llmsFullTxt: { name: 'llms-full.txt' },
  mdFiles: true
}
```

当开启 [国际化](https://rspress.rs/zh/guide/basic/i18n.md) 时，会使用[多组配置](#group)，默认值为:

```ts
[
  {
    llmsTxt: { name: 'llms.txt' },
    llmsFullTxt: { name: 'llms-full.txt' },
    mdFiles: true,
    include: ({ page }) => page.lang === config.lang,
  },
  // 根据 locales 配置自动生成其他语言
  {
    llmsTxt: { name: `${lang}/llms.txt` },
    llmsFullTxt: { name: `${lang}/llms-full.txt` },
    mdFiles: true,
    include: ({ page }) => page.lang === lang,
  },
  // ...
];
```

### llmsTxt

- **类型**: `false | LlmsTxt`

```ts
import type { PageIndexInfo } from '@rspress/core';

export interface LlmsTxt {
  name: string;
  onTitleGenerate?: (context: {
    title: string | undefined;
    description: string | undefined;
  }) => string;
  onLineGenerate?: (page: PageIndexInfo) => string;
  onAfterLlmsTxtGenerate?: (llmsTxtContent: string) => string;
}
```

- **默认值**: `{ name: 'llms.txt' }`

是否生成 llms.txt 文件，或者通过 hooks 自定义生成 llms.txt 文件。

一个 llms.txt 文件的默认格式如下：

```markdown
# {title}

> {description}

## {nav1.title}

- [{page.title}]({ page.routePath }): {page.frontmatter.description}

## {nav2.title}

- [{page.title}]({ page.routePath }): {page.frontmatter.description}
```

你可以通过 hook 对指定部分进行修改。

- `onTitleGenerate`: 自定义生成 title 和 description 部分。
- `onLineGenerate`: 自定义生成 md 文件的每一行。
- `onAfterLlmsTxtGenerate`: 最后修改 llms.txt 文件的内容。

例如：

```ts
pluginLlms({
  llmsTxt: {
    onTitleGenerate: ({ title, description }) => {
      return `# ${title} - llms.txt

> ${description}

Rspress is a static site generator based on Rsbuild and it can generate llms.txt with @rspress/plugin-llms.
`;
    },
  },
});
```

对应的生成结果为：

```markdown
# Rspress - llms.txt

> Rsbuild based static site generator

Rspress is a static site generator based on Rsbuild and it can generate llms.txt with @rspress/plugin-llms.

## guide

- [foo](/foo.md)
```

### mdFiles

- **类型**: `false | MdFiles`

```ts
export interface MdFiles {
  mdxToMd?: boolean;
  remarkPlugins?: PluggableList;
}
```

- **默认值**: `{ mdxToMd: false, remarkPlugins: [] }`

是否生成对应路由的 markdown 文件，当设置为 `false` 时，不会生成对应路由的 markdown 文件。

#### mdxToMd

- **类型**: `boolean`
- **默认值**: `false`

是否将 mdx 内容转换为 md 内容，如果启用，会将 mdx 文件通过一组默认策略转换为 md 文件，但可能会有一定的信息丢失。

#### remarkPlugins

- **类型**: `PluggableList`
- **默认值**: `[]`

用户可以传入自定义的 remark plugins 来对 Markdown 的内容做一些修改。

### llmsFullTxt

- **类型**: `false | LlmsFullTxt`

```ts
export interface LlmsFullTxt {
  name: string;
}
```

- **默认值**: `{ name: 'llms-full.txt' }`

是否生成 llms-full.txt 文件，当设置为 `false` 时，不会生成 `llms-full.txt` 文件。

### include

- **类型**: `(context: { page: PageIndexInfo }) => boolean`

是否生成时包含某些页面，一般用于精简 llms.txt。

- 示例：

只为语言为英文的页面生成 `llms.txt` 等相关文件：

```ts
pluginLlms({
  llmsTxt: {
    name: 'llms.txt',
  },
  llmsFullTxt: {
    name: 'llms-full.txt',
  },
  include: ({ page }) => {
    return page.lang === 'en';
  },
});
```

### exclude

- **类型**: `(context: { page: PageIndexInfo }) => boolean`

是否生成时排除某些页面，会在 `include` 之后执行。

- 示例：

排除 `/foo` 路由下的单个页面：

```ts
pluginLlms({
  llmsTxt: {
    name: 'llms.txt',
  },
  llmsFullTxt: {
    name: 'llms-full.txt',
  },
  exclude: ({ page }) => {
    return page.routePath === '/foo';
  },
});
```

## UI 组件选项

### LlmsCopyButtonProps

- **类型**：`LlmsCopyButtonProps`

```ts
interface LlmsCopyButtonProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {}
```

### LlmsViewOptionsProps

- **类型**：`LlmsViewOptionsProps`

```ts
type LlmsViewOptionsItem =
  | {
      title: string;
      icon?: React.ReactNode;
      onClick?: () => void;
    }
  | {
      title: string;
      href: string;
      icon?: React.ReactNode;
    }
  | 'markdownLink'
  | 'chatgpt'
  | 'claude';

interface LlmsViewOptionsProps extends React.ButtonHTMLAttributes<HTMLButtonElement> {
  options?: LlmsViewOptionsItem[];
}
```

#### options

- **类型**：`LlmsViewOptionsItem[]`

```ts
type LlmsViewOptionsItem =
  | {
      title: string;
      icon?: React.ReactNode;
      onClick?: () => void;
    }
  | {
      title: string;
      href: string;
      icon?: React.ReactNode;
    }
  | 'markdownLink'
  | 'chatgpt'
  | 'claude';
```

- **默认值**：`['markdownLink', 'chatgpt', 'claude']`

自定义下拉菜单中的选项，默认支持 "复制 Markdown 链接"、[Chatgpt](https://chatgpt.com/) 和 [Claude](https://claude.ai)。

## 同时生成多组 `llms.txt` \{#group}

某些情况下，你可能生成多组 `llms.txt`，例如多语言站点。此时，你可以通过传入一个数组来实现。

- 示例：

```ts
// rspress.config.ts
import { defineConfig } from '@rspress/core';
defineConfig({
  lang: 'en',
  plugins: [
    pluginLlms([
      {
        llmsTxt: {
          name: 'llms.txt',
        },
        llmsFullTxt: {
          name: 'llms-full.txt',
        },
        include: ({ page }) => page.lang === 'en',
      },
      {
        llmsTxt: {
          name: 'zh/llms.txt',
        },
        llmsFullTxt: {
          name: 'zh/llms-full.txt',
        },
        include: ({ page }) => page.lang === 'zh',
      },
    ]),
  ],
});
```
