Spring AI 面试题结构化输出怎么做Prompt 模板、实体解析、落库策略一次讲透如果你的 AI 应用只需要“回一段话”那普通聊天能力就够了但只要要进系统、进流程、进审批结构化输出就会变成第一优先级。这篇我就按 Java 项目里最常见的工单提取、简历解析、风控摘要这类场景来讲 Spring AI 的结构化输出怎么做。个人主页GitHub主页文章目录Spring AI 面试题结构化输出怎么做Prompt 模板、实体解析、落库策略一次讲透先看真实问题为什么很多模型回答看起来很聪明系统却还是接不住一张表先看懂纯文本回答和结构化输出到底差在哪举个具体例子售后工单智能分流模型先提取再决定是否转人工代码示例Prompt 模板 entity 映射 结果落库结构化 DTOSpring AI 结构化输出解析失败时的兜底处理SQL 示例结构化结果落库表系统设计时我会优先拆哪几层Prompt 约束层对象解析层落库与补偿层真正上线时最容易卡住的点监控和指标建议盯哪些如果面试官问我这块怎么设计我会这样答结语先看真实问题为什么很多模型回答看起来很聪明系统却还是接不住AI 项目里最常见的尴尬场景是模型回答看起来很完整但字段名称不稳定、布尔值表达不统一、时间格式前后不一最后后端根本没法直接入库。所以一旦涉及提取、分类、归因、摘要这些系统化动作关键目标就不是“让回答更像人”而是“让结果更像 Java 对象”。工单优先级、标签、是否升级到人工这些都应该是字段不应该只是正文里的描述如果解析失败没有兜底就会出现模型回了内容但流程节点没法继续往下走结构化输出不仅要关注模型效果还要考虑落库、补偿和重试一张表先看懂纯文本回答和结构化输出到底差在哪维度怎么做为什么纯文本前端展示友好系统不容易做后续流转结构化对象直接映射成 DTO适合进库、进规则、进审批模板约束提前规定字段和格式减少模型自由发挥解析兜底失败时走重试或人工审核避免链路卡死举个具体例子售后工单智能分流模型先提取再决定是否转人工用户提交一段售后描述后端先把标题、正文、历史客服记录拼成 Prompt。模型输出priority、category、needEscalation、actions这几个关键字段。如果needEscalationtrue系统直接创建人工工单否则进入自动回复流程。如果解析失败或者字段为空记录到异常表里后续做人工补录或重试。代码示例Prompt 模板 entity 映射 结果落库结构化 DTOpublicrecordTicketSummary(StringticketId,Stringcategory,Stringpriority,booleanneedEscalation,ListStringactions,Stringreason){}Spring AI 结构化输出ServiceRequiredArgsConstructorpublicclassTicketSummaryService{privatefinalChatClientchatClient;privatefinalAiExtractRecordRepositoryextractRecordRepository;publicTicketSummarysummarize(Ticketticket){TicketSummarysummarychatClient.prompt().system( 你是售后工单分流助手。 你必须输出结构化结果不要输出额外解释。 priority 只能是 LOW、MEDIUM、HIGH。 category 只能是 REFUND、LOGISTICS、QUALITY、OTHER。 ).user(u-u.text( 工单标题: {title} 工单正文: {content} 历史客服备注: {remark} 请完成分类、优先级判断并给出建议动作。 ).param(title,ticket.getTitle()).param(content,ticket.getContent()).param(remark,ticket.getLastRemark())).call().entity(TicketSummary.class);saveResult(ticket.getId(),summary);returnsummary;}privatevoidsaveResult(LongticketId,TicketSummarysummary){AiExtractRecordrecordnewAiExtractRecord();record.setBizId(ticketId);record.setExtractType(TICKET_SUMMARY);record.setResultJson(JsonUtils.toJson(summary));record.setParseStatus(SUCCESS);extractRecordRepository.save(record);}}解析失败时的兜底处理publicTicketSummarysafeSummarize(Ticketticket){try{returnsummarize(ticket);}catch(Exceptionex){extractRecordRepository.save(AiExtractRecord.fail(ticket.getId(),ex.getMessage()));returnnewTicketSummary(String.valueOf(ticket.getId()),OTHER,MEDIUM,true,List.of(建议转人工复核),模型解析失败已走人工兜底);}}SQL 示例结构化结果落库表createtableai_extract_record(idbigintprimarykeyauto_increment,biz_idbigintnotnullcomment业务主键例如工单ID,extract_typevarchar(64)notnullcomment提取类型,result_json jsonnotnullcomment结构化结果,parse_statusvarchar(32)notnullcommentSUCCESS/FAIL,error_messagevarchar(500)null,created_timedatetimenotnulldefaultcurrent_timestamp,updated_timedatetimenotnulldefaultcurrent_timestamponupdatecurrent_timestamp);系统设计时我会优先拆哪几层Prompt 约束层先把字段范围、枚举值、必填项写死不要靠模型自由发挥复杂场景建议一类任务一个模板不要让一个万能 Prompt 兼容所有提取任务对象解析层让结果尽量直接映射到 DTO后面业务代码更稳如果业务字段很多可以先提取一级摘要再做二次加工落库与补偿层成功结果和失败结果都要落库后面才好做回放和质量分析关键链路不要只信任一次模型输出要给人工复核留入口真正上线时最容易卡住的点没有给字段限定枚举值最后 priority 可能返回“较高”“高优先级”“urgent”各种写法。解析成功就直接当真值使用忽略了模型可能对边界样本判断错误。没有落失败日志后面根本不知道是 Prompt 写坏了还是模型偶发输出格式异常。监控和指标建议盯哪些结构化解析成功率字段缺失率、枚举越界率人工复核触发率不同模型在同一提取任务上的准确率和成本如果面试官问我这块怎么设计我会这样答如果面试官问 Spring AI 的结构化输出怎么做我会先讲这不是“模型回个 JSON”这么简单而是 Prompt 约束、实体解析、落库补偿三件事一起做。真正上线时我会先定义 DTO 和字段边界再用模板约束输出最后把成功和失败都落库保证流程可追踪、可回放、可纠错。结语AI 提取任务里最值钱的不是模型说得多漂亮而是它能不能稳定变成 Java 能消费的对象。你们如果在做 AI 分类或提取最头疼的是字段不稳定还是落库后怎么做人工兜底