发票云(智能特性)
旗舰版标准版智能特性
旗舰版标准版智能特性
🤖 AI Support​​
  1. 统一反馈
  • 整体介绍
  • 开发指南
  • 授权
    • token获取
      POST
  • 智能特性
    • 文档信息识别
      • 国际发票识别
      • 国际发票识别(明细)
      • 文档信息识别(反馈)
      • 银行回单识别
    • 三单匹配
      • 三单匹配-同步接口
      • 三单匹配-异步任务提交
      • 三单匹配-异步结果查询
    • 统一反馈
      • 三单匹配反馈详细说明
      • 算法服务统一反馈接口
        POST
    • 文档分类(区分发票、附件)
      POST
    • 智能赋码税收分类编码识别
      POST
  • 文档中心
    • 外部文件上传接口
      POST
  • 国际发票
  • 数据模型
    • 示例数据模型
      • Pet
      • Category
      • Tag
旗舰版标准版智能特性
旗舰版标准版智能特性
🤖 AI Support​​
  1. 统一反馈

三单匹配反馈详细说明

一、概述#

三单匹配任务支持 4 种反馈类型,每种类型的 taskData 结构不同:
反馈类型说明是否需要 taskIdtaskData 是否为空
ACCEPT用户接受算法结果✅ 必须✅ 可为空
ABANDON用户放弃算法结果✅ 必须✅ 可为空
MODIFY用户修改算法结果✅ 必须❌ 需要传数据
MANUAL用户未调用算法,手动匹配❌ 不需要❌ 需要传数据

二、场景1:ACCEPT(接受算法结果)#

使用场景
用户查看算法匹配结果后,认为结果正确,直接采用,无需修改。
请求参数
以下是转换后的 Markdown 表格:
参数值说明
taskType"three_way_match"固定值
feedbackType"ACCEPT"固定值
clientId客户ID必填
taskId匹配接口返回的任务ID必填,用于关联原始任务
taskData{}空对象即可
完整示例
  {
      "taskType": "three_way_match",
      "feedbackType": "ACCEPT",
      "clientId": "client_123",
      "taskId": "8a99a18a3ca66a8fb332c66130b09f44",
      "taskData": {}
  }
返回示例
  {
      "errcode": 0,
      "description": "反馈提交成功",
      "data": {}
  }
注意事项
taskId 必须是从匹配异步提交接口返回的有效任务ID
taskData 传空对象即可,不需要传递具体数据

三、场景2:ABANDON(放弃算法结果)#

使用场景
用户查看算法匹配结果后,认为结果不符合预期,放弃使用算法结果。
请求参数
参数值说明
taskType"three_way_match"固定值
feedbackType"ABANDON"固定值
clientId客户ID必填
taskId匹配接口返回的任务ID必填,用于关联原始任务
taskData{}空对象即可
完整示例
  {
      "taskType": "three_way_match",
      "feedbackType": "ABANDON",
      "clientId": "client_123",
      "taskId": "8a99a18a3ca66a8fb332c66130b09f44",
      "taskData": {}
  }
返回示例
  {
      "errcode": 0,
      "description": "反馈提交成功",
      "data": {}
  }
注意事项
放弃操作会记录在系统中,用于后续分析算法效果
taskData 传空对象即可

四、场景3:MODIFY(修改算法结果)#

使用场景
用户在算法匹配结果的基础上进行了修改(如调整匹配关系、引入新的入库单等),然后采用
改后的结果。
taskData 字段说明
1.
userResult(object)- 必填
用户最终确认的匹配结果。
结构:
  {
      "matches": [
          {
              "targetItemId": "发票明细ID",
              "candidateItemIds": ["入库单明细ID1", "入库单明细ID2"]
          }
      ]
  }
字段说明:
字段: matches
类型: array
说明: 匹配关系列表
────────────────────────────────────────
字段: targetItemId
类型: string
说明: 发票明细ID(对应发票文件中的 item_id)
────────────────────────────────────────
字段: candidateItemIds
类型: array[string]
说明: 入库单明细ID列表(对应入库单文件中的 item_id)
说明:
一条发票明细可以匹配多条入库单明细
如果某条发票明细没有匹配到任何入库单,可以不包含在 matches 数组中,或者
candidateItemIds 传空数组
2.
extraCandidateUrl(string)- 可选
额外入库单文件的 URL 地址。
何时需要传:
用户引入了原任务没有的入库单明细时需要传
建议做法:
业务端可直接将 userResult
中涉及的入库单的完整明细数据(包含该入库单的所有明细行)组成 CSV 文件传入
无需判断是否有新入库单,算法侧会自动处理
文件格式:
CSV 格式,UTF-8 编码
字段结构与匹配接口的 candidateUrl 一致
⚠️ 重要:
需要传该入库单的所有明细行,而不仅仅是被匹配的明细行
例如:userResult
中用到了入库单A的第2、5行,但需要传入入库单A的所有明细行(1-10行)
完整示例1:仅调整匹配关系
用户只在原入库单范围内调整了匹配关系,没有引入新入库单。
  {
      "taskType": "three_way_match",
      "feedbackType": "MODIFY",
      "clientId": "client_123",
      "taskId": "8a99a18a3ca66a8fb332c66130b09f44",
      "taskData": {
          "userResult": {
              "matches": [
                  {
                      "targetItemId": "invoice_item_001",
                      "candidateItemIds": ["receipt_item_001", "receipt_item_002"]
                  },
                  {
                      "targetItemId": "invoice_item_002",
                      "candidateItemIds": ["receipt_item_003"]
                  }
              ]
          }
      }
  }
