资讯动态

AI遇到两个同名联系人,业务表单该选哪一个?

发布时间:2026/10/30 4:54:24 来源:尧图企业网站定制
AI把“借给同名人员”填进业务表单页面上的姓名看起来正确保存的却可能是另一个ID。可靠做法是先在当前允许的数据范围里检索再按零个、一个、多个候选分别处理用户确认后仍按ID重新校验不能让模型替你猜一个身份。名称是输入ID才是业务引用用户说的是名称系统保存的是稳定对象引用。名称可能重复、改名或停用房间也可能在不同楼层同名。模型从句子提取“姓名”和“房间”可以作为检索条件但不应凭自然语言生成一个看似合理的内部ID。候选情况表单处理零个保留未确定状态提示换关键词或人工选择一个可提出这一对象供核对写入前仍校验有效性多个展示可区分的必要信息让用户确认展示信息要够消歧又不要顺带公开无关手机号等个人资料。独立示例使用合成ID、姓名与租户标识不包含真实人员。先限制可见范围再做名称匹配示例里t1有两个同名对象t2还有一个同名对象。先按租户和启用状态过滤t1的候选只能有两个若先把所有租户的候选交给模型再要求它别选错已经越过了数据可见边界。EF Core全局查询过滤文档说明了用当前租户上下文过滤查询的方式。实际业务还可能有对象级权限单个TenantId条件不能自动证明所有权限均已处理。用户确认之后再查一次对象是否仍可用候选展示到用户点击之间对象可能被停用或权限发生变化。独立示例返回明确的三态结果NotFound不产生候选票据Ambiguous返回多个候选Resolved表示唯一命中。后两种结果都带本次内存候选票据绑定允许范围、候选ID集合和过期时间。名称不直接落成业务ID确认通过才返回最终ID。确认时先核票据范围与过期再核选中的ID是否在原候选集合里最后重查对象是否仍启用。伪造一个未提供过的ID会返回NOT_OFFERED切换范围返回SCOPE_CHANGED停用返回CANDIDATE_UNAVAILABLE超期返回EXPIRED成功后再次确认返回TICKET_CONSUMED。示例在进程内锁内消费票据没有实现真实会话、签名或数据库事务生产还需把票据、当前权限与业务写入放入可验证的提交边界。AssetaGuard现有名称解析代码可见唯一命中、多候选和无候选分支以及按候选编码或用户名重新查找的路径。本文另加的确认时重查是独立示例设计不宣称现有所有表单都已有候选过期处理或完整对象级权限。用输入变化检查它有没有真的消歧本次运行检查三态结果、排除另一租户、五类拒绝码以及确认成功后返回原候选的合成ID。程序没有调用真实模型所以结果只验证解析与确认规则不能证明某个模型的自然语言准确率。先给自己的表单放入两个合成同名对象看界面是否要求选择再测试确认前停用或撤权的情况。完整独立示例以下程序使用合成数据不调用产品接口不需要账号、数据库或模型服务。准备 .NET 8或兼容SDK将项目文件与程序放入同一目录。运行命令为dotnet run --project . -- example-output输出文件写入指定目录。ProjectSdkMicrosoft.NET.SdkPropertyGroupOutputTypeExe/OutputTypeTargetFrameworknet8.0/TargetFrameworkImplicitUsingsenable/ImplicitUsingsNullableenable/Nullable/PropertyGroup/ProjectusingSystem.Text.Json;usingSystem.Globalization;varrootargs.Length0?Path.GetFullPath(args[0]):Path.Combine(Environment.CurrentDirectory,example-output);Directory.CreateDirectory(root);varresultsnewDictionarystring,object();CheckResolution();File.WriteAllText(Path.Combine(root,results.json),JsonSerializer.Serialize(results,newJsonSerializerOptions{WriteIndentedtrue}));voidRequire(boolvalue,stringcode){if(!value)thrownewInvalidOperationException(code);}voidCheckResolution(){varpeoplenewListPerson{new(u1,同名人员,t1,true),new(u2,同名人员,t1,true),new(u3,同名人员,t2,true)};varticketsnewDictionarystring,CandidateTicket();varnowDateTimeOffset.Parse(2026-01-01T00:00:00Z,CultureInfo.InvariantCulture);varcounter0;varmissingResolve(不存在,t1);Require(missing.StatusResolveStatus.NotFoundmissing.TicketIdnull,ZERO_MATCH);varambiguousResolve(同名人员,t1);Require(ambiguous.StatusResolveStatus.Ambiguousambiguous.CandidateIds.SequenceEqual(new[]{u1,u2}),SCOPE_BEFORE_MATCH);Require(Confirm(ambiguous.TicketId!,u3,t1,now).CodeNOT_OFFERED,FORGED_ID_ACCEPTED);Require(Confirm(ambiguous.TicketId!,u1,t2,now).CodeSCOPE_CHANGED,CROSS_SCOPE);people[0]people[0]with{Activefalse};Require(Confirm(ambiguous.TicketId!,u1,t1,now).CodeCANDIDATE_UNAVAILABLE,STALE_CANDIDATE);Require(Confirm(ambiguous.TicketId!,u2,t1,now.AddMinutes(6)).CodeEXPIRED,EXPIRED_ACCEPTED);varuniqueResolve(同名人员,t1);Require(unique.StatusResolveStatus.Resolvedunique.CandidateIds.Single()u2,ONE_MATCH);varconfirmedConfirm(unique.TicketId!,u2,t1,now);Require(confirmed.CodeCONFIRMEDconfirmed.EntityIdu2,CONFIRM_FAILED);Require(Confirm(unique.TicketId!,u2,t1,now).CodeTICKET_CONSUMED,REPLAY_ACCEPTED);results[A4]new{passedtrue,resultContractnew[]{NotFound,Ambiguous,Resolved},errorsnew[]{NOT_OFFERED,SCOPE_CHANGED,CANDIDATE_UNAVAILABLE,EXPIRED,TICKET_CONSUMED},confirmedEntityconfirmed.EntityId,modelCalledfalse};Console.WriteLine(PASS A4 resultStates3 rejectionCodes5 confirmedu2 modelCalledfalse);NameResolutionResolve(stringname,stringscope){varidspeople.Where(xx.Tenantscopex.Activex.Namename).Select(xx.Id).ToArray();if(ids.Length0)returnnew(ResolveStatus.NotFound,ids,null);varticketIdticket-counter;tickets[ticketId]new(scope,ids,now.AddMinutes(5),false);returnnew(ids.Length1?ResolveStatus.Resolved:ResolveStatus.Ambiguous,ids,ticketId);}ConfirmationConfirm(stringticketId,stringid,stringscope,DateTimeOffsetat){// 此票据只在本进程内存保存真实服务须绑定会话/权限并原子消费。lock(tickets){if(!tickets.TryGetValue(ticketId,outvarticket))returnnew(TICKET_NOT_FOUND,null);if(ticket.Scope!scope)returnnew(SCOPE_CHANGED,null);if(ticket.Consumed)returnnew(TICKET_CONSUMED,null);if(atticket.ExpiresAt)returnnew(EXPIRED,null);if(!ticket.CandidateIds.Contains(id))returnnew(NOT_OFFERED,null);if(!people.Any(xx.Ididx.Tenantscopex.Active))returnnew(CANDIDATE_UNAVAILABLE,null);tickets[ticketId]ticketwith{Consumedtrue};returnnew(CONFIRMED,id);}}}publicrecordPerson(stringId,stringName,stringTenant,boolActive);publicenumResolveStatus{NotFound,Resolved,Ambiguous}publicrecordNameResolution(ResolveStatusStatus,string[]CandidateIds,string?TicketId);publicrecordCandidateTicket(stringScope,string[]CandidateIds,DateTimeOffsetExpiresAt,boolConsumed);publicrecordConfirmation(stringCode,string?EntityId);

读完文章,也想定制专属网站?

尧图设计师 24 小时内与您沟通定制方案

免费获取报价 →
↑