Files
airz-uniapp/docs/需求与评估结果数据契约.md
T
hujun e5406c23a6 fix: 修复匹配详情提示及公积金可选路径问题
修复匹配详情中“用户自填未经核验”等来源说明,清理未参与项的橙色注意提示,修正贷款统计口径文案;补充公积金完整可选路径提取逻辑,确保明确无额外时长要求的公积金分支可正确识别并通过。
2026-10-19 16:11:59 +08:00

325 lines
42 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 融资需求与评估结果数据契约
## 2026-10-14 补充:结果默认进入匹配栏目(本地待发布)
提交后的分析页仅在status=succeeded、hasReport=true且publishedRevisionId等于本次revisionId时,自动redirect至报告tab=matches并携带该revisionId。processing继续轮询,failed保留恢复入口;离页、过期请求或切换账号的回包不能触发跳转,旧成功版本不能冒充本次结果。无tab的历史报告仍默认overview,显式栏目及冻结版本兼容保持。
所有实际匹配三态均展示已有有效score(含0%),保留真实状态;待确认文案改为待核实,资料不足不混同,旧null分数不补造。报告/列表/详情/对比统一此口径,不改准入、分数、排序或rank。匹配栏目底部只保留修改资料与一句结果说明,其他栏目保留完整报告行动及元信息。本节覆盖下方旧展示限制;本轮前端115项纯检查、33项合成页面检查及微信29页编译通过,未部署/调用真实模型或真机验收。
## 2026-10-14 匹配摘要与派生年龄增补(本地待发布)
报告匹配标签与独立列表默认展示前3款实际产品,优先符合条件,再待核实、条件不符;不足3款时按实际数量显示。保留真实三态,unknown/ineligible不进入候选排名,不冒充推荐或获批概率。符合条件项保留真实分数(包括0%),旧结果无分数时不造分;查看更多使用冻结结果的all分组游标。
新个人评估从有效身份证计算评估当天的周岁,冻结策略为identity-age-v1。只向模型/报告提供age事实(integer、unit=age、source=self_reported、state=provided),供 `fact:age` 证据引用;证件号码不进入模型或公开响应。身份证无效时不猜算,企业评估不自动使用个人年龄;旧冻结任务和旧报告保持。没有新增采集项/数据库列,具体校验与排序见[匹配规则契约最新增补](产品匹配规则开发契约.md)。
## 2026-10-09 万元输入与缴纳资料增补(当前)
小程序所有业务金额含socialSecurityBase/housingFundBase以万元输入和展示,最多六位小数;提交前以整数分换算为yuan元两位小数字符串。0.8万元=8000.00元、0.000001万元=0.01元;回填、确认、档案和在线报告对称转换。后端元金额及历史快照原值不改,基数仅随评估版本JSON保存,不增fa_user_info列;未知留空、未缴纳清空、企业拒绝有效个人基数。
缴纳时长支持six_to_twelve_months/twelve_to_twenty_four_months/twenty_four_months_plus,旧six_months_plus保留原意。readiness v3分母个人11/企业6不变;满6月分档只适配原six_months_plus匹配阈值。新执行快照冻结financingGradePolicy、报告保存12档等级,旧任务/报告不补算。后端profile-grade-r4已发布,小程序待用户发行;PDF基数仍元单位。详见[发布与发行说明](后端配套发布与小程序发行-20261009.md)。
## 2026-10-09 补充:融资能力综合等级
用户确认采用A+、A、A-、B+、B、B-、C+、C、C-、D+、D、D-12档,综合融资能力与资料完整度,首版权重80/20。新增financingGrade和冻结financingGradePolicy,详见[分级规则](融资能力分级规则.md)与开发文档0.83。该指标独立于第4节原资料准备状态、产品匹配百分比和overallScore;原readiness、completeness及score=null保持。旧报告不补算、不覆盖;只有新v3执行快照发布规则后计算。平台自定阈值尚未真实样本校准。本批未部署或发行,以下旧契约解释按原字段含义继续适用。
## 2026-09-30 最新覆盖约定(评估版本)
最新存储/隐私/修改规则见[评估版本与最新资料](评估版本与最新资料.md):资料表只存每用户个人/企业各一条最新正式资料;新建增加会话,修改复用会话并新增日志JSON版本;匹配仍为会话match_result数组,历史结果和输入绑定revisionId。重评失败保留上次成功结果;身份业务资料明文,本人编辑完整回填,展示/PDF/模型上下文脱敏保留。当前代码已实施,正式迁移部署尚未执行;下述inputVersion=3采集范围继续有效,其余旧存储/只读/加密约定由本节覆盖。
## 2026-09-29 最新覆盖约定(inputVersion=3)
个人/企业信用融资恢复至2026-09-23 19:04需求扩展之前的采集范围:删除融资金额、融资期限、资金用途、其他用途说明;保留经营月数和原有身份/经营收入/资产负债/资料授权。提交使用inputVersion=3,结果仍为resultVersion=2,保留报告三栏、产品匹配、助手、PDF与行动入口。v3不生成需求事实或匹配规则,不把取消采集的字段列为“未提供/待核实”、补填项或完整度扣分项;产品自身额度、期限、利率和用途资料保留。其他真实缺失或来源未核验仍按既有规则处理。
资质匹配快照标记profileOnly=true并纳入摘要;编译产品规则时移除requestedAmountYuan、requestedTermMonths、purposeCode相关条件。新准备策略self-reported-profile-20260929-v2,个人11项/企业6项,不含需求条件项。旧输入1/2不再接受新建;保留旧报告解析分支仅供归档兼容。
已按用户授权在111.230.144.231/airz执行:删除报告161/229、关联会话151/219及2条日志;普通助手449及其2条日志保留,会员1个、产品6个保留。fa_user_info删除requested_amount、requested_term_months、purpose_code、purpose_detail四列;input_version、analysis_context属于必要版本和快照元数据,继续保留。两个触发器同步移除需求列校验,输入版本允许1/2/3,接口新建最低3。22张不相关表摘要一致,log_bin_trust_function_creators临时开启后恢复0。备份:D:/AAdesk/202609/airz-backups/restore-profile-20260929-180938/。
下文v2字段、用途字典、需求覆盖与旧保留历史约定为历史设计,不可据此恢复采集或重跑旧迁移;其他冻结、鉴权、幂等、三态、金额精度要求继续适用。
---
版本:v1.6(匹配读接口及03/04/05/06基础已接,单产品AI解释与07—10扩展待开发)。日期:2026-09-24。配套:[开发文档](开发文档.md)、[开发进度](开发进度.md)。
本文补充融资需求字段、资料完整度与准备等级、产品匹配解释三个范围,作为后续前后端、数据迁移及验收的共同依据。依据为[开发说明书](开发说明书.docx)第2—5节及[原型图](原型.jpg)第02—05、09屏,并遵循用户后续确认的无草稿、H5优先、数据库存元及复用评估/报告表的约定。
**实施状态:需求v2、用途字典、完整度/准备状态、执行策略快照和报告v2自填支线已实现。** DEC-DEMAND和DEC-READINESS已按用户授权采用首版开发配置;新提交冻结targetResultVersion=2。升级前未带该标记或目标1的输入仍走resultVersion=1,旧成功报告不重算。真实匹配及产品解释待DEC-MATCH/产品资料,v2有限真实模型样例现已通过,生产业务和大样本语义验收仍待完成;证据见开发文档0.7、开发进度6.7及[真实模型验证记录](报告v2真实模型验证.md)。
## 1. 范围与业务含义
| 概念 | 回答的问题 | 不能表示的含义 |
| --- | --- | --- |
| 融资需求 | 用户希望获得多少资金、使用多久、用在哪里 | 银行批准额度、实际利率或放款承诺 |
| 资料完整度 | 当前版本列明的自填信息项有多少有效填写 | 真实性、信用评分、所有银行所需材料已齐全 |
| 融资准备等级 | 按已发布资料规则,哪些信息缺失、矛盾或可以进入人工核对 | 风险等级、授信等级、获批概率 |
| 产品匹配 | 在指定时点、产品版本和已知事实下,具体条件是否满足 | 审批结论;自填条件满足也未经机构核验 |
最初契约不新增页面,需求录入放评估页的“资金需求”步骤/分组,确认页、档案、报告同步显示。2026-09-24用户明确要求补齐04—10,现以[页面改造方案](原型04-10页面改造与跳转方案.md)为准:新增对比/下一步行动页并将PDF纳入一期任务;其余渠道、注销、知识库未随本次扩大。原型默认最多三个候选,不足不补造;匹配解释仍在现有产品详情展示,传递assessmentId与productId。
本次只增加共同融资需求字段。年龄段/工作年限、企业开票/纳税/流水/法人等补充资料另在 ASSESS-001 的字段字典阶段细化;当前已有 `year_invoicing/year_tax_amount` 可复用,但没有录入/API支撑时不能启用依赖它们的准入规则或宣称相关完整度已覆盖。企业成立月数与经营月数不等同,不能互相代填。
## 2. 融资需求输入
### 2.1 请求与字段
新增输入格式 `inputVersion:2`,仍使用 `POST /api/v1/assessments`。顶层保留 type、requestId、moneyUnit、form、documents、consentIds;新增 inputVersion:int。下列字段放入 form,个人/企业共用;现有姓名、证件、收入等必填约束本次不放宽。
| API字段 | 类型/单位 | v2提交约束 | fa_user_info已实现存储 |
| --- | --- | --- | --- |
| requestedAmountYuan | string,元 | 必填,`0.01`—`999999999.99`,规范两位小数,禁止JSON number、指数、负数、逗号、空格 | 新增 requested_amount DECIMAL(11,2) NULL |
| requestedTermMonths | int,月 | 必填,1—9999;禁止0、小数、数字字符串;范围为技术表示上限,不表示产品支持如此长期限 | 新增 requested_term_months SMALLINT UNSIGNED NULL |
| purposeCode | string,稳定枚举 | 必填,必须在本次类型允许的已发布用途字典内 | 新增 purpose_code VARCHAR(32) NULL,ASCII区分大小写 |
| purposeDetail | string或null | purposeCode=other时必填,trim后2—200个字符;禁止HTML/控制字符;其余用途必须null或缺省 | 新增 purpose_detail VARCHAR(200) NULL |
| inputVersion(顶层) | int | 新客户端发送2;服务端版本策略见第7节 | 新增 input_version TINYINT UNSIGNED NOT NULL DEFAULT 1 |
金额继续由客户端字符串运算完成万元→元,服务器以十进制处理;例如 `12.345678 万元` 对应 `123456.78` 元。需求金额不是已有负债、年营收或产品最高额度,不复用这些列。未知需求不以0代填;v2正式提交缺少上述必填字段时返回422,表单仍只保留当前流程内存,不增加保存草稿接口。
**用途字典已发布:`financing-purposes-20260923-v1`(DEC-DEMAND):**
| 评估类型 | 允许code及显示名 |
| --- | --- |
| personal | daily_consumption 日常消费、education 教育进修、home_improvement 家居装修、personal_business 个体经营周转、other 其他用途 |
| enterprise | working_capital 经营周转、inventory_purchase 采购备货、equipment_purchase 设备购置、business_expansion 经营扩展、other 其他用途 |
字典需包含版本、适用type、code、label、requiresDetail和启用状态。`GET /dictionaries` 已返回 assessmentInputVersions、minNewAssessmentInputVersion、financingPurposes及其版本,公开且no-store;当前由服务端配置发布,无后台编辑。移除配置条目即停用新建用途,变更需提升版本。正式提交事务内保存所用字典版本及用途项快照,显示名变化或后续停用不更改已提交记录的用途含义,也不阻止原请求幂等重放;保存位置见第6.2节。用途类别本身不表示机构允许;是否允许由产品规则及正式来源确定,尤其不能把“其他用途”直接判为满足。
### 2.2 服务端校验与隐私
- 同一requestId比较规范化的**全部输入**,包括 inputVersion 和四个新字段;缺省可选值归一为null,非法值不得静默丢弃。只允许目标类型的用途code,个人用途不能混入企业提交。
- 规范金额格式 `^(?:0|[1-9][0-9]{0,8})\.[0-9]{2}$` 后,再检查严格大于零。客户端展示万元,所有API及JSON快照金额均为元字符串。
- 用途说明是用户自由文本,只在本人只读详情及有权限的后台展示;不写请求日志,不作为可执行规则,不直接发送模型。后续报告v2的AI仅可接收经过白名单处理的用途code/标签、需求金额和期限事实;当前v1报告尚未接入这些新事实。说明中即使含“忽略规则”等内容也不影响匹配。
- 格式合法但互相矛盾的数据另做一致性校验。例如信用卡已用额度大于总额度时,v2提交返回422 FIELD_INCONSISTENT;不自动改小金额或改成0。不能从“贷款笔数为0”简单推断其他全部债务余额必为0,不做未经定义的跨概念推导。
- `documents/consentIds` 当前只能为空。后续接入授权后,拒绝可选征信查询不阻止自填提交,不为未付费查询扣资料完整度分,也不将未查询当成征信正常。
### 2.3 已实现请求示例
以下为本地已支持的合成企业请求样例,不代表生产已发布:
```json
{
"inputVersion": 2,
"type": "enterprise",
"requestId": "needs_submit_example_001",
"moneyUnit": "yuan",
"form": {
"name": "示例联系人",
"phone": "19900000000",
"city": "深圳市",
"cityCode": "440300",
"enterpriseName": "示例企业",
"businessCode": "91440300123456789A",
"occupation": "科技服务",
"operatingMonths": 24,
"annualRevenue": "1000000.01",
"totalDebtBalance": "0.00",
"monthlyLoanPayment": "0.00",
"requestedAmountYuan": "123456.78",
"requestedTermMonths": 12,
"purposeCode": "working_capital",
"purposeDetail": null
},
"documents": [],
"consentIds": []
}
```
HTTP201接受回执保持 `{assessmentId:string,submissionStatus:"accepted"}`;新需求不进入会变化的回执。状态与报告仍通过assessmentId读取。GET详情返回 inputVersion 与四个需求字段,金额不转number;历史v1新增字段null并显示“当时未采集”。
## 3. 资料完整度
### 3.1 字段集合与计算
完整度由服务端确定性计算,保存 policyVersion、适用字段集合、逐项状态和计算时点。前端只渲染服务端结果,不沿用本机表单百分比充当正式报告结果。**首版已采用等权字段计数,不引入风险权重;DEC-READINESS开发版为self-reported-base-20260924-v1,后续变更需版本化发布。**
已实现首版字段集 `self-reported-base-20260924-v1` 只覆盖已实现资料和新增需求,不声称覆盖说明书尚未接入的全部经营资料:
| 分组 | 个人适用字段 | 企业适用字段 |
| --- | --- | --- |
| 基础描述(2项) | city、occupation | city、occupation(行业) |
| 融资需求(3项) | requestedAmountYuan、requestedTermMonths、purposeCode | 同左 |
| 收入/经营 | monthlyIncome、socialSecurity、housingFund(3项) | annualRevenue、operatingMonths(2项) |
| 债务情况 | totalDebtBalance、monthlyLoanPayment、creditLoanCount、creditCardCount、creditCardTotalLimit、creditCardUsedLimit(6项) | totalDebtBalance、monthlyLoanPayment(2项) |
| 条件项 | purposeCode=other时加入purposeDetail(1项) | 同左 |
因此个人基础分母14、企业基础分母9;选择other各加1。表单无需为达到100%而强迫填写不适用字段。姓名、证件、手机号、企业名称/代码属于身份/提交校验,不计入这个资料完成比例;附件数量、授权选择、第三方付费查询、房车有无均不计分。city有效文本计已填;cityCode未知单独影响地区规则的unknown,不反向把已有城市输入当空。
逐项 `state=provided|missing|invalid|not_applicable`:
- provided:适用且通过类型、枚举、范围校验;合法 `0`、`"0.00"`、`none`、`no` 都是有效回答,不因金额小或选择“无”降低完整度。
- missing:适用但null/未采集;空字符串在请求校验/规范化时处理,禁止写成“未知”字符串冒充已填。
- invalid:历史或内部数据未通过字段校验,不计已填;v2新提交原则上在写库前拒绝。
- not_applicable:由已发布的type/条件规则判定,排除分母;不能由客户端传入,也不能为了提高比例自行排除。
`applicableCount` 为非not_applicable项数,`providedCount`为其中provided项数。`percent=ROUND_HALF_UP(100×providedCount/applicableCount)`,整数0—100,整数/十进制运算,不用二进制浮点。已发布策略的分母为0视为配置错误,任务failed、errorCode=ASSESSMENT_POLICY_INVALID,不生成正式completeness或成功报告,不能给0或100分。未填项按字段清单输出 missingFields;invalidFields单独列出。一致性问题使用 consistencyIssues 记录,不因单字段都已填而消失。
验证样例:个人普通用途14项中11项provided,返回79;企业9项中8项provided,返回89;全部provided且含债务金额为0时仍100。该比例仅表示当前字段集填写情况,与收入高低、产品数量、查询授权无关。
### 3.2 完整度DTO
`completeness={status,policyVersion,providedCount,applicableCount,percent,items,missingFields,invalidFields}`。
- status:evaluated / policy_unconfirmed / legacy_unavailable。
- evaluated时 policyVersion非空,计数/percent为整数,items完整包含 `{fieldKey,label,state}`;字段顺序由策略固定。missingFields/invalidFields为fieldKey数组,可由items复算。
- 规则未发布时 status=policy_unconfirmed,policyVersion/计数/percent=null,items与缺失数组为空;前端展示“资料完整度规则待配置”,不展示0分。可以在其他区域继续呈现实际输入和缺失事实。
- 历史v1报告不事后添加试算分:适配为legacy_unavailable/null,或沿用v1展示“未计算”。新字段集发布只影响新评估,不重算旧比例。
## 4. 融资准备等级
### 4.1 建议策略与发布闸门
首版采用可解释的资料状态;以下规则已按本轮授权落地为 **DEC-READINESS开发版**,生产业务验收仍需人工样例,不使用A/B/C信用分:
| 判断顺序 | 条件 | 已实现code / label |
| --- | --- | --- |
| 1 | 尚无已发布的完整度/准备策略,或记录不支持该输入版本 | code=null;状态policy_unconfirmed或legacy_unavailable;显示未评定 |
| 2 | 存在invalid字段或已定义的consistencyIssues | needs_verification / 需核实资料 |
| 3 | 适用字段存在missing | needs_information / 待完善资料 |
| 4 | 当前字段集全部provided,且无上述问题 | ready_for_review / 可进入资料核对 |
等级依赖实际计数而非四舍五入后的percent,避免99.x%显示100后误升等级。没有任意80/90分门槛;若业务希望使用分档或权重,应先提交版本化规则和人工样例,经确认后另发策略。上述“可进入资料核对”只针对当前自填字段集,即使完整度100也可能缺少银行要求的材料,不代表满足某产品,更不代表已经核验、可以获批或可以申请。
准备等级不读取候选产品数量、不依赖AI生成成功与否、不以收入额度高低给人分级。外部资料未查询单独写 verificationStatus=not_verified 和风险提示;可选授权的拒绝本身不降级。
### 4.2 准备等级DTO与解释
`readiness={status,policyVersion,code,label,basis,verificationStatus}`;status同完整度,未计算时code/label/policyVersion=null、basis=[]。evaluated时保存稳定code、显示标签和 `basis:[{basisId,code,fieldRefs,issueRefs,message}]`,basisId在本报告内唯一且稳定。basis由服务端模板生成,fieldRefs引用本次字段清单,issueRefs引用一致性问题ID。模型可解释既有basis,但无权改code/label/优先级。
`consistencyIssues:[{id,code,fieldRefs,message}]`只使用已发布校验规则。例如 `CREDIT_CARD_USED_EXCEEDS_LIMIT` 引用creditCardUsedLimit和creditCardTotalLimit。历史异常仍保留原值供本人/有权限后台核对,不用AI猜测正确数值。
## 5. 产品匹配与结果解释
2026-09-24已接通发布预检、字段编译、目录冻结、三态判定、productId升序及正式任务落库;不启用评分。快照结构见[产品规则开发契约](产品匹配规则开发契约.md)第7节。本地经用户授权上架6条演示产品,用于联调;匹配读接口/页面、真实产品规则与人工金标准仍待验收。
### 5.1 候选判定与未知值
1. 先验证产品发布状态、有效期、适用对象和配置完整性,冻结本次可评估产品集合。草稿/下架/过期产品不进入本次集合;无真实产品或无已发布规则时 matching.status=unavailable。
2. 产品所引用字段必须在服务器规则白名单内,有已定义类型/单位/来源;不支持的字段或操作符阻止发布。不得从 condition、grade、recommendation、deprecated 等任意描述文本直接推断准入。
3. 每条规则返回 `pass|fail|unknown|not_applicable`。客户端不能指定not_applicable;未知金额、未提供cityCode、未查询的信用信息不能当作0或正常。规则所需证据必须达到 rule.requiredSource=self_reported或verified;自填满足阈值不能冒充verified。
4. 硬规则中任一fail → eligibility=ineligible;无fail但任一unknown → unknown;适用硬规则全部pass → eligible。fail与unknown并存时仍ineligible,同时保留未知项。不能把零条有效硬规则当作默认通过:产品必须有有效发布校验及本节需求规则。
5. 产品配置缺失/非法与用户信息缺失不同。产品amount/term为null不能当“无限制”,regions=[]是全国、regions=null是未配置。配置损坏时整次匹配failed并记录安全错误,不悄悄跳过产品后宣称完整匹配。用户字段缺失才使用unknown。
**需求匹配口径:单产品完整覆盖。** `amountMinYuan ≤ requestedAmountYuan ≤ amountMaxYuan`、`termMinMonths ≤ requestedTermMonths ≤ termMaxMonths`,边界包含;禁止自动修改用户需求、拆金额或拼多个产品凑额度。产品用途白名单放入带版本的eligibility_rules;没有明确用途依据则阻止发布,“其他用途”需人工核实,返回unknown,不从purposeDetail自由文本自动推断。
unknown不是建议申请;ineligible不是永久拒绝。展示应为“本次资料不满足已知条件”或“缺少判断依据”,并说明所用资料未经核验。only eligible进入默认候选列表。
### 5.2 排序、理由与证据
- `score` 为number|null。业务评分尚未定稿时始终null,不显示匹配百分比。DEC-MATCH定稿后才允许0—100的规则匹配指标,存scorePolicyVersion;仍不代表审批概率。overallScore也不由模型生成。
- 发布时必须提供稳定排序策略版本。建议无评分首版按运营已确认优先级、productId升序排序;如优先级尚未配置,显式使用productId升序作为稳定展示顺序,标注“不代表优劣排序”。不可临时用AI结果排序。
- eligible项rank从1递增;ineligible/unknown的rank=null,不进入候选排名。默认最多展示三家且有查看更多;其他结果独立显示“条件不符”与“待补资料”,不混入推荐卡片。若提供额度/利率排序,仅改变客户端显示顺序,不覆盖历史rank。
- 推荐依据 `positiveReasons`、不符条件 `blockingReasons`、待核实/注意事项 `cautions` 分开保存。首页各组最多展示三条;没有证据就不生成,详情可读完整列表。通过部分条件的不适配产品,其positiveReasons不能标成“推荐该产品”。
- 理由 `{reasonId,code,text,evidenceRefs}` 由确定性规则/模板生成,evidenceRefs至少一个且只引用本项证据。失败条件、未知依据全部保存,不能因为只展示三条而丢掉阻断项。产品公共优势不是用户个性化理由。
- 证据 `{evidenceId,ruleId,ruleVersion,kind,fieldRefs,operator,expected,actual,outcome,source,observedAt}` 固定类型、单位和来源。evidenceId在整份报告内唯一且稳定,例如由productId、ruleId和条目序号组成,不能让不同产品的同名规则共用ID。kind=hard/soft,source=self_reported/verified/product_snapshot;expected/actual金额保持元字符串,未知actual=null。规则快照保存requiredSource,复核时能判明证据是否够用。
- 单项 `aiExplanation={status,text,evidenceRefs,reasonExplanations,generatedAt,errorCode,canRetry}`,status=not_requested/queued/running/completed/failed(2026-09-28已实现);reasonExplanations为`{reasonId,text,evidenceRefs}[]`,generatedAt为ISO时间或null,errorCode为稳定错误码或null,canRetry为boolean。taskId/leaseUntil/requestKeys/attempts仅内部保存,不通过DTO外发;只解释服务端已生成的理由,不能新增规则、伪造优势/风险或改判定。模型内容缺证据、含审批承诺或改写数值时拒绝保存该段,保留规则理由并显示解释暂不可用。不存在“必须每家补足三正三反”的生成要求。
证据类型增补:source在事实完全缺失/无法确定来源时允许null,不捏造self_reported/verified;observedAt未知也为null。额外提供requiredSource、reasonCode、valueType及unit,现已映射入正式match_result。not_applicable以product_snapshot作为适用范围依据来源。
### 5.3 结果存储与接口
仍在 `fa_ai_chat.match_result` 保存有序JSON数组,数据库键沿用snake_case,DTO层转camelCase;不新建匹配表,不把有序数组改为对象。每项包含:
| API键 | 持久化键 | 类型与约束 |
| --- | --- | --- |
| productId / productVersion | product_id / product_version | string / int;ID传输用字符串,版本为冻结版本 |
| eligibility / rank / score | eligibility / rank / score | eligible或ineligible或unknown;rank:int或null;score:number或null |
| scorePolicyVersion | score_policy_version | 未评分时null |
| reasons | reasons | string[],保留已有键供服务端迁移兼容;由positive/blocking/cautions确定性汇总,不能作为唯一证据 |
| positiveReasons / blockingReasons / cautions | positive_reasons / blocking_reasons / cautions | 理由对象数组 |
| evidence / aiExplanation | evidence / ai_explanation | 证据数组及可空解释对象,嵌套对象也显式映射键名 |
| productSnapshot | product_snapshot | 不可变产品参数、适用对象/地区/用途规则、材料、来源引用、采集/更新时间、产品版本;金额元字符串,期限月,年化百分数字符串 |
`Assessment::complete()`现已对v2按冻结目录复算并比对整个匹配数组与统计,允许未评分score=null及非候选rank=null,禁止非法组合/引用写入;v1保留旧格式。匹配读接口尚未实现。19项正式任务测试已覆盖合法null落库及旧冻结引擎兼容。
聚合对象 `matching={status,reasonCode,ruleVersion,orderingPolicyVersion,catalogSnapshotId,candidateCount,ineligibleCount,unknownCount}` 存在report_data,不放入match_result数组头部:
- status=unavailable:未运行,reasonCode=PRODUCT_CATALOG_UNAVAILABLE / MATCH_RULES_UNPUBLISHED / LEGACY_INPUT / DEMAND_INCOMPLETE;三个计数为null,match_result=[]。
- status=completed:已完成规则执行,计数为非负整数,允许candidateCount=0;应结合另外两个计数解释原因,不能把unknown说成不符合。
- status=failed:执行器/存储/配置异常,计数null;整次评估维持failed,不向报告接口暴露部分成功的正式报告。失败信息由状态接口提供,需用户重试。
未具备真实产品时,可以先成功生成需求/完整度自填报告并标unavailable;这只是内部开发支线,**不改变一期必须完成真实产品匹配及外部渠道验收的既定范围**。
| 方法/路径(/api/v1前缀) | 实施状态 | data与行为 |
| --- | --- | --- |
| GET /assessments/:id/report | 已支持v1/v2自填支线 | 本人成功记录;resultVersion辨识格式,未完成409、越权/不存在404;no-store |
| GET /assessments/:id/matches | 已实现 | 参数eligibility默认eligible,可选ineligible/unknown;limit默认3、1—50,cursor可空。data={assessmentId,resultVersion,matching,items,hasMore,nextCursor};unavailable返回200+空数组及明确状态,不冒充零候选 |
| GET /assessments/:id/matches/:productId | 已实现 | 只返回本次已评估的产品结果/全部理由/快照;未在快照内或越权404。不能拿公共当前产品临时拼出旧评估结论 |
| GET /products/:id | 已实现,会员Bearer鉴权 | 当前公共产品资料(非匿名);无用户等级、理由或匹配分;与个人化结果分离 |
本轮请求/响应示例、错误码及公共DTO范围见[规则契约第8节](产品匹配规则开发契约.md)。matches只读成功评估,未成功409;参数错误422。服务端先鉴权归属,再解析游标;游标绑定assessmentId、resultVersion、冻结结果摘要、eligibility和偏移量,非法/不匹配游标422。快照不可变,分页不能混用当前产品列表。v1成功报告也可返回matching.status=unavailable/reasonCode=LEGACY_INPUT;不回填历史match_result。
当前产品是否下架单列 `currentAvailability=available|unavailable|unknown`,由读取时受限查询得到,不写回productSnapshot、不改历史rank;当前不可用或查询失败时,申请准备页说明状态,不能继续显示“立即申请”。本项目仍只做资料引导,不向银行提交申请。
## 6. 报告v2与任务快照
### 6.1 报告组合契约
`resultVersion=2`、`reportType=financing_needs_analysis`。服务端组装报告:
| 字段 | 生成方与约束 |
| --- | --- |
| assessmentId、inputVersion、generatedAt、modelCode | 服务端;modelCode为实际指定模型快照 |
| overallScore | 首版null,无已确认评分规则不生成 |
| demand | 服务端冻结 requestedAmountYuan/requestedTermMonths/purposeCode/purposeLabel;不含自由说明正文 |
| facts | 服务端白名单事实,fieldKey、valueType、value、unit、source、observedAt;金额value为元字符串、月/数量为int、枚举为code、未知null;不含身份资料 |
| completeness、readiness、consistencyIssues、matching | 服务端按第3—5节计算;模型无修改权限 |
| summary、strengths、improvements、riskWarnings | AI定性文本;summary为string,后三者为 `{text,evidenceRefs}[]`,证据不足可为空;风险提示另含服务端固定“自填未核验”等提示 |
| disclaimer、policyVersions、systemWarnings | 服务端固定模板及版本集合;systemWarnings为固定风险提示字符串数组,独立于模型风险引用;政策、字段字典和模型版本不能省略 |
报告标准区块为“需求概况—资料完整度—准备等级—主要优势—待完善项—风险提示—候选及解释—免责声明”。不必为每个区块生成长文本;缺数据时明确未提供。需求金额/期限、比例、等级、匹配理由通过结构化事实呈现,AI正文继续只作定性解释。
v2模型输出不直接作为完整Report入库。服务端仅接受固定四个模型字段summary/strengths/improvements/riskWarnings;summary 2—600字符,各数组0—6项,每text 2—400字符,每条evidenceRefs 1—5个且去重,只引用输入的facts/ruleEvidence/readinessBasis公共引用ID。统一引用命名空间 `fact:<fieldKey>`、`rule:<evidenceId>`、`readiness:<basisId>`,使用第4.2/5.2节保存的唯一ID;无引用的优势不能存。外发提供allowedEvidenceRefs,但不传完整度计数/百分比;单项建议1—3个引用,服务端上限仍为5。不得从自填零负债推断信用记录,不得从资料齐全推断受理资格;not_applicable不是缺失。保留禁止数值复述、HTML和控制字符的校验,补中文项数/“为零”等模式;新增结构不得沿用当前只支持observations/suggestions/dataGaps的v1解析器。summary仅概括事实且不能改变结构化结论。
禁止输出保证通过、审批概率、已核验信用良好、内部渠道等无依据结论。语义校验和提示词不能保证模型绝无错误,需用人工金标准样例持续验收;数值、等级和准入结果始终由服务端权威字段控制。主报告结构不合法时任务failed;单产品AI解释失败时保留确定性匹配理由,不触发无限收费重试。
### 6.2 冻结与持久化
- 已为 `fa_ai_chat` 新增 `analysis_context JSON NULL`,仅用于正式assessment会话的依据快照,不新建业务表。快照分成不可覆盖的input_snapshot和execution_snapshot两个部分,分别只写入一次。
- **提交时冻结输入依据:** 正式提交事务在保存fa_user_info和会话的同时写入input_snapshot,已实现inputVersion、normalizationVersion、targetResultVersion及完整purposeDictionary(version、items,含type/code/label/requiresDetail/enabled)。基础字段规范化由固定版本代码处理,未冻结全部字段校验规则全文;未来变更须保留原版本规范化路径。输入原值仍冻结在fa_user_info,不重复存整包身份资料。此时execution_snapshot=null;用途改名/停用不影响已接受输入,读取和分析使用提交时的标签。快照写入失败则整个提交回滚,不能只保存输入而丢失其解释依据。
- **执行时冻结计算依据(新目标v2已实现自填支线):** worker首次抢占后、任何外部调用前,在事务内一次性补入execution_snapshot:目标resultVersion、完整度与准备策略、evaluatedAt和匹配不可用原因。本轮真实产品未就绪,productSnapshots=[]、matchingRules/orderingPolicy=null;真实集合、产品快照、匹配规则全文及排序策略随PRODUCT实施,不伪造快照。沿用input_snapshot的输入含义,不重新套用当前用途启用门槛;没有可用策略也保存明确的unavailable原因。
- analysis_context只由服务端写,具有schemaVersion、inputHash、executionHash、contentHash和上述版本集合;以规范化JSON计算SHA-256,输入和执行部分分别校验,executionHash/contentHash在执行部分冻结前为null,冻结后生成且不再变化。快照包含可重现的实际策略内容,不能只留版本号而覆盖后台配置。当前引擎equal-fields-v1的类型范围与舍入算法固定在代码,快照保存definitions/fields/conditionalFields/consistencyRules/readinessOrder/labels及版本;算法变化须支持旧引擎,不原地改旧版本语义。catalogSnapshotId由冻结集合内容摘要形成,不要求新增产品集合表。容量和产品数量须在实际产品规模确定后设置有界限制,超限明确失败,禁止悄悄截断候选范围。
- 失败重试在相同assessmentId下复用已经冻结的两部分快照;更换taskId仅代表新执行尝试。若尚未成功冻结execution_snapshot,则下一次在首次可用的抢占阶段补入并记录当时策略版本,不声称采用提交时未取得的规则;input_snapshot始终不变。重复消费不得覆盖任一已有部分,哈希不符时明确失败。旧v1记录的context可继续为null,不伪造历史字典。
- 需要更新需求、采用最新产品/规则或补充资料时,创建新assessmentId。成功报告不提供“原地刷新结论”。运行中产品下架不能改写快照;读取时另附currentAvailability。外部数据若后续接入,同样先冻结授权结果的来源/时间,不回写原表单。
- 完成事务原子写report_data、match_result、result_version、rule_version、模型快照及succeeded。rule_version标识整套报告策略发布版本;各子策略版本保存在policyVersions/context中。消息与tokens继续写fa_ai_chat_log,未知用量null。
- analysis_context不存密钥、证件或重复整包自由文本;可凭assessmentId读取冻结输入。存取权限按评估归属,公共产品API不返回这些context。后台不得修改已提交输入、context或历史结论。
## 7. 版本兼容与迁移
1. **目标版本冻结(已实施):** 新提交input_snapshot.targetResultVersion=2;发布前无该标记或显式1则仍使用v1,不因重试升级。`assessment.new_result_version`仅影响新提交,改配置不重算旧报告。
2. **版本相互独立:** inputVersion是提交字段结构,resultVersion是结果JSON结构,policyVersion是计算策略,productVersion是产品修订;不能只用某一个version替代全部。
3. **旧记录不补造:** 新增输入列先可空,input_version默认1,历史需求字段均null,不用收入/负债猜需求;旧报告仍resultVersion=1。v2只在新提交校验中强制需求字段,不能直接给全部历史行加NOT NULL。
4. **兼容窗口:** 服务端先支持v1/v2及双版本报告读取,再发布发送v2的前端。部署配置minNewAssessmentInputVersion明确新建最低版本;兼容窗口可为1,切到2后新requestId缺省或显式1返回422 INPUT_VERSION_UNSUPPORTED。切换时点由发布记录确认,不允许永久依赖缺省v1绕过必填。
5. **幂等优先:** 鉴权后先定位(userId,requestId)。已有记录按其原inputVersion及冻结的normalizationVersion/输入字典做结构校验、规范化并与原规范值比较;v1使用保留的v1规范化路径。同内容仍HTTP201固定回执,即使当前最低版本为2或原用途已停用;不得重新套用当前字典的启用门槛。输入版本或合法内容冲突409 REQUEST_CONFLICT,格式本身非法仍422。不得先套v2必填而拒绝原v1成功请求的重放。软删除旧键仍409,不能重建。
6. **旧重试:** 已有v1失败记录保持v1输入和v1自填分析,不因升级自动获得v2完整度/等级/匹配;迁移时为旧任务选择v1处理路径。若需v2需求分析,用户重新填写并正式提交新记录。旧重试键仍返回原taskId,不换版本重跑。旧报告结构不支持时显示明确格式提示,不用当前规则重新计算。
7. **增量迁移(本地已执行,部署其他环境仍须预检):** 先预检版本/异常金额/业务行数,备份目标结构与数据;追加fa_user_info五个字段、fa_ai_chat.analysis_context;新增金额/期限非负和范围CHECK允许历史NULL,用途字典在服务端校验。稳定查询确有需求再加索引,不为每个需求字段预先建索引。迁移工具需可重复执行、校验列类型与约束,不只检查列名。
8. **回滚:** 发布前停止或排空旧worker,再部署支持新context和v1/v2的消费者;重启后验证积压任务。回滚优先关闭新建v2、保留新列和兼容读取;存在v2任务/报告时不得直接退回只认v1的旧代码、删列或覆盖备份。恢复备份须先核对备份后新增业务数据,不自动重跑旧空库迁移。
## 8. 验收样例与任务归属
以下为验收条件全集。需求输入、字典/历史冻结、版本回放及重试保持已由76项专项检查和H5验证;41项基础、29项任务、15项HTTP回归通过。新增54项覆盖完整度/准备状态、执行快照、报告v2与模型引用校验,H5已验证个人79%、企业100%和未发布无分。三态匹配、真实产品证据、v2真实模型语义与渠道验收仍待完成,不能以已通过子集替代。
| 场景 | 验收结果 | 任务 |
| --- | --- | --- |
| 需求金额 | 12.345678万元精确往返123456.78元;0/负数/超上限/JSON number拒绝 | ASSESS-001、ASSESS-003、ASSESS-004 |
| 期限与用途 | 期限整数边界通过;0/小数拒绝;other缺说明拒绝,非other带说明拒绝,跨类型用途拒绝 | ASSESS-001、ASSESS-003 |
| 原键重放 | 同键同内容仍原回执;只改金额/期限/用途/说明/版本任一项409 | ASSESS-003 |
| 用途版本变化 | 提交后改名/停用不改旧标签,不阻断原键重放;新提交按当前发布字典校验 | ASSESS-003、REPORT-002 |
| 版本切换 | 最低新建版本2时,旧v1原键可重放,新v1键422;旧报告/失败重试保持v1 | ASSESS-002、ASSESS-003、REPORT-002 |
| 完整度 | 个人11/14=79,企业8/9=89;0/none计已填、null不计;other增加条件项 | REPORT-003 |
| 等级 | 未发布规则无分数/等级;所有字段已填但一致性异常仍需核实;100%不表示授信 | REPORT-003、REPORT-004 |
| 授权与来源 | 拒绝可选查询不扣完整度,不宣称信用正常;verified要求不可用self_reported替代 | FILE-004、PRODUCT-002、REPORT-003 |
| 产品边界 | 金额/期限等于上下界通过,超界fail;不拆额度、不改需求;other用途unknown | PRODUCT-002 |
| 三态合并 | fail+unknown→ineligible并保留两类证据;无fail有unknown不得进入候选 | PRODUCT-002 |
| 配置异常 | 无支持字段/非法操作符/用途或地区配置缺失阻止发布;运行配置损坏或完整度分母0明确failed,不生成成功报告 | PRODUCT-001、PRODUCT-003、REPORT-003 |
| 解释证据 | 所有理由可追溯到冻结规则/事实;不凑三条;模型不能改判定或宣称获批 | PRODUCT-004、REPORT-003 |
| 空结果 | 未运行unavailable≠已运行零候选≠执行failed;unknown单列显示 | PRODUCT-004、REPORT-004 |
| 快照与分页 | 改价/下架/规则更新不改历史;游标绑本人评估和结果;跨账户详情404 | ASSESS-002、PRODUCT-004 |
| 历史写入 | score/rank合法null可以写;违规组合拒绝;报告和匹配同事务,无部分成功报告 | REPORT-003 |
| 输入最小化 | 模型无手机号/证件/自由用途说明;任意文本不影响规则;错误日志不泄露资料 | ASSESS-003、REPORT-001 |
| 任务跨发布 | worker重启、重复消费、过期和重试保持冻结版本,旧taskId无权回写 | REPORT-002 |
实施顺序:DEC-DEMAND定用途/必填和字段 → ASSESS-001迁移与字典 → ASSESS-003 v2校验和幂等 → ASSESS-002/004确认与历史 → DEC-READINESS与REPORT-003完整度/等级 → DEC-MATCH、PRODUCT-001/002确定性匹配 → PRODUCT-003真实资料发布 → PRODUCT-004/REPORT-004解释和全链路验收。上下游可独立做规则测试,外部数据和真实产品未就绪时保持完整一期未验收。
本次沿用现有60个任务编号并扩展相关交付项,不把文档完成记成业务完成。原69—117人日是历史全量基线;新增版本兼容、上下文快照和解释交互须在上述决策完成后重估,不声称全部增量已包含原工时,也不把基线直接当最新剩余工作量。