feat: 实现采购运行时规格解析 (#255)
This commit is contained in:
@@ -153,55 +153,39 @@ func MatchSybSpecWithAI(ctx context.Context, db *sql.DB, actor *model.User, snap
|
||||
}
|
||||
bindings := bindAICandidates(eligible)
|
||||
baseDecision.CandidatesJSON = candidateAuditJSON(bindings)
|
||||
if snapshot.Client == nil || snapshot.Secret == "" || snapshot.Provider.ProviderID == "" {
|
||||
return recordAIMatchWithoutSave(db, baseDecision, "failed", "AI 服务商运行快照不可用")
|
||||
}
|
||||
request := AIModelMatchRequest{ProductTitle: truncateRunes(orderContext.Order.Title, 300), SourceSpec: truncateRunes(orderContext.Order.ProductSpec, 300)}
|
||||
for _, binding := range bindings {
|
||||
request.Candidates = append(request.Candidates, AIModelCandidate{ID: binding.ID,
|
||||
Label: truncateRunes(binding.Choice.Label, 300), Options: boundedAIOptions(binding.Choice.Options)})
|
||||
}
|
||||
response, modelErr := snapshot.Client.Match(ctx, snapshot.Provider, snapshot.Secret, request)
|
||||
if modelErr != nil {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "failed", safeAIError(modelErr))
|
||||
result.ModelCalled = true
|
||||
return result, auditErr
|
||||
}
|
||||
if err := validateAIModelMatchResponse(response); err != nil {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "failed", err.Error())
|
||||
result.ModelCalled = true
|
||||
return result, auditErr
|
||||
}
|
||||
selection := selectAIWhitelistedCandidate(ctx, snapshot, request)
|
||||
response := selection.Response
|
||||
baseDecision.ChosenCandidateID = response.CandidateID
|
||||
baseDecision.ConfidenceBPS = response.ConfidenceBPS
|
||||
baseDecision.ConfidenceSet = true
|
||||
baseDecision.Reason = response.Reason
|
||||
baseDecision.ConfidenceSet = selection.ConfidenceSet
|
||||
baseDecision.Reason = selection.Reason
|
||||
baseDecision.ConflictDimensionsJSON = stringArrayJSON(response.ConflictDimensions)
|
||||
baseDecision.MissingDimensionsJSON = stringArrayJSON(response.MissingDimensions)
|
||||
if response.Conclusion != "match" {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "rejected", response.Reason)
|
||||
result.ModelCalled = true
|
||||
if selection.Status != aiSelectionMatched {
|
||||
outcome := "rejected"
|
||||
if selection.Status == aiSelectionFailed {
|
||||
outcome = "failed"
|
||||
}
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, outcome, selection.Reason)
|
||||
result.ModelCalled = selection.ModelCalled
|
||||
return result, auditErr
|
||||
}
|
||||
selected, found := bindingByID(bindings, response.CandidateID)
|
||||
if !found {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "rejected", "模型返回了不在候选白名单中的编号")
|
||||
result.ModelCalled = true
|
||||
// selectAIWhitelistedCandidate 已核对过同一 request;此分支只防以后
|
||||
// 绑定构造被改坏时把错误候选写进真实映射。
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "rejected", "候选绑定已变化,未保存映射")
|
||||
result.ModelCalled = selection.ModelCalled
|
||||
return result, auditErr
|
||||
}
|
||||
baseDecision.ChosenOptionKey = selected.Choice.Key
|
||||
if len(response.ConflictDimensions) > 0 || len(response.MissingDimensions) > 0 {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "rejected", "模型报告仍有冲突或缺失维度")
|
||||
result.ModelCalled = true
|
||||
return result, auditErr
|
||||
}
|
||||
if response.ConfidenceBPS < snapshot.Provider.ConfidenceThresholdBPS {
|
||||
result, auditErr := recordAIMatchWithoutSave(db, baseDecision, "rejected", "模型置信度低于管理员设置的自动写入阈值")
|
||||
result.ModelCalled = true
|
||||
return result, auditErr
|
||||
}
|
||||
result, err := saveAutomaticMapping(db, *actor, *orderContext, selected.Choice, "ai", baseDecision)
|
||||
result.ModelCalled = true
|
||||
result.ModelCalled = selection.ModelCalled
|
||||
return result, err
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user