全域搜索
提供文件的可搜索文本,跨文件、Doc 和记录执行 grep,再按范围读取匹配内容。
全域搜索
Busabase 为用户和 AI 智能体提供一套完整的精确检索流程:
提供可搜索文本 -> grep -> 按范围读取匹配行POST /api/v1/grep 会搜索文件、Doc 正文和 Base 记录中当前已批准的标准值。结果包含来源、行号、列号和上下文,调用方可以先定位证据,再读取更多内容。
哪些内容可以搜索
| 来源 | grep 使用的文本 |
|---|---|
| 文件 | Asset 的可搜索文本槽 |
| Doc | 当前 Doc 正文 |
| 记录 | 当前已批准的记录字段 |
Markdown、JSON、CSV、日志和源代码等文本文件会直接使用自己的 UTF-8 字节作为可搜索文本。PDF、Office 文档、音频、视频或图片等二进制文件,需要外部工具或智能体先提取或转录文本,再将结果提供给 Asset。
Busabase 负责存储和搜索已提供的文本,但不会内置运行 OCR、语音转录或文档解析器。
为文件提供可搜索文本
Asset 的 textStatus 有四种状态:
| 状态 | 含义 | 下一步 |
|---|---|---|
missing | 尚未提供可搜索文本 | 提供文本,或标记为没有可提取文本 |
present | 当前可搜索文本已经就绪 | 执行 grep 或读取;有更好的提取结果时可替换 |
stale | 提供文本后,源文件又发生了变化 | 提供从新文件生成的文本 |
none | 已明确标记为没有可提取文本 | 将来有 OCR 或转录结果时仍可提供文本 |
Asset 详情页提供同样的添加、替换和预览操作。API 与智能体客户端支持三种写入方式。
小文本:直接写入
UTF-8 文本不超过 1 MB 时,直接调用 putText:
curl -X PUT "$BUSABASE_BASE_URL/api/v1/assets/$ASSET_ID/text" \
-H "Authorization: Bearer $BUSABASE_API_KEY" \
-H "Content-Type: application/json" \
--data '{"text":"提取后的合同文本\n终止条款……"}'响应会返回持久化后的状态与计数:
{
"assetId": "asset_contract_pdf",
"textStatus": "present",
"lineCount": 84,
"charCount": 4921,
"byteCount": 8036
}大文本:先上传,再绑定
文本超过 1 MB 时,使用适合流式处理的三步流程:
- 调用
POST /api/v1/assets/text/upload-urls获取临时上传地址。 - 将 UTF-8
.txt字节PUT到返回的uploadUrl。 - 调用
PUT /api/v1/assets/{assetId}/text,绑定返回的storageKey。
SIZE_BYTES=$(wc -c < extracted.txt | tr -d ' ')
curl -X POST "$BUSABASE_BASE_URL/api/v1/assets/text/upload-urls" \
-H "Authorization: Bearer $BUSABASE_API_KEY" \
-H "Content-Type: application/json" \
--data "{\"assetId\":\"$ASSET_ID\",\"sizeBytes\":$SIZE_BYTES}"
# -> { "uploadUrl": "...", "storageKey": "...", "expiresIn": 900 }
curl -X PUT "<uploadUrl>" \
-H "Content-Type: text/plain; charset=utf-8" \
--data-binary @extracted.txt
curl -X PUT "$BUSABASE_BASE_URL/api/v1/assets/$ASSET_ID/text" \
-H "Authorization: Bearer $BUSABASE_API_KEY" \
-H "Content-Type: application/json" \
--data '{"storageKey":"<storageKey>"}'最后一步会校验上传的字节和 UTF-8 编码,并让文本进入可搜索状态。再次提供文本会替换之前的可搜索文本。
没有可提取文本:标记为 none
对于纯图片或其他无法提取文本的文件,明确标记文本槽:
curl -X PUT "$BUSABASE_BASE_URL/api/v1/assets/$ASSET_ID/text" \
-H "Authorization: Bearer $BUSABASE_API_KEY" \
-H "Content-Type: application/json" \
--data '{"none":true}'之后 grep 会将该 Asset 计入 unsearchable,而不会反复报告为 missing。将来可以通过提供文本撤销这一状态。
跨文件、Doc 和记录执行 grep
省略 sources 即搜索全部三类来源,也可以只选择需要的来源:
curl -X POST "$BUSABASE_BASE_URL/api/v1/grep" \
-H "Authorization: Bearer $BUSABASE_API_KEY" \
-H "Content-Type: application/json" \
--data '{
"pattern":"termination",
"flags":"i",
"sources":["files","docs","records"],
"contextLines":2
}'pattern 使用 JavaScript 正则表达式语法,普通单词本身也是合法 pattern。对于大型搜索,可以用 scope.files、scope.docs 或 scope.records 缩小范围。
{
"matches": [
{
"source": "files",
"assetId": "asset_contract_pdf",
"fileName": "contract.pdf",
"drivePath": "legal/contract.pdf",
"line": 118,
"column": 1,
"text": "Termination requires 30 days notice.",
"before": ["..."],
"after": ["..."]
}
],
"coverage": {
"files": { "scanned": 24, "missing": [], "stale": [], "unsearchable": 1, "errored": [], "notReached": 0 },
"docs": { "scanned": 12, "errored": [], "notReached": 0 },
"records": { "scanned": 178, "errored": [], "notReached": 0 }
},
"truncated": false
}在把零匹配解释为“确实不存在”之前,务必检查 coverage。出现 missing、stale、errored、notReached 或 truncated: true,说明搜索并不完整。缺失或过期的文件需要补充新文本;notReached 或截断通常意味着应该缩小范围或收窄 pattern。
只读取匹配附近的范围
文件在第 118 行命中后,只读取附近窗口,不必下载完整提取文本:
curl "$BUSABASE_BASE_URL/api/v1/assets/$ASSET_ID/text/lines?startLine=113&endLine=123" \
-H "Authorization: Bearer $BUSABASE_API_KEY"如果命中来自 Doc,则使用结果中的 nodeId 调用对应的 Doc 接口:
curl "$BUSABASE_BASE_URL/api/v1/docs/$NODE_ID/lines?startLine=113&endLine=123" \
-H "Authorization: Bearer $BUSABASE_API_KEY"Asset 单次读取最多 2,000 行,并使用存储范围读取,因此“先 grep、再读取”的方式同样适用于非常大的提取文本。
putText 不等于 editContent
这两个操作修改的对象和审核规则完全不同:
| 操作 | 修改内容 | 源文件 | 审核方式 |
|---|---|---|---|
assets.putText | grep 和范围读取使用的、可重新生成的派生文本 | 不变 | 直接写入,并记录审计日志 |
assets.editContent | 挂载在 Drive 或 Skill 中的标准文本文件字节 | 合并后改变 | 创建 ChangeRequest,由人工审核 |
不要使用 putText 编辑 PDF、文档或已挂载文本文件本身。它只负责提供 grep 读取的文本表示。只有需要修改真实文件时,才使用 editContent。
Asset 响应中不会内联提供 asset.text 字段。大文本不会进入 AssetVO;请通过 asset.textStatus 查看状态,用 putText 写入,用 grep 搜索,再用 readTextLines 按范围读取。