CSDN博客-星火知识库教程

【超详细】微信小程序对接讯飞星火知识库:文档上传、向量化、萃取 QA、流式问答从零到上线

摘要 :本文以可运行的微信小程序项目 xinghuo 为例,按 CSDN 教程体例,逐步拆解 讯飞 星火知识库 ChatDoc API 的完整链路:鉴权 → 文档上传 → 向量化轮询 → 知识库 → 文档萃取(QA)→ WebSocket 流式问答 。包含官方接口请求/响应示例、与 Java/Python Demo 对照、完整小程序源码说明 、域名配置、以及笔者在实际开发中遇到的 405 / 60005 / 域名不合法 等问题的排查过程。
建议收藏,适合准备做 RAG、企业知识库问答、展会手册/ PDF 智能客服的开发者。

标签微信小程序 讯飞星火 星火知识库 ChatDoc RAG 文档问答 WebSocket 知识萃取

官方文档星火知识库 API 文档
官方 Python Demochatdoc-api-python-demo.zip


目录

  • 零、读完本文你能做什么
  • [一、先搞清楚:网页上传 ≠ API 闭环](#一、先搞清楚:网页上传 ≠ API 闭环)
  • [二、核心概念:fileId、repoId、libId 一文讲透](#二、核心概念:fileId、repoId、libId 一文讲透)
  • 三、环境准备与开通(带操作清单)
  • [四、鉴权算法:逐行实现 + 两大坑](#四、鉴权算法:逐行实现 + 两大坑)
  • [五、接口详解①:文档上传 file/upload](#五、接口详解①:文档上传 file/upload)
  • [六、接口详解②:文档状态 file/status(向量化)](#六、接口详解②:文档状态 file/status(向量化))
  • [七、接口详解③:知识库 repo](#七、接口详解③:知识库 repo)
  • [八、接口详解④:文档萃取 qa/extract 全链路](#八、接口详解④:文档萃取 qa/extract 全链路)
  • [九、接口详解⑤:WebSocket 文档问答](#九、接口详解⑤:WebSocket 文档问答)
  • [十、接口详解⑥:文档列表 file/list](#十、接口详解⑥:文档列表 file/list)
  • 十一、端到端时序:上传→萃取→问答
  • 十二、微信小程序项目结构
  • [十三、配置文件 config.js 逐项说明](#十三、配置文件 config.js 逐项说明)
  • [十四、utils 工具层源码精读](#十四、utils 工具层源码精读)
  • [十五、页面层:文档列表页 files](#十五、页面层:文档列表页 files)
  • [十六、页面层:问答页 index](#十六、页面层:问答页 index)
  • 十七、微信域名与开发者工具设置
  • 十八、错误大全:现象→原因→解决
  • [十九、自测 Checklist](#十九、自测 Checklist)
  • 二十、上线与安全建议
  • 二十一、总结
  • [附录 A:官方错误码表](#附录 A:官方错误码表)
  • [附录 B:完整项目目录树](#附录 B:完整项目目录树)

零、读完本文你能做什么

完成本文实践后,你可以:

  1. 微信小程序 里选择 PDF/Word,调用 API 上传到讯飞知识库(不依赖 chatdoc 网页后台手工传文件)。
  2. 自动轮询向量化 ,直到文档状态为 vectored
  3. 自动发起文档萃取 ,生成 QA 对,并 qa/apply 写入知识库(无 repoId 时可自动建库)。
  4. 在聊天页基于该文档 WebSocket 流式问答 ,支持多轮对话、qaMode: MIX 混合检索。
  5. file/list 核对当前 APP_ID 下有哪些文档,避免「无文件权限」。

最终效果类似:上传《参展商手册》→ 自动萃取几十上百条 QA → 用户问「如何报名参展」→ 基于手册流式回答。


一、先搞清楚:网页上传 ≠ API 闭环

1.1 两种上传方式对比

对比项 网页 chatdoc.xfyun.cn API file/upload(本文)
操作入口 浏览器可视化 小程序 / 服务端代码
归属关系 必须属于某个开放平台应用 同上,Header 里带 appId
得到的 ID 页面展示 文件ID 响应 JSON 的 data.fileId
是否自动萃取 网页可能有单独按钮,与 API 无关 需主动调 qa/extract
适用场景 体验、运营手工维护 产品化、自动化、小程序闭环

1.2 为什么网页上的 fileId 在小程序里报错?

典型报错:

text 复制代码
code: 60005
message: 您没有文件权限

原因 :你在 config.js 里填的 APP_ID(例如 d87f81de)与网页上传时登录账号绑定的不是同一个应用

讯飞侧权限模型是:fileId 从属于创建它的 appId,不能跨应用借用。

正确做法

  • 要么:网页与小程序统一同一个应用的 APPID;
  • 要么:只在小程序里用 API 上传 ,用 file/list 查本应用下的 fileId。

1.3 创建应用时没有「星火知识库」分类?

正常现象。流程是:

  1. 控制台 → 创建应用(分类选「企业服务 / 教育 / 其他」均可);
  2. 进入该应用 → 能力列表 → 开通 星火知识库 / 文档问答
  3. 复制 APPID、APISecretconfig.js

详见 讯飞快速指引


二、核心概念:fileId、repoId、libId 一文讲透

这是全文最容易踩坑的部分,请务必理解。

2.1 三个 ID 对照表

名称 示例 来源 用于 API 字段 常见误用
fileId a90c49dcc76f4a9a82bdcc562c512bb6 上传接口返回 / 文档列表 / 网页「文件ID」 fileIds: ['...'] 填进 REPO_ID → 报「知识库不存在」
repoId 8e9f5da278c24f08880e5b0380626b85(32位UUID) repo/createrepo/list repoId: '...' 与 fileId 混用
libId(网页) 19855 URL doc-detail?libId=19855 不能用于 API 当成 repoId

2.2 问答时传 fileIds 还是 repoId?

官方要求:repoIdrepoIdsfileIds 三者必填其一

模式 配置 行为
单文档问答 FILE_IDS: ['fileId'] 只检索该 PDF
知识库问答 REPO_ID: 'repoId' 检索库内多文档 + 已 apply 的 QA
本项目存储 wx.setStorageSync('ACTIVE_FILE_IDS') 上传后自动写入,优先于 config

本项目逻辑:若存在 ACTIVE_REPO_ID,问答只传 repoId ;否则传 fileIds

2.3 文档状态机(必须等 vectored)

复制代码
uploaded → texted → ocring → spliting → splited → vectoring → vectored
                                                      ↓
                                                   failed
状态 含义 能否问答 能否萃取
uploaded 已上传
vectoring 向量化中
vectored 已向量化
failed 失败

上传接口不会立刻返回 vectored ,必须轮询 file/status


三、环境准备与开通(带操作清单)

3.1 账号与资质

  • 注册 讯飞开放平台
  • 完成实名认证(部分能力需认证后可见)
  • 创建应用,开通 星火知识库,领取免费额度

3.2 微信小程序

  • 注册小程序,获取 AppID(微信的,与讯飞 APPID 不同)
  • 安装 微信开发者工具
  • 导入本项目,填写自己的讯飞 config.js

3.3 服务器域名(上线必做)

登录 微信公众平台 → 开发管理 → 开发设置 → 服务器域名:

类型 填写
request 合法域名 https://chatdoc.xfyun.cn
socket 合法域名 wss://chatdoc.xfyun.cn

开发调试 :开发者工具 → 详情 → 本地设置 → 勾选 「不校验合法域名...」 ;项目 project.private.config.json"urlCheck": false

【建议配图】微信公众平台「服务器域名」配置页截图。

3.4 下载官方 Demo 对照

Python Demo 中鉴权、上传、问答 URL 与本文一致,建议下载对照调试:

https://openres.xfyun.cn/xfyundoc/2024-08-20/e1c9e232-ee6d-495e-a3ce-af7ea60648e8/1724123967360/chatdoc-api-python-demo.zip


四、鉴权算法:逐行实现 + 两大坑

文档章节:二、鉴权认证

4.1 算法步骤(与 Java 官方一致)

text 复制代码
输入:appId(字符串), secret(APISecret), timestamp(秒,long)

Step1: auth = MD5( appId + timestamp )   // 拼接后做 MD5,32位小写 hex,无盐
Step2: signature = Base64( HmacSHA1( auth, secret ) )  // auth 为消息,secret 为密钥

Python 官方写法Document_Q_And_A.py):

python 复制代码
m2 = hashlib.md5()
data = bytes(self.appId + self.timeStamp, encoding="utf-8")
m2.update(data)
checkSum = m2.hexdigest()

signature = hmac.new(
    self.apiSecret.encode('utf-8'),
    signature_origin.encode('utf-8'),
    digestmod=hashlib.sha1
).digest()
signature = base64.b64encode(signature).decode(encoding='utf-8')

4.2 坑①:WebSocket 的 signature 不要做 URL 编码

官方 Demo 注释原文:

python 复制代码
# 使用urlencode会导致签名乱码
return self.originUrl + "?" + f'appId={self.appId}&timestamp={self.timeStamp}&signature={signature}'

错误写法(会 405 Invalid Signature):

javascript 复制代码
`signature=${encodeURIComponent(signature)}`  // ❌

正确写法:

javascript 复制代码
`wss://chatdoc.xfyun.cn/openapi/chat?appId=${appId}&timestamp=${timestamp}&signature=${signature}`

4.3 坑②:secret 填错字段

控制台字段 是否用于 ChatDoc
APISecret ✅ 填到 APP_SECRET
APIKey ❌ 常用于其他星火接口,勿混淆

4.4 小程序完整实现(utils/auth.js 核心)

javascript 复制代码
function getSignature(appId, secret, timestamp) {
  const auth = md5(String(appId) + String(timestamp))
  return hmacSha1Base64(auth, secret)
}

function getAuthHeaders(appId, secret) {
  const timestamp = Math.floor(Date.now() / 1000)
  return {
    appId,
    timestamp: String(timestamp),
    signature: getSignature(appId, secret, timestamp)
  }
}

function buildChatWsUrl(appId, secret) {
  const timestamp = Math.floor(Date.now() / 1000)
  const signature = getSignature(appId, secret, timestamp)
  return `wss://chatdoc.xfyun.cn/openapi/chat?appId=${appId}&timestamp=${timestamp}&signature=${signature}`
}

HTTP 类接口(上传、列表、萃取)在 Header 中带 appIdtimestampsignature 即可。

4.5 鉴权失败 HTTP 状态码

HTTP Code 说明
401 参数缺失、签名解析失败、签名校验失败
403 时间戳偏差超过 5 分钟
405 应用无效 / Invalid Signature

五、接口详解①:文档上传 file/upload

文档:3.1 文档上传

5.1 基本信息

URL POST https://chatdoc.xfyun.cn/openapi/v1/file/upload
Content-Type multipart/form-data
鉴权 Header:appId, timestamp, signature

5.2 表单字段说明

字段 必须 说明
file 与 url 二选一 文件流 小程序 wx.uploadFilename 必须为 file
fileType Y wiki 固定值
parseType Y AUTO 智能判断是否 OCR;可选 TEXT / OCR
stepByStep N false true 时仅分片,需再调 embedding;一般传 false
url N 文件 URL 与 file 二选一
fileName 用 url 时必传 带后缀文件名 本地 file 上传可不传

限制:doc/docx、pdf、md、txt ;≤ 20MB ;≤ 100 万字符

5.3 成功响应示例

json 复制代码
{
  "code": 0,
  "sid": "",
  "desc": null,
  "data": {
    "fileId": "",
    "quantity": "12",
    "parseType": "TEXT"
  }
}

立即记录 data.fileId,后续所有接口都依赖它。

5.4 小程序:选文件 + 上传

选文件(从微信聊天记录选 PDF 等):

javascript 复制代码
wx.chooseMessageFile({
  count: 1,
  type: 'file',
  extension: ['pdf', 'doc', 'docx', 'txt', 'md'],
  success(res) {
    const file = res.tempFiles[0]
    // file.path  临时路径
    // file.name  文件名
    // file.size  字节数,需 <= 20*1024*1024
  }
})

上传utils/api.jsuploadFile):

javascript 复制代码
wx.uploadFile({
  url: 'https://chatdoc.xfyun.cn/openapi/v1/file/upload',
  filePath: filePath,
  name: 'file',
  formData: {
    fileType: 'wiki',
    parseType: 'AUTO',
    stepByStep: 'false'
  },
  header: getAuthHeaders(appId, secret),
  success(res) {
    const body = JSON.parse(res.data)
    if (body.code === 0) {
      const fileId = body.data.fileId
    }
  }
})

5.5 封装函数 uploadDocument(utils/file.js)

javascript 复制代码
function uploadDocument(appId, secret, filePath, fileName) {
  return uploadFile('/openapi/v1/file/upload', {
    appId,
    secret,
    filePath,
    formData: {}
  }).then(data => ({
    fileId: data.fileId,
    parseType: data.parseType,
    quantity: data.quantity,
    fileName
  }))
}

六、接口详解②:文档状态 file/status(向量化)

文档:3.2 文档状态查询

6.1 基本信息

URL POST https://chatdoc.xfyun.cn/openapi/v1/file/status
Content-Type application/x-www-form-urlencoded
Body fileIds=id1fileIds=id1,id2

6.2 响应示例

json 复制代码
{
  "code": 0,
  "desc": "成功",
  "data": [
    {
      "fileId": "你的fileId",
      "fileStatus": "vectoring"
    }
  ]
}

6.3 轮询实现 waitUntilVectored

本项目策略:

  • 3 秒 查一次;
  • 最多 100 次(约 5 分钟);
  • vectored → resolve;failed → reject;否则 setTimeout 继续。
javascript 复制代码
function waitUntilVectored(appId, secret, fileId, options = {}) {
  const { interval = 3000, maxAttempts = 100, onProgress } = options
  let attempts = 0
  const poll = () => {
    attempts += 1
    return getFileStatus(appId, secret, fileId).then(list => {
      const item = list[0]
      onProgress && onProgress(item)
      if (item.fileStatus === 'vectored') return item
      if (item.fileStatus === 'failed') throw new Error('文档处理失败')
      if (attempts >= maxAttempts) throw new Error('处理超时')
      return new Promise(r => setTimeout(() => r(poll()), interval))
    })
  }
  return poll()
}

界面提示 :将 vectoring 显示为「向量化中」,避免用户以为卡死。


七、接口详解③:知识库 repo

文档:六、高级功能-知识库

7.1 何时需要知识库?

场景 是否需要 repoId
只问一本 PDF ❌,仅 fileIds 即可
多文档统一问答
萃取后 qa/apply 必填 (本项目无 repo 时自动 repo/create

7.2 创建知识库 repo/create

http 复制代码
POST https://chatdoc.xfyun.cn/openapi/v1/repo/create
Content-Type: application/json

{
  "repoName": "2026x'x'x",
  "repoDesc": "手册",
  "repoTags": "展会"
}

响应 data 即为 repoId(字符串 UUID)。

7.3 添加文件 repo/file/add

json 复制代码
{
  "repoId": "xxx",
  "fileIds": [""]
}

注意:文件须 vectored;单次最多 20 个 fileId。

7.4 小程序「创建知识库」

pages/files/files.jsonCreateRepo 弹窗输入名称 → 调用 createRepo → 结果存入 wx.setStorageSync('ACTIVE_REPO_ID', repoId)


八、接口详解④:文档萃取 qa/extract 全链路

文档:四、高级功能-文档萃取

8.1 重要:上传 ≠ 萃取

很多开发者以为「上传并向量化」后,网页上看到的「萃取」会自动完成。

实际上:

  • 向量化 :上传后服务端流水线自动做,查到 vectored 即可问答「原文片段」;
  • 萃取 :必须额外调用 /qa/extract ,才会生成 QA 对
  • 生效 :萃取结果要通过 /qa/apply 写入索引(且需要 repoId ),问答时 qaMode: MIX 才能用好 QA。

8.2 步骤 1:提交萃取任务

http 复制代码
POST https://chatdoc.xfyun.cn/openapi/v1/qa/extract
Content-Type: application/json

请求体:

json 复制代码
{
  "fileId": "你的fileId",
  "chunkSize": 2000,
  "numPerChunk": 2,
  "answerSize": 200,
  "includeAnswer": true
}
参数 说明
chunkSize 按多少字符分块再抽 QA
numPerChunk 每块约抽几个问题(非精确)
answerSize 答案长度上限(非精确)

前置条件:fileStatus === 'vectored'

响应 datataskId(也可后续用 fileId 查状态)。

8.3 步骤 2:轮询萃取状态

http 复制代码
GET https://chatdoc.xfyun.cn/openapi/v1/qa/extract/status?fileId=xxx

Header 仍需鉴权。

data 值 含义
UNSTARTED 未开始
EXTRACTING 萃取中(大 PDF 可能 数分钟
EXTRACTED 完成
FAILED 失败

本项目:每 4 秒轮询,最多 90 次。

8.4 步骤 3:获取萃取结果

http 复制代码
GET https://chatdoc.xfyun.cn/openapi/v1/qa/extract/result?fileId=xxx

响应 data 为数组:

json 复制代码
[
  {
    "id": "你的id",
    "question": "参展商如何办理证件?",
    "answer": "请携带......",
    "chunkIndexReferences": [1, 2, 3],
    "answerChunkIndexReferences": [1, 2, 3]
  }
]

8.5 步骤 4:应用 QA 对(关键)

http 复制代码
POST https://chatdoc.xfyun.cn/openapi/v1/qa/apply
json 复制代码
{
  "fileId": "你的fileId",
  "repoId": "你的知识库ID",
  "question": "参展商如何办理证件?",
  "answer": "请携带......",
  "embType": "QA"
}

fileId、repoId 均为必填。 本项目 ensureRepoId:若用户未配置 REPO_ID,自动 repo/create 再逐条 apply。

8.6 本项目自动化 runExtractPipeline(utils/extract.js)

text 复制代码
startExtract
  → waitUntilExtracted
  → getExtractResult
  → ensureRepoId(无则 createRepo)
  → addFilesToRepo(忽略失败)
  → applyAllQaPairs(递归逐条 apply)

上传时 uploadAndProcess 在向量化、加库之后,若 config.extract.enabled === true 自动执行上述流程。

已有文档未萃取 :列表页点 「萃取」 按钮,单独执行 runExtractPipeline

8.7 config.extract 配置项

javascript 复制代码
extract: {
  enabled: true,      // 上传完成后是否自动萃取
  chunkSize: 2000,
  numPerChunk: 2,     // 越大 QA 越多,耗时越长
  answerSize: 200,
  autoApply: true       // 是否自动 qa/apply
}

九、接口详解⑤:WebSocket 文档问答

文档:3.3 文档问答

9.1 连接 URL

text 复制代码
wss://chatdoc.xfyun.cn/openapi/chat?appId=xxx&timestamp=xxx&signature=xxx

使用 wx.connectSocket({ url })不要对 signature 做 encodeURIComponent。

9.2 连接成功后发送 JSON

json 复制代码
{
  "fileIds": ["a90c49dcc76f4a9a82bdcc562c512bb6"],
  "messages": [
    { "role": "user", "content": "展会开放时间是?" }
  ],
  "chatExtends": {
    "spark": true,
    "temperature": 0.5,
    "retrievalFilterPolicy": "REGULAR",
    "qaMode": "MIX"
  }
}

多轮对话示例:

json 复制代码
{
  "messages": [
    { "role": "user", "content": "如何理赔?" },
    { "role": "assistant", "content": "此前回答的完整内容......" },
    { "role": "user", "content": "家属有什么福利?" }
  ]
}

9.3 流式响应字段

json 复制代码
{
  "code": 0,
  "content": "根据手册,",
  "sid": "870b299a48ba46b6b5e4dfbd99fe4497",
  "status": 1
}
status 含义 客户端处理
0 首包 拼接 content
1 中间包 继续拼接
2 结束 关闭连接,结束 loading
99 文档引用 fileRefer 为 Map,可选展示

9.4 chatExtends 参数说明

字段 说明
spark 无文档匹配时是否用大模型兜底
temperature (0,1],越大越随机
retrievalFilterPolicy STRICT / REGULAR / LENIENT / OFF
qaMode QA_FIRST / QA_SUMMARY / MIX / WIKI_ONLY

萃取后建议 qaMode: 'MIX',同时参考 QA 对与 wiki 分片。

9.5 utils/chatdoc.js 核心逻辑

javascript 复制代码
const url = buildChatWsUrl(appId, secret)
const socketTask = wx.connectSocket({ url })

socketTask.onOpen(() => {
  socketTask.send({ data: JSON.stringify(payload) })
})

socketTask.onMessage((res) => {
  const data = JSON.parse(res.data)
  if (data.code !== 0) { /* 405/60005 等 */ }
  if (data.content) fullContent += data.content
  if (data.status === 2) onComplete({ content: fullContent })
})

十、接口详解⑥:文档列表 file/list

文档:5.8 文档列表

10.1 请求

http 复制代码
POST https://chatdoc.xfyun.cn/openapi/v1/file/list
Content-Type: application/json

{
  "currentPage": 1,
  "pageSize": 20,
  "fileName": "",
  "extName": "",
  "fileStatus": ""
}

10.2 响应(节选)

json 复制代码
{
  "code": 0,
  "data": {
    "total": 3,
    "rows": [
      {
        "fileId": "你的fileId",
        "fileName": "2026xxxxxx.pdf",
        "fileStatus": "vectored",
        "extName": "pdf",
        "quantity": 24
      }
    ]
  }
}

用途:确认 fileId 是否属于当前 APP_ID;复制 ID 到配置;查看是否已向量化。


十一、端到端时序:上传→萃取→问答

chatdoc.xfyun.cn 小程序 用户 chatdoc.xfyun.cn 小程序 用户 loop [每3秒] opt [配置了 REPO_ID] loop [每4秒] loop [每条 QA] 点击「上传文档」 POST /file/upload (multipart) fileId POST /file/status vectoring / vectored POST /repo/file/add POST /qa/extract GET /qa/extract/status EXTRACTING / EXTRACTED GET /qa/extract/result QA 列表 POST /qa/apply 存储 ACTIVE_FILE_IDS 输入问题 WebSocket /openapi/chat 流式 content (status 0,1,2)


十二、微信小程序项目结构

12.1 app.json 注册页面

json 复制代码
{
  "pages": [
    "pages/index/index",
    "pages/files/files",
    "pages/logs/logs"
  ],
  "window": {
    "navigationBarTitleText": "星火知识库问答"
  }
}

12.2 目录树(附录 B 有完整版)

text 复制代码
xinghuo/
├── config.js                 # 讯飞凭证、萃取、问答参数
├── config.example.js
├── pages/
│   ├── index/                # 流式问答 UI
│   └── files/                # 上传、列表、萃取
└── utils/
    ├── auth.js               # 鉴权
    ├── api.js                # HTTP / 上传 / GET
    ├── file.js               # 上传+向量化+总流程
    ├── extract.js            # 萃取+apply
    ├── repo.js               # 知识库
    └── chatdoc.js            # WebSocket 问答

十三、配置文件 config.js 逐项说明

javascript 复制代码
module.exports = {
  // 【必填】讯飞开放平台 → 星火知识库应用
  APP_ID: '你的APPID',
  APP_SECRET: '你的APISecret',

  // 【可选】已有知识库 ID,上传后 repo/file/add
  REPO_ID: '',

  // 【可选】固定文档;留空则走上传+本地存储
  FILE_IDS: [],

  // 【萃取】上传并向量化完成后自动执行
  extract: {
    enabled: true,
    chunkSize: 2000,
    numPerChunk: 2,
    answerSize: 200,
    autoApply: true
  },

  // 【问答】WebSocket chatExtends
  chatExtends: {
    spark: true,
    temperature: 0.5,
    retrievalFilterPolicy: 'REGULAR',
    qaMode: 'MIX'
  }
}

本地存储键(代码内,无需手写 config):

Key 含义
ACTIVE_FILE_IDS 当前问答用的 fileId 数组
ACTIVE_REPO_ID 当前问答用的 repoId(优先于 FILE_IDS)

十四、utils 工具层源码精读

14.1 api.js:三类 HTTP 封装

函数 用途
request JSON POST + 鉴权 Header
requestForm 表单 POST(file/status)
requestGet GET + query(萃取状态/结果)
uploadFile wx.uploadFile 封装

统一域名:https://chatdoc.xfyun.cn

14.2 file.js:uploadAndProcess 总控

javascript 复制代码
uploadDocument
  → waitUntilVectored
  → [可选] addFilesToRepo
  → [可选] runExtractPipeline

页面只调 uploadAndProcess,通过 onProgress 更新 uploadMessage 展示进度。

14.3 extract.js:萃取流水线

见第八章;applyAllQaPairs 顺序调用避免并发触发频控(错误码 68003 操作太过频繁)。

14.4 chatdoc.js:流式问答

注意 code !== 0 时即使 status === 2 也要走错误分支(业务错误包在最后一帧的情况)。


十五、页面层:文档列表页 files

15.1 功能清单

按钮/操作 调用
上传文档 chooseMessageFileuploadAndProcess
创建知识库 createRepo
刷新列表 getFileList
萃取 runExtractPipeline(仅 vectored)
使用 setStorage ACTIVE_FILE_IDS
按知识库问答 清除 FILE_IDS,保留 REPO_ID
去问答 navigateBack → index

15.2 上传进度文案示例

text 复制代码
准备上传...
正在上传...
上传成功,正在向量化...
切分中 / 向量化中
正在加入知识库...
正在提交萃取任务...
萃取中,请稍候...
正在将 QA 写入知识库...
正在应用 QA 3/28...

【建议配图】文档列表页:上传中、列表展示 fileId 与状态、萃取按钮。


十六、页面层:问答页 index

16.1 发送流程

  1. 用户输入 → _sendMessage
  2. getChatTargets() 取 repoId 或 fileIds
  3. 组装 messages(过滤 welcome、loading)
  4. chatWithKnowledge 建立 WebSocket
  5. onChunk 实时更新 assistant 气泡
  6. status === 2 结束 loading

16.2 入口

底部 「文档列表」wx.navigateTo('/pages/files/files')


十七、微信域名与开发者工具设置

17.1 两类域名缺一不可

能力 域名类型 域名
上传、列表、状态、萃取 request https://chatdoc.xfyun.cn
问答 WebSocket socket wss://chatdoc.xfyun.cn

只配 socket 不配 request → 上传报:

text 复制代码
https://chatdoc.xfyun.cn 不在以下 request 合法域名列表中

17.2 开发者工具本地设置

  1. 右上角 详情
  2. 本地设置
  3. 勾选 不校验合法域名、web-view(业务域名)、TLS 版本以及 HTTPS 证书
  4. 编译

同时 project.private.config.json

json 复制代码
"setting": {
  "urlCheck": false
}

十八、错误大全:现象→原因→解决

18.1 405 Invalid Signature

可能原因 解决
APISecret 填错 对照控制台复制
用了 APIKey 改用 APISecret
WebSocket URL 对 signature 做了 encode 去掉 encodeURIComponent
时间戳偏差 >5 分钟 同步系统时间

18.2 60005 无文件权限

可能原因 解决
fileId 来自其他 APP_ID 用 file/list 查本应用文档
网页上传与小程序不是同一应用 统一应用或 API 重新上传

18.3 知识库不存在

可能原因 解决
把 fileId 填进 REPO_ID 改填 FILE_IDS
把 libId=19855 填进 REPO_ID 用 repo/list 拿 API 的 repoId

18.4 request / socket 域名报错

见第十七章;真机预览必须在公众平台配置域名。

18.5 上传成功但问答无内容

可能原因 解决
未等 vectored 就问答 轮询完成后再问
未萃取且问题只匹配 QA 开启萃取或改 qaMode 为 WIKI_ONLY
retrievalFilterPolicy 过严 改为 LENIENT 或 OFF

18.6 萃取超时

可能原因 解决
PDF 页数多 增大 maxAttempts;稍后点「萃取」重试
额度不足 控制台查看用量

十九、自测 Checklist

  • config.js APP_ID / APP_SECRET 正确
  • 开发者工具已关闭域名校验或已配置域名
  • 上传 5MB 以内 pdf 成功返回 fileId
  • 列表页状态变为「可向量化问答」
  • 萃取完成弹窗显示 QA 条数 > 0
  • 问答页能流式输出
  • 问一个手册里明确存在的问题,答案相关
  • file/list 能看到刚上传的文件

二十、上线与安全建议

  1. APISecret 不要写死在小程序包内,生产环境用云函数/自有后端代理签名与上传。
  2. 上传+萃取耗时长,建议进度条、防重复点击、可取消(本项目可扩展 abort)。
  3. qa/apply 条数多时注意接口频率,必要时加 delay。
  4. 个人主体小程序可能无法配置外部业务域名,需企业主体或中转服务。
  5. 涉政涉敏内容会返回 10019 / 10013 等,见附录 A。

二十一、总结

阶段 接口 小程序实现
鉴权 Header / WSS query utils/auth.js
上传 POST /file/upload wx.uploadFile
向量化 POST /file/status 轮询 waitUntilVectored
知识库 /repo/create, /repo/file/add 可选 + 自动建库
萃取 /qa/extract + status + result runExtractPipeline
应用 QA /qa/apply 逐条 apply
问答 WSS /openapi/chat chatdoc.js 流式 UI

核心认知再强调三遍:

  1. fileId 只属于一个讯飞 APP_ID
  2. 上传不会自动萃取,必须调第四章接口;
  3. WebSocket 的 signature 不要 URL 编码

按本文接口顺序实现,即可在小程序内完成与讯飞星火知识库一致的 上传 → 萃取 → 问答 全链路。


附录 A:官方错误码表

错误码 描述 处理
10019 问题或文段可能涉政 检查内容
10013 敏感违规 检查内容
10014 输出敏感 换问法
60001 文件类型不对 检查格式
60002 文件大小超限 ≤20MB
60005 无文件权限 检查 appId 与 fileId
60014 问答未传文件 id 检查入参
62001 未找到相关文本段 换问题或调低过滤阈值
68003 操作太频繁 降频
99999 内部错误 重试/工单
相关推荐
fhqlongteng11 小时前
RK3576上electron调用GPU的功能设置方法
前端·javascript·electron·gpu·rk3576
weixin_3975740911 小时前
ReAct推理链的工程化实现与最佳实践
前端·react.js·前端框架
冰暮流星11 小时前
javascript之window对象方法
开发语言·javascript·ecmascript
c++之路11 小时前
责任链模式(Chain of Responsibility Pattern)
java·前端·责任链模式
倔强的石头_11 小时前
从收藏夹到选题库-QClaw如何帮创作者管理灵感
前端
努力成为AK大王12 小时前
从前端到数据库:一个 Web 项目的完整通信链路解析
前端·数据库·ajax·jdbc
川冰ICE12 小时前
JavaScript入门⑩|BOM与浏览器对象,localStorage_位置_历史记录
开发语言·javascript·ecmascript
耿公子和编程12 小时前
easybr指纹浏览器:轻量高效的环境隔离解决方案
前端·浏览器·开发工具