mirror of
https://github.com/labring/FastGPT.git
synced 2025-10-14 15:11:13 +00:00
update doc search engine (#5386)
* update doc search engine * custom tokenizer * tokenizer
This commit is contained in:
@@ -1,4 +1 @@
|
||||
NEXT_PUBLIC_SEARCH_APPKEY=
|
||||
SEARCH_APPWRITEKEY=
|
||||
NEXT_PUBLIC_SEARCH_APPID=
|
||||
FASTGPT_HOME_DOMAIN=
|
@@ -19,26 +19,14 @@ RUN apk add --no-cache \
|
||||
fontconfig
|
||||
WORKDIR /app
|
||||
|
||||
ARG NEXT_PUBLIC_SEARCH_APPKEY
|
||||
ARG NEXT_PUBLIC_SEARCH_APPID
|
||||
ARG SEARCH_APPWRITEKEY
|
||||
ARG FASTGPT_HOME_DOMAIN
|
||||
|
||||
ENV NEXT_PUBLIC_SEARCH_APPKEY=$NEXT_PUBLIC_SEARCH_APPKEY
|
||||
ENV NEXT_PUBLIC_SEARCH_APPID=$NEXT_PUBLIC_SEARCH_APPID
|
||||
ENV SEARCH_APPWRITEKEY=$SEARCH_APPWRITEKEY
|
||||
ENV FASTGPT_HOME_DOMAIN=$FASTGPT_HOME_DOMAIN
|
||||
|
||||
COPY . .
|
||||
RUN npm install
|
||||
RUN npm run build
|
||||
# Update search index if SEARCH_APPWRITEKEY is provided
|
||||
RUN if [ -n "$SEARCH_APPWRITEKEY" ]; then \
|
||||
echo "SEARCH_APPWRITEKEY found, updating search index..." && \
|
||||
(npm run update-index-action || echo "Search index update failed, but continuing..."); \
|
||||
else \
|
||||
echo "SEARCH_APPWRITEKEY not provided, skipping search index update"; \
|
||||
fi
|
||||
|
||||
|
||||
FROM base AS runner
|
||||
RUN apk add --no-cache curl
|
||||
|
@@ -1,29 +1,11 @@
|
||||
# FastGPT 文档
|
||||
|
||||
这是FastGPT的官方文档,采用fumadoc框架。
|
||||
|
||||
## 配置文档搜索
|
||||
|
||||
点击[Algolia](https://dashboard.algolia.com/account/overview),进行注册账号,注册成功后需要点击页面的搜索,然后查看应用,默认会有一个应用。
|
||||
|
||||

|
||||
|
||||
拥有应用后点击个人头像,点击设置,点击`API Keys`查看自己的应用id和key。
|
||||
|
||||

|
||||
|
||||
页面中的`Application ID`和`Search API Key`,`Write API KEY`就是环境变量对应的`NEXT_PUBLIC_SEARCH_APPID`和`NEXT_PUBLIC_SEARCH_APPKEY`,`SEARCH_APPWRITEKEY`
|
||||
|
||||

|
||||
|
||||
## 运行项目
|
||||
|
||||
要运行文档,首先需要进行环境变量配置,在文档的根目录下创建`.env.local`文件,填写以下环境变量:
|
||||
|
||||
```bash
|
||||
SEARCH_APPWRITEKEY = #这是上面获取的Write api key
|
||||
NEXT_PUBLIC_SEARCH_APPKEY = #这是上面获取的搜索key
|
||||
NEXT_PUBLIC_SEARCH_APPID = #这是上面的搜索id
|
||||
FASTGPT_HOME_DOMAIN = #要跳转的FastGPT项目的域名,默认海外版
|
||||
```
|
||||
|
||||
|
@@ -1,7 +1,21 @@
|
||||
import { source } from '@/lib/source';
|
||||
import { enhancedTokenizer } from '@/lib/tokenizer';
|
||||
import { createFromSource } from 'fumadocs-core/search/server';
|
||||
|
||||
export const { GET } = createFromSource(source, {
|
||||
// https://docs.orama.com/open-source/supported-languages
|
||||
language: 'english'
|
||||
// 使用中文分词器时不能设置 language 选项
|
||||
localeMap: {
|
||||
en: {
|
||||
language: 'english'
|
||||
},
|
||||
'zh-CN': {
|
||||
components: {
|
||||
tokenizer: enhancedTokenizer()
|
||||
},
|
||||
search: {
|
||||
threshold: 0,
|
||||
tolerance: 0
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
@@ -1,43 +0,0 @@
|
||||
const fs = require('fs');
|
||||
const path = require('path');
|
||||
const matter = require('gray-matter');
|
||||
|
||||
// ✅ 设置要处理的根目录(可修改为你的文档目录)
|
||||
const rootDir = path.resolve(__dirname, 'content/docs');
|
||||
|
||||
// ✅ 仅保留的 frontmatter 字段
|
||||
const KEEP_FIELDS = ['title', 'description'];
|
||||
|
||||
function cleanFrontmatter(filePath) {
|
||||
const raw = fs.readFileSync(filePath, 'utf-8');
|
||||
const parsed = matter(raw);
|
||||
|
||||
// 仅保留需要的字段
|
||||
const newData = {};
|
||||
for (const key of KEEP_FIELDS) {
|
||||
if (parsed.data[key] !== undefined) {
|
||||
newData[key] = parsed.data[key];
|
||||
}
|
||||
}
|
||||
|
||||
const cleaned = matter.stringify(parsed.content, newData);
|
||||
fs.writeFileSync(filePath, cleaned, 'utf-8');
|
||||
console.log(`✔ Cleaned: ${path.relative(rootDir, filePath)}`);
|
||||
}
|
||||
|
||||
function walk(dir) {
|
||||
const entries = fs.readdirSync(dir);
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry);
|
||||
const stat = fs.statSync(fullPath);
|
||||
|
||||
if (stat.isDirectory()) {
|
||||
walk(fullPath); // 🔁 递归子目录
|
||||
} else if (entry.endsWith('.mdx')) {
|
||||
cleanFrontmatter(fullPath);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// 🚀 开始执行
|
||||
walk(rootDir);
|
@@ -1,6 +1,5 @@
|
||||
'use client';
|
||||
// components/CustomSearchDialog.tsx
|
||||
import { liteClient } from 'algoliasearch/lite';
|
||||
import { useDocsSearch } from 'fumadocs-core/search/client';
|
||||
import {
|
||||
SearchDialog,
|
||||
@@ -15,21 +14,11 @@ import {
|
||||
} from 'fumadocs-ui/components/dialog/search';
|
||||
import { useI18n } from 'fumadocs-ui/contexts/i18n';
|
||||
|
||||
if (!process.env.NEXT_PUBLIC_SEARCH_APPID || !process.env.NEXT_PUBLIC_SEARCH_APPKEY) {
|
||||
throw new Error('NEXT_PUBLIC_SEARCH_APPID and NEXT_PUBLIC_SEARCH_APPKEY are not set');
|
||||
}
|
||||
|
||||
const client = liteClient(
|
||||
process.env.NEXT_PUBLIC_SEARCH_APPID,
|
||||
process.env.NEXT_PUBLIC_SEARCH_APPKEY
|
||||
);
|
||||
|
||||
export default function CustomSearchDialog(props: SharedProps) {
|
||||
const { locale } = useI18n();
|
||||
const { search, setSearch, query } = useDocsSearch({
|
||||
type: 'algolia',
|
||||
client,
|
||||
indexName: 'document',
|
||||
type: 'fetch',
|
||||
api: '/api/search',
|
||||
locale
|
||||
});
|
||||
|
||||
|
@@ -8,4 +8,4 @@ title: 其他问题
|
||||
|
||||
## 想做多用户
|
||||
|
||||
开源版未支持多用户,仅商业版支持。
|
||||
社区版未支持多用户,仅商业版支持。
|
||||
|
@@ -7,11 +7,11 @@ import { Alert } from '@/components/docs/Alert';
|
||||
|
||||
## 简介
|
||||
|
||||
FastGPT 商业版是基于 FastGPT 开源版的增强版本,增加了一些独有的功能。只需安装一个商业版镜像,并在开源版基础上填写对应的内网地址,即可快速使用商业版。
|
||||
FastGPT 商业版是基于 FastGPT 社区版的增强版本,增加了一些独有的功能。只需安装一个商业版镜像,并在社区版基础上填写对应的内网地址,即可快速使用商业版。
|
||||
|
||||
## 功能差异
|
||||
|
||||
| | 开源版 | 商业版 | Saas 版 |
|
||||
| | 社区版 | 商业版 | Saas 版 |
|
||||
| ------------------------------ | ------------------------------------------ | ------ | ------- |
|
||||
| **应用构建** | | | |
|
||||
| 工作流编排 | ✅ | ✅ | ✅ |
|
||||
@@ -89,13 +89,13 @@ FastGPT 商业版软件根据不同的部署方式,分为 3 类收费模式。
|
||||
|
||||
### 如何交付?
|
||||
|
||||
完整版应用 = 开源版镜像 + 商业版镜像
|
||||
完整版应用 = 社区版镜像 + 商业版镜像
|
||||
|
||||
我们会提供一个商业版镜像给你使用,该镜像需要一个 License 启动。
|
||||
|
||||
### 二次开发如何操作?
|
||||
|
||||
可以修改开源版部分代码,不支持修改商业版镜像。完整版本=开源版+商业版镜像,所以是可以修改部分内容的。但是如果二开了,后续则需要自己进行代码合并升级。
|
||||
可以修改社区版部分代码,不支持修改商业版镜像。完整版本=社区版+商业版镜像,所以是可以修改部分内容的。但是如果二开了,后续则需要自己进行代码合并升级。
|
||||
|
||||
### Sealos 运行费用
|
||||
|
||||
|
@@ -5,12 +5,14 @@ description: FastGPT 配置参数介绍
|
||||
|
||||
由于环境变量不利于配置复杂的内容,新版 FastGPT 采用了 ConfigMap 的形式挂载配置文件,你可以在 `projects/app/data/config.json` 看到默认的配置文件。可以参考 [docker-compose 快速部署](/docs/development/docker/) 来挂载配置文件。
|
||||
|
||||
**开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。
|
||||
**开发环境下**,你需要将示例配置文件 `config.json` 复制成 `config.local.json` 文件才会生效。
|
||||
|
||||
下面配置文件示例中包含了系统参数和各个模型配置:
|
||||
|
||||
## 4.8.20+ 版本新配置文件示例
|
||||
|
||||
> 从4.8.20版本开始,模型在页面中进行配置。
|
||||
|
||||
```json
|
||||
{
|
||||
"feConfigs": {
|
||||
@@ -22,7 +24,8 @@ description: FastGPT 配置参数介绍
|
||||
"vlmMaxProcess": 15, // 图片理解模型最大处理进程
|
||||
"tokenWorkers": 50, // Token 计算线程保持数,会持续占用内存,不能设置太大。
|
||||
"hnswEfSearch": 100, // 向量搜索参数,仅对 PG 和 OB 生效。越大,搜索越精确,但是速度越慢。设置为100,有99%+精度。
|
||||
"customPdfParse": { // 4.9.0 新增配置
|
||||
"customPdfParse": {
|
||||
// 4.9.0 新增配置
|
||||
"url": "", // 自定义 PDF 解析服务地址
|
||||
"key": "", // 自定义 PDF 解析服务密钥
|
||||
"doc2xKey": "", // doc2x 服务密钥
|
||||
@@ -57,7 +60,7 @@ description: FastGPT 配置参数介绍
|
||||
|
||||
#### 2. 修改 FastGPT 配置文件
|
||||
|
||||
开源版用户在 `config.json` 文件中添加 `systemEnv.customPdfParse.doc2xKey` 配置,并填写上申请到的 API Key。并重启服务。
|
||||
社区版用户在 `config.json` 文件中添加 `systemEnv.customPdfParse.doc2xKey` 配置,并填写上申请到的 API Key。并重启服务。
|
||||
|
||||
商业版用户在 Admin 后台根据表单指引填写 Doc2x 服务密钥。
|
||||
|
||||
|
@@ -9,7 +9,7 @@ PDF 是一个相对复杂的文件格式,在 FastGPT 内置的 pdf 解析器
|
||||
|
||||
市面上目前有多种解析 PDF 的方法,比如使用 [Marker](https://github.com/VikParuchuri/marker),该项目使用了 Surya 模型,基于视觉解析,可以有效提取图片、表格、公式等复杂内容。
|
||||
|
||||
在 `FastGPT v4.9.0` 版本中,开源版用户可以在`config.json`文件中添加`systemEnv.customPdfParse`配置,来使用 Marker 解析 PDF 文件。商业版用户直接在 Admin 后台根据表单指引填写即可。需重新拉取 Marker 镜像,接口格式已变动。
|
||||
在 `FastGPT v4.9.0` 版本中,社区版用户可以在`config.json`文件中添加`systemEnv.customPdfParse`配置,来使用 Marker 解析 PDF 文件。商业版用户直接在 Admin 后台根据表单指引填写即可。需重新拉取 Marker 镜像,接口格式已变动。
|
||||
|
||||
## 使用教程
|
||||
|
||||
@@ -23,6 +23,7 @@ PDF 是一个相对复杂的文件格式,在 FastGPT 内置的 pdf 解析器
|
||||
docker pull crpi-h3snc261q1dosroc.cn-hangzhou.personal.cr.aliyuncs.com/marker11/marker_images:v0.2
|
||||
docker run --gpus all -itd -p 7231:7232 --name model_pdf_v2 -e PROCESSES_PER_GPU="2" crpi-h3snc261q1dosroc.cn-hangzhou.personal.cr.aliyuncs.com/marker11/marker_images:v0.2
|
||||
```
|
||||
|
||||
### 2. 添加 FastGPT 文件配置
|
||||
|
||||
```json
|
||||
@@ -52,7 +53,7 @@ docker run --gpus all -itd -p 7231:7232 --name model_pdf_v2 -e PROCESSES_PER_GPU
|
||||
|
||||
```
|
||||
[Info] 2024-12-05 15:04:42 Parsing files from an external service
|
||||
[Info] 2024-12-05 15:07:08 Custom file parsing is complete, time: 1316ms
|
||||
[Info] 2024-12-05 15:07:08 Custom file parsing is complete, time: 1316ms
|
||||
```
|
||||
|
||||
然后你就可以发现,通过 Marker 解析出来的 pdf 会携带图片链接:
|
||||
@@ -63,14 +64,13 @@ docker run --gpus all -itd -p 7231:7232 --name model_pdf_v2 -e PROCESSES_PER_GPU
|
||||
|
||||

|
||||
|
||||
|
||||
## 效果展示
|
||||
|
||||
以清华的 [ChatDev Communicative Agents for Software Develop.pdf](https://arxiv.org/abs/2307.07924) 为例,展示 Marker 解析的效果:
|
||||
|
||||
| | | |
|
||||
| --- | --- | --- |
|
||||
|  |  |  |
|
||||
| | | |
|
||||
| ------------------------------- | ------------------------------- | ------------------------------- |
|
||||
|  |  |  |
|
||||
|  |  |  |
|
||||
|
||||
上图是分块后的结果,下图是 pdf 原文。整体图片、公式、表格都可以提取出来,效果还是杠杠的。
|
||||
@@ -95,5 +95,5 @@ CUSTOM_READ_FILE_URL=http://xxxx.com/v1/parse/file
|
||||
CUSTOM_READ_FILE_EXTENSION=pdf
|
||||
```
|
||||
|
||||
* CUSTOM_READ_FILE_URL - 自定义解析服务的地址, host改成解析服务的访问地址,path 不能变动。
|
||||
* CUSTOM_READ_FILE_EXTENSION - 支持的文件后缀,多个文件类型,可用逗号隔开。
|
||||
- CUSTOM_READ_FILE_URL - 自定义解析服务的地址, host改成解析服务的访问地址,path 不能变动。
|
||||
- CUSTOM_READ_FILE_EXTENSION - 支持的文件后缀,多个文件类型,可用逗号隔开。
|
||||
|
@@ -16,11 +16,12 @@ curl --location --request POST 'https://{{host}}/api/admin/initv462' \
|
||||
```
|
||||
|
||||
初始化说明:
|
||||
|
||||
1. 初始化全文索引
|
||||
|
||||
## V4.6.2 功能介绍
|
||||
|
||||
1. 新增 - 全文索引(需配合 Rerank 模型,在看怎么放到开源版,模型接口比较特殊)
|
||||
1. 新增 - 全文索引(需配合 Rerank 模型,在看怎么放到社区版,模型接口比较特殊)
|
||||
2. 新增 - 插件来源(预计4.7/4.8版本会正式使用)
|
||||
3. 优化 - PDF读取
|
||||
4. 优化 - docx文件读取,转成 markdown 并保留其图片内容
|
||||
|
@@ -18,6 +18,7 @@ curl --location --request POST 'https://{{host}}/api/admin/initv47' \
|
||||
```
|
||||
|
||||
脚本功能:
|
||||
|
||||
1. 初始化插件的 parentId
|
||||
|
||||
## 3. 升级 ReRank 模型
|
||||
@@ -31,18 +32,17 @@ cohere的重排模型对中文不是很好,感觉不如 bge 的好用,接入
|
||||
|
||||
```json
|
||||
{
|
||||
"reRankModels": [
|
||||
{
|
||||
"model": "rerank-multilingual-v2.0", // 这里的 model 需要对应 cohere 的模型名
|
||||
"name": "检索重排", // 随意
|
||||
"requestUrl": "https://api.cohere.ai/v1/rerank",
|
||||
"requestAuth": "Coherer上申请的key"
|
||||
}
|
||||
]
|
||||
"reRankModels": [
|
||||
{
|
||||
"model": "rerank-multilingual-v2.0", // 这里的 model 需要对应 cohere 的模型名
|
||||
"name": "检索重排", // 随意
|
||||
"requestUrl": "https://api.cohere.ai/v1/rerank",
|
||||
"requestAuth": "Coherer上申请的key"
|
||||
}
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
## V4.7 更新说明
|
||||
|
||||
1. 新增 - 工具调用模块,可以让LLM模型根据用户意图,动态的选择其他模型或插件执行。
|
||||
@@ -57,7 +57,7 @@ cohere的重排模型对中文不是很好,感觉不如 bge 的好用,接入
|
||||
10. 优化 - 变量输入弹窗。
|
||||
11. 优化 - docker 部署,自动初始化副本集。
|
||||
12. 优化 - 浏览器读取文件自动推断编码,减少乱码情况。
|
||||
13. 修复 - 开源版重排选不上。
|
||||
13. 修复 - 社区版重排选不上。
|
||||
14. 修复 - http 请求 body,不使用时,传入undefined。(会造成部分GET请求失败)
|
||||
15. 新增 - 支持 http url 使用变量。
|
||||
16. 修复 - 469 的提取的提示词容易造成幻觉。
|
||||
|
@@ -23,7 +23,7 @@ description: FastGPT V4.9.10 更新说明
|
||||
2. 知识库预处理参数增加 “分块条件”,可控制某些情况下不进行分块处理。
|
||||
3. 知识库预处理参数增加 “段落优先” 模式,可控制最大段落深度。原“长度优先”模式,不再内嵌段落优先逻辑。
|
||||
4. 工作流调整为单向接入和接出,支持快速的添加下一步节点。
|
||||
5. 开放飞书和语雀知识库到开源版。
|
||||
5. 开放飞书和语雀知识库到社区版。
|
||||
6. gemini 和 claude 最新模型预设。
|
||||
|
||||
## ⚙️ 优化
|
||||
|
@@ -29,6 +29,7 @@ description: FastGPT V4.9.6 更新说明
|
||||
3. 连续工具调用,上下文截断异常
|
||||
|
||||
## 升级指南
|
||||
|
||||
### 1. 做好数据备份
|
||||
|
||||
### 2. 部署 MCP server 服务
|
||||
@@ -39,15 +40,15 @@ description: FastGPT V4.9.6 更新说明
|
||||
|
||||
```yml
|
||||
fastgpt-mcp-server:
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.9.6
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
container_name: fastgpt-mcp-server
|
||||
image: ghcr.io/labring/fastgpt-mcp_server:v4.9.6
|
||||
ports:
|
||||
- 3005:3000
|
||||
networks:
|
||||
- fastgpt
|
||||
restart: always
|
||||
environment:
|
||||
- FASTGPT_ENDPOINT=http://fastgpt:3000
|
||||
```
|
||||
|
||||
#### Sealos 部署
|
||||
@@ -56,14 +57,15 @@ fastgpt-mcp-server:
|
||||
|
||||
### 3. 修改 FastGPT 容器环境变量
|
||||
|
||||
#### 开源版
|
||||
#### 社区版
|
||||
|
||||
修改`config.json`配置文件,增加: `"feconfigs.mcpServerProxyEndpoint": "fastgpt-mcp-server 的访问地址"`, 末尾不要携带/,例如:
|
||||
|
||||
```json
|
||||
{
|
||||
"feConfigs": {
|
||||
"lafEnv": "https://laf.dev",
|
||||
"mcpServerProxyEndpoint": "https://mcp.fastgpt.cn"
|
||||
"mcpServerProxyEndpoint": "https://mcp.fastgpt.cn"
|
||||
}
|
||||
}
|
||||
```
|
||||
|
338
document/lib/tokenizer.ts
Normal file
338
document/lib/tokenizer.ts
Normal file
@@ -0,0 +1,338 @@
|
||||
import { createTokenizer } from '@orama/tokenizers/mandarin';
|
||||
|
||||
export const enhancedTokenizer = () => {
|
||||
// 整词配置 - 需要保持完整的词汇
|
||||
const wholeWords = [
|
||||
// 产品相关
|
||||
'fastgpt',
|
||||
'FastGPT',
|
||||
'快速GPT',
|
||||
'Saas',
|
||||
'SaaS',
|
||||
'云服务',
|
||||
'社区版',
|
||||
'商业版',
|
||||
'开源版',
|
||||
'企业版',
|
||||
'专业版',
|
||||
'智能对话系统',
|
||||
'AI应用平台',
|
||||
'知识库问答系统',
|
||||
|
||||
// 核心功能模块
|
||||
'知识库',
|
||||
'工作流',
|
||||
'应用构建',
|
||||
'对话管理',
|
||||
'可视化编排',
|
||||
'拖拽式设计',
|
||||
'零代码搭建',
|
||||
'低代码开发',
|
||||
'流程编排',
|
||||
|
||||
// 工作流节点
|
||||
'AI对话',
|
||||
'知识库搜索',
|
||||
'问题分类',
|
||||
'内容提取',
|
||||
'用户选择',
|
||||
'表单输入',
|
||||
'文本编辑',
|
||||
'指定回复',
|
||||
'文档解析',
|
||||
'HTTP请求',
|
||||
'真假判断',
|
||||
'变量更新',
|
||||
'代码运行',
|
||||
'循环',
|
||||
'指代消解',
|
||||
'自定义反馈',
|
||||
'工具调用',
|
||||
|
||||
// AI模型相关
|
||||
'AI',
|
||||
'Agent',
|
||||
'LLM',
|
||||
'大语言模型',
|
||||
'ChatGPT',
|
||||
'GPT-4',
|
||||
'GPT-3.5',
|
||||
'Claude',
|
||||
'文心一言',
|
||||
'通义千问',
|
||||
'DeepSeek',
|
||||
'Function Call',
|
||||
'Prompt',
|
||||
'提示词',
|
||||
'系统提示词',
|
||||
'Temperature',
|
||||
'温度参数',
|
||||
'Token',
|
||||
'OpenAI',
|
||||
'Anthropic',
|
||||
'百度',
|
||||
'阿里云',
|
||||
'智谱AI',
|
||||
'One-API',
|
||||
'AI-Proxy',
|
||||
'Ollama',
|
||||
'Xinference',
|
||||
|
||||
// 技术术语
|
||||
'API',
|
||||
'OpenAPI',
|
||||
'SSO',
|
||||
'MCP',
|
||||
'向量数据库',
|
||||
'语义搜索',
|
||||
'embedding',
|
||||
'RAG',
|
||||
'检索增强生成',
|
||||
'PGVector',
|
||||
'Milvus',
|
||||
'MongoDB',
|
||||
'PostgreSQL',
|
||||
'Redis',
|
||||
'Docker',
|
||||
'Sealos',
|
||||
'Nginx',
|
||||
'Cloudflare',
|
||||
|
||||
// 数据处理
|
||||
'数据集',
|
||||
'Dataset',
|
||||
'文档导入',
|
||||
'数据处理',
|
||||
'索引模型',
|
||||
'重排模型',
|
||||
'分块策略',
|
||||
'增强处理',
|
||||
'问答拆分',
|
||||
'向量化',
|
||||
'文本分割',
|
||||
'知识结构化',
|
||||
'自动索引',
|
||||
'图片标注',
|
||||
'OCR识别',
|
||||
|
||||
// 集成相关
|
||||
'Webhook',
|
||||
'第三方集成',
|
||||
'企业微信',
|
||||
'钉钉',
|
||||
'DingTalk',
|
||||
'飞书',
|
||||
'Feishu',
|
||||
'Lark',
|
||||
'微信公众号',
|
||||
|
||||
// 业务概念
|
||||
'沙盒',
|
||||
'Sandbox',
|
||||
'插件',
|
||||
'Plugin',
|
||||
'模板',
|
||||
'权限管理',
|
||||
'团队协作',
|
||||
'用户角色',
|
||||
'访问控制',
|
||||
'数据安全',
|
||||
'隐私保护',
|
||||
|
||||
// 界面元素
|
||||
'工作台',
|
||||
'Dashboard',
|
||||
'调试预览',
|
||||
'发布分享',
|
||||
'对话窗口',
|
||||
'聊天界面',
|
||||
'引用展示',
|
||||
'猜你想问',
|
||||
'文件上传',
|
||||
'表单配置',
|
||||
'系统配置',
|
||||
'模型配置',
|
||||
'参数设置',
|
||||
'高级编排',
|
||||
'简易模式',
|
||||
'专业模式',
|
||||
|
||||
// 搜索插件
|
||||
'Bing搜索',
|
||||
'Google搜索',
|
||||
'SearXNG搜索',
|
||||
'Doc2x插件',
|
||||
|
||||
// 文件格式
|
||||
'PDF',
|
||||
'Word',
|
||||
'Excel',
|
||||
'CSV',
|
||||
'TXT',
|
||||
'Markdown',
|
||||
'JSON',
|
||||
|
||||
// 部署运维
|
||||
'环境变量',
|
||||
'config.json',
|
||||
'配置文件',
|
||||
'负载均衡',
|
||||
'高可用',
|
||||
'容灾备份',
|
||||
'监控告警',
|
||||
'性能优化',
|
||||
'响应速度',
|
||||
'并发处理',
|
||||
'缓存机制',
|
||||
|
||||
// 多语言
|
||||
'i18n',
|
||||
'国际化',
|
||||
'中文',
|
||||
'英文',
|
||||
'日文',
|
||||
'多语言支持',
|
||||
|
||||
// 版本管理
|
||||
'版本更新',
|
||||
'升级指南',
|
||||
'更新日志',
|
||||
'兼容性',
|
||||
'迁移指南'
|
||||
];
|
||||
|
||||
// 同义词配置 - 为整词添加相关的同义词
|
||||
const synonymsMap: Record<string, string[]> = {
|
||||
// 产品版本相关
|
||||
开源版: ['社区版', '开源', '开源版', '免费版'],
|
||||
商业版: ['商业版', '付费版', '企业版', '专业版', '标准版', '高级版'],
|
||||
社区版: ['社区版', '开源版', '免费版'],
|
||||
企业版: ['企业版', '商业版', '付费版', '专业版'],
|
||||
|
||||
// 核心功能
|
||||
知识库: ['知识库', '知识体系', '数据库', '文档库', '资料库', '信息库', '语料库'],
|
||||
工作流: ['工作流', '流程', '工作流程', '业务流程', '可视化流程', '流程图', '编排', '组合'],
|
||||
应用构建: ['应用构建', '应用搭建', '应用创建', '搭建', '构建', '创建应用'],
|
||||
对话管理: ['对话管理', '聊天管理', '会话管理', '对话控制'],
|
||||
|
||||
// AI相关
|
||||
AI: ['AI', '人工智能', '机器学习', '深度学习', '智能', '智能化'],
|
||||
大语言模型: ['大语言模型', 'LLM', '语言模型', '大模型', '生成式AI', '对话模型'],
|
||||
Agent: ['Agent', '智能体', '代理', '智能助手', 'AI助理', '机器人'],
|
||||
提示词: ['提示词', 'Prompt', '指令', '命令', '提示', '指示'],
|
||||
|
||||
// 技术概念
|
||||
API: ['API', '接口', '接口调用', '应用程序接口', '集成接口', '外部接口'],
|
||||
向量数据库: ['向量数据库', '向量存储', '向量索引', 'Vector Database'],
|
||||
语义搜索: [
|
||||
'语义搜索',
|
||||
'语义检索',
|
||||
'智能检索',
|
||||
'相似度搜索',
|
||||
'向量搜索',
|
||||
'检索系统',
|
||||
'搜索引擎'
|
||||
],
|
||||
RAG: ['RAG', '检索增强生成', '检索增强', '知识检索'],
|
||||
|
||||
// 数据处理
|
||||
数据集: ['数据集', 'Dataset', '数据源', '数据', '资料'],
|
||||
文档导入: ['文档导入', '文件导入', '数据导入', '批量导入', '上传文档'],
|
||||
数据处理: ['数据处理', '文档处理', '内容处理', '文件解析', '信息提取', '结构化处理'],
|
||||
向量化: ['向量化', 'embedding', '向量转换', '特征提取'],
|
||||
|
||||
// 界面相关
|
||||
工作台: ['工作台', 'Dashboard', '控制台', '管理台', '操作台', '仪表板'],
|
||||
调试预览: ['调试预览', '预览', '调试', '测试', '试运行'],
|
||||
发布分享: ['发布分享', '发布', '分享', '部署', '上线'],
|
||||
|
||||
// 插件相关
|
||||
插件: ['插件', 'Plugin', '扩展', '组件', '模块', '附加功能', '外部工具', '第三方工具'],
|
||||
搜索插件: ['搜索插件', '搜索工具', '搜索扩展', '网络搜索'],
|
||||
|
||||
// 集成相关
|
||||
第三方集成: ['第三方集成', '外部集成', '平台集成', '系统对接', '接口集成'],
|
||||
企业微信: ['企业微信', '企微', 'WeWork'],
|
||||
钉钉: ['钉钉', 'DingTalk', '阿里钉钉'],
|
||||
飞书: ['飞书', 'Feishu', 'Lark', '字节飞书'],
|
||||
|
||||
// 权限管理
|
||||
权限管理: ['权限管理', '访问控制', '用户权限', '权限控制', '授权管理'],
|
||||
团队协作: ['团队协作', '多人协作', '协同工作', '团队管理'],
|
||||
用户角色: ['用户角色', '角色管理', '权限角色', '用户权限'],
|
||||
|
||||
// 安全相关
|
||||
数据安全: ['数据安全', '信息安全', '数据保护', '安全防护'],
|
||||
隐私保护: ['隐私保护', '数据隐私', '信息保护', '隐私安全'],
|
||||
访问控制: ['访问控制', '权限控制', '访问权限', '安全认证'],
|
||||
|
||||
// 部署相关
|
||||
Docker: ['Docker', '容器', '容器化', '镜像部署'],
|
||||
环境变量: ['环境变量', '配置变量', '系统变量', '环境配置'],
|
||||
配置文件: ['配置文件', '配置', '设置文件', 'config'],
|
||||
|
||||
// 性能相关
|
||||
性能优化: ['性能优化', '系统优化', '速度提升', '效率优化', '性能调优'],
|
||||
响应速度: ['响应速度', '响应时间', '处理速度', '执行速度'],
|
||||
并发处理: ['并发处理', '并发', '多线程', '高并发'],
|
||||
缓存机制: ['缓存机制', '缓存', '内存缓存', '数据缓存'],
|
||||
|
||||
// 多语言
|
||||
国际化: ['国际化', 'i18n', '多语言', '本地化'],
|
||||
多语言支持: ['多语言支持', '多语言', '国际化支持', '语言切换'],
|
||||
|
||||
// 版本管理
|
||||
版本更新: ['版本更新', '系统更新', '功能更新', '补丁更新', '版本升级'],
|
||||
升级指南: ['升级指南', '更新指南', '迁移指南', '升级说明'],
|
||||
更新日志: ['更新日志', '版本日志', '修改日志', '发布日志'],
|
||||
|
||||
// 工作流节点
|
||||
AI对话: ['AI对话', 'AI聊天', '智能对话', '机器人对话'],
|
||||
知识库搜索: ['知识库搜索', '文档搜索', '资料搜索', '内容搜索'],
|
||||
问题分类: ['问题分类', '意图识别', '分类器', '问题识别'],
|
||||
内容提取: ['内容提取', '信息提取', '文本提取', '数据提取'],
|
||||
用户选择: ['用户选择', '选择器', '用户输入', '交互选择'],
|
||||
表单输入: ['表单输入', '用户输入', '数据输入', '信息收集'],
|
||||
文档解析: ['文档解析', '文件解析', '内容解析', '格式转换'],
|
||||
代码运行: ['代码运行', '代码执行', '脚本执行', '沙盒执行'],
|
||||
工具调用: ['工具调用', '函数调用', 'Function Call', 'API调用']
|
||||
};
|
||||
|
||||
const baseTokenizer = createTokenizer();
|
||||
|
||||
return {
|
||||
...baseTokenizer,
|
||||
tokenize: (text: string) => {
|
||||
// 先处理整词,用特殊标记保护它们
|
||||
let processedText = text;
|
||||
const protectedTokens = new Map();
|
||||
let tokenIndex = 0;
|
||||
|
||||
wholeWords.forEach((word) => {
|
||||
const regex = new RegExp(`\\b${word}\\b`, 'gi');
|
||||
processedText = processedText.replace(regex, (match) => {
|
||||
const placeholder = `__PROTECTED_TOKEN_${tokenIndex}__`;
|
||||
protectedTokens.set(placeholder, match.toLowerCase());
|
||||
tokenIndex++;
|
||||
return placeholder;
|
||||
});
|
||||
});
|
||||
|
||||
// 用基础分词器处理
|
||||
let tokens = baseTokenizer.tokenize(processedText);
|
||||
|
||||
// 恢复被保护的整词,并添加同义词
|
||||
tokens = tokens
|
||||
.map((token) => {
|
||||
if (protectedTokens.has(token)) {
|
||||
const originalWord = protectedTokens.get(token);
|
||||
return synonymsMap[originalWord] || [originalWord];
|
||||
}
|
||||
return token;
|
||||
})
|
||||
.flat();
|
||||
|
||||
return [...new Set(tokens)]; // 去重
|
||||
}
|
||||
};
|
||||
};
|
@@ -1,92 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
// 从 mdx 文件中读取 weight
|
||||
async function getWeightFromFile(filePath) {
|
||||
const content = await fs.readFile(filePath, 'utf-8');
|
||||
const weightMatch = content.match(/weight:\s*(\d+)/);
|
||||
return weightMatch ? parseInt(weightMatch[1], 10) : 0;
|
||||
}
|
||||
|
||||
// 从 meta.json 中读取最小 weight(用于子目录)
|
||||
async function getWeightFromMeta(dir) {
|
||||
const metaPath = path.join(dir, 'meta.json');
|
||||
if (!(await fs.pathExists(metaPath))) return Infinity;
|
||||
|
||||
try {
|
||||
const meta = await fs.readJson(metaPath);
|
||||
const pages = meta.pages || [];
|
||||
let minWeight = Infinity;
|
||||
|
||||
for (const pageName of pages) {
|
||||
const mdxPath = path.join(dir, `${pageName}.mdx`);
|
||||
if (await fs.pathExists(mdxPath)) {
|
||||
const w = await getWeightFromFile(mdxPath);
|
||||
if (w < minWeight) minWeight = w;
|
||||
}
|
||||
}
|
||||
return minWeight === Infinity ? 0 : minWeight;
|
||||
} catch {
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
// 主函数,返回当前目录的最小 weight
|
||||
async function generateMetaRecursive(dir) {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
const items = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
const fullPath = path.join(dir, entry.name);
|
||||
|
||||
if (entry.isDirectory()) {
|
||||
const subWeight = await generateMetaRecursive(fullPath);
|
||||
items.push({ name: entry.name, weight: subWeight });
|
||||
} else if (
|
||||
entry.isFile() &&
|
||||
entry.name.endsWith('.mdx') &&
|
||||
!entry.name.endsWith('.en.mdx')
|
||||
) {
|
||||
const nameWithoutExt = entry.name.replace(/\.mdx$/, '');
|
||||
const weight = await getWeightFromFile(fullPath);
|
||||
items.push({ name: nameWithoutExt, weight });
|
||||
}
|
||||
}
|
||||
|
||||
// 排序 pages
|
||||
items.sort((a, b) => a.weight - b.weight);
|
||||
const pages = items.map((item) => item.name);
|
||||
|
||||
// 读取或创建 meta.json
|
||||
const metaPath = path.join(dir, 'meta.json');
|
||||
let meta = {
|
||||
title: 'FastGPT',
|
||||
description: 'FastGPT Docs',
|
||||
};
|
||||
|
||||
if (await fs.pathExists(metaPath)) {
|
||||
try {
|
||||
meta = await fs.readJson(metaPath);
|
||||
} catch {
|
||||
console.warn(`⚠️ Failed to parse existing meta.json at ${metaPath}, using defaults.`);
|
||||
}
|
||||
}
|
||||
|
||||
meta.pages = pages;
|
||||
|
||||
// 写入 meta.json,格式化为一行的 pages
|
||||
const jsonString = JSON.stringify(meta, null, 2);
|
||||
const oneLinePages = `"pages": ${JSON.stringify(pages)}`;
|
||||
const finalJson = jsonString.replace(/"pages": \[[\s\S]*?\]/, oneLinePages);
|
||||
await fs.writeFile(metaPath, finalJson, 'utf-8');
|
||||
console.log(`✅ Updated meta.json in ${dir}`);
|
||||
|
||||
return items.length > 0 ? items[0].weight : 0;
|
||||
}
|
||||
|
||||
// 启动
|
||||
const targetDir = './content/docs/introduction/development/upgrading';
|
||||
|
||||
generateMetaRecursive(targetDir)
|
||||
.then(() => console.log('🎉 All meta.json files generated/updated!'))
|
||||
.catch((err) => console.error(err));
|
@@ -1,59 +0,0 @@
|
||||
import fs from 'fs-extra';
|
||||
import path from 'path';
|
||||
|
||||
async function generateMeta(dir) {
|
||||
const entries = await fs.readdir(dir, { withFileTypes: true });
|
||||
|
||||
const pages = [];
|
||||
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
pages.push(entry.name);
|
||||
} else if (
|
||||
entry.isFile() &&
|
||||
entry.name.endsWith('.mdx') &&
|
||||
!entry.name.endsWith('.en.mdx')
|
||||
) {
|
||||
const nameWithoutExt = entry.name.replace(/\.mdx$/, '');
|
||||
pages.push(nameWithoutExt);
|
||||
}
|
||||
}
|
||||
|
||||
const metaPath = path.join(dir, 'meta.json');
|
||||
|
||||
// 使用 JSON.stringify,spaces设为2,数组不换行
|
||||
// 通过 replacer 参数实现“pages”数组一行
|
||||
const jsonString = JSON.stringify(
|
||||
{ pages },
|
||||
(key, value) => {
|
||||
if (key === 'pages') {
|
||||
return value; // 保持pages数组原样
|
||||
}
|
||||
return value;
|
||||
},
|
||||
2
|
||||
);
|
||||
|
||||
// 手动替换 pages 数组换行,变成一行显示
|
||||
const oneLinePages = `"pages": ${JSON.stringify(pages)}`;
|
||||
const finalJson = jsonString.replace(
|
||||
/"pages": \[[^\]]*\]/,
|
||||
oneLinePages
|
||||
);
|
||||
|
||||
await fs.writeFile(metaPath, finalJson, 'utf-8');
|
||||
console.log(`Generated meta.json in ${dir}`);
|
||||
|
||||
// 递归处理子目录
|
||||
for (const entry of entries) {
|
||||
if (entry.isDirectory()) {
|
||||
await generateMeta(path.join(dir, entry.name));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
const targetDir = './content/docs/development/openapi';
|
||||
|
||||
generateMeta(targetDir)
|
||||
.then(() => console.log('All meta.json files generated!'))
|
||||
.catch((err) => console.error(err));
|
30
document/package-lock.json
generated
30
document/package-lock.json
generated
@@ -11,7 +11,6 @@
|
||||
"dependencies": {
|
||||
"@orama/orama": "^3.1.11",
|
||||
"@orama/tokenizers": "^3.1.11",
|
||||
"algoliasearch": "^5.34.0",
|
||||
"fast-glob": "^3.3.3",
|
||||
"fs-extra": "^11.3.0",
|
||||
"fumadocs-core": "15.6.3",
|
||||
@@ -47,6 +46,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-abtesting/-/client-abtesting-5.34.0.tgz",
|
||||
"integrity": "sha512-d6ardhDtQsnMpyr/rPrS3YuIE9NYpY4rftkC7Ap9tyuhZ/+V3E/LH+9uEewPguKzVqduApdwJzYq2k+vAXVEbQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -62,6 +63,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-analytics/-/client-analytics-5.34.0.tgz",
|
||||
"integrity": "sha512-WXIByjHNA106JO1Dj6b4viSX/yMN3oIB4qXr2MmyEmNq0MgfuPfPw8ayLRIZPa9Dp27hvM3G8MWJ4RG978HYFw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -77,6 +80,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-common/-/client-common-5.34.0.tgz",
|
||||
"integrity": "sha512-JeN1XJLZIkkv6yK0KT93CIXXk+cDPUGNg5xeH4fN9ZykYFDWYRyqgaDo+qvg4RXC3WWkdQ+hogQuuCk4Y3Eotw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"engines": {
|
||||
"node": ">= 14.0.0"
|
||||
}
|
||||
@@ -86,6 +91,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-insights/-/client-insights-5.34.0.tgz",
|
||||
"integrity": "sha512-gdFlcQa+TWXJUsihHDlreFWniKPFIQ15i5oynCY4m9K3DCex5g5cVj9VG4Hsquxf2t6Y0yv8w6MvVTGDO8oRLw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -101,6 +108,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-personalization/-/client-personalization-5.34.0.tgz",
|
||||
"integrity": "sha512-g91NHhIZDkh1IUeNtsUd8V/ZxuBc2ByOfDqhCkoQY3Z/mZszhpn3Czn6AR5pE81fx793vMaiOZvQVB5QttArkQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -116,6 +125,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-query-suggestions/-/client-query-suggestions-5.34.0.tgz",
|
||||
"integrity": "sha512-cvRApDfFrlJ3Vcn37U4Nd/7S6T8cx7FW3mVLJPqkkzixv8DQ/yV+x4VLirxOtGDdq3KohcIbIGWbg1QuyOZRvQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -131,6 +142,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/client-search/-/client-search-5.34.0.tgz",
|
||||
"integrity": "sha512-m9tK4IqJmn+flEPRtuxuHgiHmrKV0su5fuVwVpq8/es4DMjWMgX1a7Lg1PktvO8AbKaTp9kTtBAPnwXpuCwmEg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -146,6 +159,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/ingestion/-/ingestion-1.34.0.tgz",
|
||||
"integrity": "sha512-2rxy4XoeRtIpzxEh5u5UgDC5HY4XbNdjzNgFx1eDrfFkSHpEVjirtLhISMy2N5uSFqYu1uUby5/NC1Soq8J7iw==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -161,6 +176,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/monitoring/-/monitoring-1.34.0.tgz",
|
||||
"integrity": "sha512-OJiDhlJX8ZdWAndc50Z6aUEW/YmnhFK2ul3rahMw5/c9Damh7+oY9SufoK2LimJejy+65Qka06YPG29v2G/vww==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -176,6 +193,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/recommend/-/recommend-5.34.0.tgz",
|
||||
"integrity": "sha512-fzNQZAdVxu/Gnbavy8KW5gurApwdYcPW6+pjO7Pw8V5drCR3eSqnOxSvp79rhscDX8ezwqMqqK4F3Hsq+KpRzg==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0",
|
||||
"@algolia/requester-browser-xhr": "5.34.0",
|
||||
@@ -191,6 +210,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-browser-xhr/-/requester-browser-xhr-5.34.0.tgz",
|
||||
"integrity": "sha512-gEI0xjzA/xvMpEdYmgQnf6AQKllhgKRtnEWmwDrnct+YPIruEHlx1dd7nRJTy/33MiYcCxkB4khXpNrHuqgp3Q==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0"
|
||||
},
|
||||
@@ -203,6 +224,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-fetch/-/requester-fetch-5.34.0.tgz",
|
||||
"integrity": "sha512-5SwGOttpbACT4jXzfSJ3mnTcF46SVNSnZ1JjxC3qBa3qKi4U0CJGzuVVy3L798u8dG5H0SZ2MAB5v7180Gnqew==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0"
|
||||
},
|
||||
@@ -215,6 +238,8 @@
|
||||
"resolved": "https://registry.npmjs.org/@algolia/requester-node-http/-/requester-node-http-5.34.0.tgz",
|
||||
"integrity": "sha512-409XlyIyEXrxyGjWxd0q5RASizHSRVUU0AXPCEdqnbcGEzbCgL1n7oYI8YxzE/RqZLha+PNwWCcTVn7EE5tyyQ==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-common": "5.34.0"
|
||||
},
|
||||
@@ -1466,7 +1491,6 @@
|
||||
"version": "3.1.11",
|
||||
"resolved": "https://registry.npmjs.org/@orama/tokenizers/-/tokenizers-3.1.11.tgz",
|
||||
"integrity": "sha512-fwULrEdbP5/83gFjaX1X/l7lzdD7LxBT8YbAzcY89BmXjJcJETU/5qckp4ZNDMhRRjJUSGKH4bAXHsm6yu+ZPw==",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"@orama/orama": "3.1.11"
|
||||
},
|
||||
@@ -2723,6 +2747,8 @@
|
||||
"resolved": "https://registry.npmjs.org/algoliasearch/-/algoliasearch-5.34.0.tgz",
|
||||
"integrity": "sha512-wioVnf/8uuG8Bmywhk5qKIQ3wzCCtmdvicPRb0fa3kKYGGoewfgDqLEaET1MV2NbTc3WGpPv+AgauLVBp1nB9A==",
|
||||
"license": "MIT",
|
||||
"optional": true,
|
||||
"peer": true,
|
||||
"dependencies": {
|
||||
"@algolia/client-abtesting": "5.34.0",
|
||||
"@algolia/client-analytics": "5.34.0",
|
||||
|
@@ -4,8 +4,6 @@
|
||||
"private": true,
|
||||
"scripts": {
|
||||
"build": "next build",
|
||||
"update-index-action": "node ./update-index.mjs",
|
||||
"update-index": "node --env-file=.env.local ./update-index.mjs",
|
||||
"dev": "next dev --turbo",
|
||||
"start": "next start",
|
||||
"postinstall": "fumadocs-mdx"
|
||||
@@ -13,7 +11,6 @@
|
||||
"dependencies": {
|
||||
"@orama/orama": "^3.1.11",
|
||||
"@orama/tokenizers": "^3.1.11",
|
||||
"algoliasearch": "^5.34.0",
|
||||
"fast-glob": "^3.3.3",
|
||||
"fs-extra": "^11.3.0",
|
||||
"fumadocs-core": "15.6.3",
|
||||
|
@@ -1,28 +0,0 @@
|
||||
import { algoliasearch } from 'algoliasearch';
|
||||
import { sync } from 'fumadocs-core/search/algolia';
|
||||
import * as fs from 'node:fs';
|
||||
|
||||
async function main() {
|
||||
const content = fs.readFileSync('.next/server/app/static.json.body');
|
||||
|
||||
// now you can pass it to `sync`
|
||||
/** @type {import('fumadocs-core/search/algolia').DocumentRecord[]} **/
|
||||
const records = JSON.parse(content.toString());
|
||||
|
||||
if (!process.env.NEXT_PUBLIC_SEARCH_APPID || !process.env.SEARCH_APPWRITEKEY || !process.env.SEARCH_APPWRITEKEY) {
|
||||
console.log('NEXT_PUBLIC_SEARCH_APPID or SEARCH_APPWRITEKEY is not set');
|
||||
return;
|
||||
}
|
||||
|
||||
const client = algoliasearch(
|
||||
process.env.NEXT_PUBLIC_SEARCH_APPID || '',
|
||||
process.env.SEARCH_APPWRITEKEY || ''
|
||||
);
|
||||
|
||||
void sync(client, {
|
||||
indexName: 'document',
|
||||
documents: records
|
||||
});
|
||||
}
|
||||
|
||||
main();
|
Reference in New Issue
Block a user