完整示例2:引入新入库单
用户引入了原任务没有的入库单明细。
  {
      "taskType": "three_way_match",
      "feedbackType": "MODIFY",
      "clientId": "client_123",
      "taskId": "8a99a18a3ca66a8fb332c66130b09f44",
      "taskData": {
          "userResult": {
              "matches": [
                  {
                      "targetItemId": "invoice_item_001",
                      "candidateItemIds": ["receipt_item_001", "new_receipt_item_001"]
                  }
              ]
          },
          "extraCandidateUrl": "https://example.com/additional_receipts.csv"
      }
  }
返回示例
  {
      "errcode": 0,
      "description": "反馈提交成功",
      "data": {}
  }
注意事项
1.
userResult 必填:必须传入用户最终确认的匹配结果
2.
extraCandidateUrl 的使用:
如果不确定是否有新入库单,建议直接传入
传入时需要包含完整的入库单数据(所有明细行)
3.
结果对比分析:
算法侧会保存原始匹配结果(systemResult)
对比 userResult,可以分析用户修改了哪些地方
用于模型优化和归因分析

五、场景4:MANUAL(人工手动匹配)#

使用场景
用户没有调用算法匹配接口,直接进行手动匹配。这种情况下没有
taskId,需要提供完整的原始数据。
taskData 字段说明
1.
supplierId(string)- 必填
供应商ID,用于标识本次匹配涉及的供应商。
2.
targetUrl(string)- 必填
发票文件的 url 地址。
文件格式:
CSV 格式,UTF-8 编码
字段结构与匹配接口的 targetUrl 一致
必须包含 doc_id 字段(发票唯一标识)
3.
candidateUrl(string)- 必填
入库单文件的 url 地址。
文件格式:
CSV 格式,UTF-8 编码
字段结构与匹配接口的 candidateUrl 一致
4.
settings(object)- 可选
动态配置项,用于记录用户手动匹配时使用的配置。
格式:与匹配接口的 settings 参数一致,例如:
  {
      "priceTolerance": 0.05,
      "priceToleranceType": "0",
      "quantityTolerance": 1.0,
      "quantityToleranceType": "1",
      "amountTolerance": 0.02,
      "amountToleranceType": "0",
      "matchMode": "2"
  }
5.
userResult(object)- 必填
用户手动匹配的结果。
结构:与 MODIFY 场景中的 userResult 一致。
完整示例
  {
      "taskType": "three_way_match",
      "feedbackType": "MANUAL",
      "clientId": "client_123",
      "taskData": {
          "supplierId": "supplier_456",
          "targetUrl": "https://example.com/invoice.csv",
          "candidateUrl": "https://example.com/receipts.csv",
          "settings": {
              "priceTolerance": 0.05,
              "priceToleranceType": "0",
              "matchMode": "0"
          },
          "userResult": {
              "matches": [
                  {
                      "targetItemId": "invoice_item_001",
                      "candidateItemIds": ["receipt_item_001"]
                  },
                  {
                      "targetItemId": "invoice_item_002",
                      "candidateItemIds": ["receipt_item_002", "receipt_item_003"]
                  }
              ]
          }
      }
  }
返回示例
  {
      "errcode": 0,
      "description": "反馈提交成功",
      "data": {}
  }
注意事项
1.
不需要 taskId:因为用户没有调用过匹配接口,所以不需要传 taskId
2.
必须提供完整数据:需要提供 supplierId、targetUrl、candidateUrl、userResult
3.
settings 可选:如果不确定用户使用的配置,可以不传
4.
文件格式要求:targetUrl 和 candidateUrl 指向的文件必须符合匹配接口的格式要求

六、常见问题#

Q1: taskId 不存在或已过期怎么办?
错误返回:
{
    "errcode": "2001",
    "description": "taskId 不存在或已过期",
    "data": null
}
原因:
taskId 输入错误
该任务没有启用反馈
任务超过 1 个月未反馈,已被自动清理
该任务已经反馈过了,不能重复反馈
解决方法:
检查 taskId 是否正确
如果任务已过期,需要重新调用匹配接口

Q2: MODIFY 场景下,extraCandidateUrl 什么时候需要传?
需要传的情况:
用户引入了原任务没有的入库单明细
建议做法:
如果不确定是否有新入库单,可以直接传
将 userResult 中涉及的所有入库单的完整明细数据组成 CSV 文件传入
算法侧会自动判断哪些是新入库单

Q3: extraCandidateUrl 中需要传哪些数据?
正确做法:
传入 userResult 中涉及的入库单的所有明细行
例如:userResult
中用到了入库单A的第2、5行,但需要传入入库单A的所有明细行(1-10行)
错误做法:
❌ 只传被匹配的明细行(不完整)

Q4: 如何判断反馈是否提交成功?
判断标准:
errcode = "0000" 表示成功
errcode != "0000" 表示失败,查看 description 了解失败原因

Q5: MANUAL 类型为什么不需要 taskId?
原因:
MANUAL 类型表示用户没有调用过匹配接口,直接手动匹配
因此不存在原始任务,也就没有 taskId
注意:
MANUAL 类型需要提供完整的原始数据(targetUrl、candidateUrl 等)

七、数据保留策略
1.
任务数据保留期:
超过 1 个月未收到反馈的任务,自动删除任务数据
因此建议尽早提交反馈
2.
中间数据保留期:
超过 10 天删除冗余中间数据(如有)
修改于 2026-02-09 03:39:10
上一页
三单匹配-异步结果查询
下一页
算法服务统一反馈接口
Built with