DTO、Advisors

共 44 题
📑 题目列表 44 题
#
★★★

1. 会话、缓存、队列和定时任务怎样保存模型、Prompt、工具和数据版本以支持恢复

会话、缓存、队列和定时任务如何保存模型、Prompt、工具和数据版本,以支持异常后的恢复?

  • 版本化与可追溯
  • 会话/缓存/队列的持久化
  • 恢复与重放

为支持恢复,每个请求/会话应记录:使用的模型与版本、Prompt 模板版本、工具版本与 Schema、检索/数据版本(如向量库索引版本、知识库版本)、以及上下文片段。会话保存完整的消息序列与关键中间状态;缓存键应包含版本信息使版本变更自动失效;队列中的任务应记录任务元数据(输入、模型、版本、重试次数)以便重放;定时任务保存执行快照与水位线。恢复时按版本取一致的配置与数据,避免旧任务用新版本导致不一致。所有版本化信息汇入审计与 trace。

"版本化"让恢复可复现:模型、Prompt、工具、数据四个维度都要有版本,任何变更都可通过版本回溯。把版本写入会话/缓存/队列/任务元数据,是做可追踪恢复(时间旅行、重放、回滚)的前提。

#
★★★

2. 配置中心与 Vault 轮换密钥时,如何避免长连接、缓存客户端和正在执行任务使用失效凭证

配置中心与 Vault 轮换密钥时,如何避免长连接、缓存客户端和正在执行任务使用失效凭证?

  • 密钥轮换与动态刷新
  • 长连接与缓存客户端的凭证更新
  • 进行中任务的安全

轮换密钥时,长连接(如 HTTP 连接池、DB 连接)可能持有旧凭证,缓存客户端可能缓存旧 key。策略:Vault 提供动态密钥/租约,客户端通过监听(如 RefreshScope、配置监听)在轮换时重建客户端与连接池;连接池支持"优雅关闭旧连接 + 新建连接";进行中的任务要么在密钥到期前完成,要么用"双密钥过渡"(新旧并存,grace 期)保证不中断。凭证对象要避免长期缓存,改为按需获取或短租约。失败的任务要能重试并重新获取新凭证。

轮换的难点是"凭证面"与"资源面"的同步。通过动态刷新重建客户端、双密钥过渡、短租约与任务重试,避免长连接与进行中任务使用失效凭证。核心是"轮换不中断、过期可重试"。

#
★★★

3. 为什么“模型直接调用 Repository”是反模式,Tool Callback 与 Repository 之间应保留哪些业务层

为什么"模型直接调用 Repository"是反模式,Tool Callback 与 Repository 之间应保留哪些业务层?

  • 分层与职责
  • 安全与权限边界
  • 事务与幂等

模型直接调用 Repository 是反模式,因为 Repository 是数据访问层,暴露了结构、绕过业务校验、权限、审计与事务边界,模型(或 Agent)可能看到不该看的数据、执行未授权操作、绕过幂等与业务规则。Tool Callback 与 Repository 之间应保留业务层(Service):Service 负责鉴权、参数校验、业务规则、幂等、事务、审计与结果脱敏,Repository 只负责数据读写。Tool 调用 Service 而非直接访问 Repository,从而复用认证、授权、事务与幂等边界。

反模式的本质是"绕过业务边界"。模型应通过"业务门面"(Service)访问数据,而非直达 Repository,这样安全、权限、事务、审计都由业务层统一保障。这是"给模型留'门'而非'后门'"的关键。

#
★★★

4. Tool Callback 中的 @ToolParam(description = "...") 如何写得让模型“选对参数”而不被忽视

Tool Callback 中的 @ToolParam(description = "...") 应如何编写,让模型"选对参数"而不被忽视?

  • 参数描述质量
  • 语义明确与约束
  • 示例与边界

要让模型选对参数,描述要:语义明确(说明参数含义、单位、格式、取值范围);给出"何时用"与"何时不用"的指引;提供示例值(如时间格式、ID 格式);说明约束(必填、枚举、默认值);避免歧义同义词。描述应站在"模型如何决策"的角度,用清晰、具体、面向业务的语言,而非含糊的字段名。必要时用 @ToolParam(required=true) 标注必填,用枚举或正则约束合法值,从而减少模型生成错误参数。

模型"选对参数"依赖 Schema 描述的质量。描述要可执行、可决策:明确含义、格式、约束、示例与边界。这比"写个简短描述"更能引导模型,是提升 Tool Call 准确率的关键工程。

#
★★★

5. 如何做容量测试以发现虚拟线程、Reactor、HTTP 连接池和 Provider 配额中的真实瓶颈

如何做容量测试,以发现虚拟线程、Reactor、HTTP 连接池和 Provider 配额中的真实瓶颈?

  • 容量测试设计
  • 分层瓶颈识别
  • 压测与监控

容量测试应分层压测并逐步构造瓶颈:先测纯网络/Reactor 层(不接 Provider)确定吞吐上限;再接入真实或模拟 Provider 观察连接池与并发;逐步提高并发观察虚拟线程、事件循环、连接池与 Provider 配额(TPM/并发限制)各自的表现。通过监控线程数、连接池水位、延迟分布、错误率与 Provider 限流,找到"谁先到顶"。压测要模拟真实负载分布(长上下文、长输出、突发),并观察 P95/P99 而非仅平均。用故障注入(延迟、限流)验证各层在压力下的行为。

瓶颈往往在"某层先到顶"。分层压测 + 逐层叠加 + 全维度监控,才能定位是虚拟线程、Reactor 事件循环、连接池还是 Provider 配额。容量测试要输出"各层上限",为容量规划与限流配置提供依据。

#
★★★

6. 依赖版本和 API 状态为什么必须按官方文档与制品仓库共同核查

依赖版本和 API 状态为什么必须按官方文档与制品仓库共同核查?

  • 官方文档与制品仓库的差异
  • 版本真实性
  • API 状态确认

官方文档描述"应该怎么用",制品仓库(Maven Central、GitHub Releases)反映"实际发布的版本与坐标"。两者必须共同核查,因为:文档可能领先或滞后于实际发布版本;某个 API 只在特定版本存在;坐标(groupId/artifactId/版本)可能变化;deprecated/experimental 状态在文档与制品中可能有出入。仅信文档可能引入不存在的版本或 API,仅信制品可能偏离文档语义。因此结合文档(用法的语义)与制品仓库(真实存在的版本与坐标)确认"版本存在、坐标正确、API 状态符合预期"。

核查是"语义 + 事实"双源校验。文档给语义与用法,制品仓库给版本与坐标事实。二者一致才能确保依赖可下载、API 存在且状态符合预期。这能防止"文档抄错 API"或"引用不存在版本"。

#
★★★

7. 怎样演练 Provider 故障、知识库不可用和结构化输出持续失败时的分层降级

怎样演练 Provider 故障、知识库不可用和结构化输出持续失败时的分层降级?

  • 故障场景识别
  • 分层降级策略
  • 演练与验证

分层降级应从上到下逐层降级:Provider 故障 → 切换到备用模型/降级到缓存回复;知识库不可用 → 跳过 RAG 检索,用模型固有能力或提示"知识库暂不可用";结构化输出持续失败 → 降级为自由文本或返回明确的错误建议。演练用故障注入(Toxiproxy、Chaos)模拟 Provider 故障、知识库 504、结构化输出反复失败,验证每一层降级路径是否生效、是否有兜底(超时、告警、优雅降级消息)。关键是定义"降级到哪一层"与"何时恢复",并测试降级后的用户体验与监控。

降级是"可停放、可回退"的层次。演练确保每层故障都有明确降级与兜底,而非任其崩溃。分层降级 + 故障演练 + 恢复验证,是可用性工程设计的关键。

#
★★★

8. 模型结构化输出映射 Java DTO 后,JSON Schema、反序列化与 Bean Validation 应如何分层

模型结构化输出映射 Java DTO 后,JSON Schema、反序列化与 Bean Validation 应如何分层?

  • JSON Schema 约束
  • 反序列化容错
  • Bean Validation 校验

三层职责:JSON Schema 用于"生成前约束"——让模型按 Schema 输出合法结构(字段类型、必填、枚举);反序列化用于"转换容错"——把 JSON 转成 DTO,容忍未知字段、缺失字段、类型不匹配(@JsonIgnoreProperties、默认值);Bean Validation 用于"业务校验"——在 DTO 上校验业务规则(@NotNull、@Size、@Pattern),校验失败给出明确错误。分层意义:Schema 约束模型输出,反序列化兜底格式差异,Validation 校验业务语义。三者配合形成"生成约束 → 转换容错 → 业务校验"的完整链路。

分层让"模型输出质量"与"代码健壮性"分离。Schema 提升生成质量,反序列化容错,Validation 兜底业务。校验失败可反馈给模型重试(配合 StructuredOutputValidationAdvisor)。

#
★★★

9. Tool Callback 调用 Spring Service 时,怎样复用认证、授权、幂等和事务边界而不让模型直接访问 Repository

Tool Callback 调用 Spring Service 时,如何复用认证、授权、幂等和事务边界,而不让模型直接访问 Repository?

  • 业务层复用
  • 认证授权传递
  • 幂等与事务

Tool Callback 应调用 Spring Service(业务层)而非 Repository,从而复用 Service 上已有的认证、授权、幂等与事务边界。认证/授权通过上下文(Context Propagation、SecurityContext)传递当前用户与租户,Service 内做权限校验;幂等通过业务键/请求 ID 保证;事务通过 @Transactional 在 Service 边界管理。模型/Agent 只持有"调用 Service 的入口",不直接拿到数据访问能力。这样模型体现的是"业务操作"而非"数据结构访问"。

复用业务边界的本质是"让模型走业务门面"。认证、授权、幂等、事务都是横切属性,集中在 Service 层,模型调用 Service 即自动获得这些保障。避免模型直接访问 Repository 是安全与正确性的根本。

#
★★★

10. Spring AI 2.0 StructuredOutputValidationAdvisor 如何在 JSON Schema 校验失败时反馈错误并触发模型重试,避免无限循环

Spring AI 2.0 StructuredOutputValidationAdvisor 如何在 JSON Schema 校验失败时反馈错误并触发模型重试,避免无限循环?

  • 校验失败反馈
  • 重试机制
  • 循环保护

StructuredOutputValidationAdvisor 在模型输出后校验其是否符合 JSON Schema,失败时把校验错误信息反馈回模型(追加"输出格式错误,请修正"的上下文),并再次调用模型,从而让模型自纠。为避免无限循环,需设置最大重试次数(如 3 次),达到上限后返回错误或降级;每次重试记录错误反馈与重试次数,超限即停止并给出明确失败。反馈信息要具体(指出哪个字段、什么约束),提高模型修正成功率。

反馈重试是"纠正循环",但必须有终止条件。错误反馈要具体、可执行,重试次数要有限,避免无限循环消耗成本。核心是"有界重试 + 具体反馈 + 失败兜底"。

#
★★★

11. Java DTO 反序列化模型输出时(Jackson、Gson)应如何处理常见的格式问题

Java DTO 反序列化模型输出时(Jackson、Gson),应如何处理常见的格式问题?

  • 反序列化器选择
  • 容错配置
  • 类型与结构处理

反序列化模型输出时,关键处理:未知字段 → @JsonIgnoreProperties(ignoreUnknown=true) 或 Jackson 的 FAIL_ON_UNKNOWN_PROPERTIES=false;缺失字段 → 用默认值或 @Nullable 声明;类型不匹配 → 编写自定义反序列化器或容错转换;嵌套结构 → 用 DTO 分层 + 泛型正确声明。Jackson 功能更全(与 Spring 集成好),Gson 更轻量。无论哪种,都要容忍模型输出的不规范性,并配合反序列化后的校验兜底。可配置自定义 ObjectMapper 处理模型输出的宽松格式。

模型输出具有不确定性,反序列化必须"容错优先"。未知字段忽略、缺失字段默认、类型不匹配容错,再以校验兜底。Jackson/Gson 的选择取决于生态与需求,容错策略是共同的。

#
★★★

12. Java DTO 反序列化模型输出时(Jackson、Gson)应如何容错未知字段、类型不匹配与缺失字段,校验失败如何反馈给模型重试

Java DTO 反序列化模型输出时(Jackson、Gson)应如何容错未知字段、类型不匹配与缺失字段,校验失败如何反馈给模型重试?

  • 容错处理
  • 校验失败反馈
  • 重试闭环

容错:未知字段用 @JsonIgnoreProperties(ignoreUnknown=true) 忽略;类型不匹配用自定义反序列化器或宽松转换(如字符串转数字、宽容枚举);缺失字段用默认值或声明可空。反序列化后做 Bean Validation,校验失败(如必填缺失、长度超限)时,把失败信息(字段、期望值、实际值)反馈给模型,提示其修正输出并重试(通过 StructuredOutputValidationAdvisor 或手动重试逻辑),并设置最大重试次数。这样形成"容错 → 校验 → 反馈 → 重试"闭环。

容错与校验是"松输入、紧输出":输入容忍格式差异,输出校验业务语义。校验失败反馈给模型能自纠,但需限次。闭环让模型输出从"可能不合法"走向"合法可用"。

#
★★★

13. RAG、记忆、日志和安全 Advisors 的顺序为何重要,异常和短路行为如何测试

RAG、记忆、日志和安全 Advisors 的顺序为何重要,异常和短路行为如何测试?

  • Advisor 顺序影响
  • 短路与异常
  • 测试方法

Advisor 顺序决定上下文组装与安全边界:记忆 Advisor 应先注入历史,RAG 再注入检索上下文,日志/观测在最外层记录,安全 Advisor 应尽早或按需拦截(如敏感内容过滤)。顺序错误会导致上下文缺失(如记录看不到请求)或安全被绕过(如日志先泄漏敏感信息)。异常与短路:安全拦截失败应短路(不调用模型),RAG/记忆失败可降级继续。测试用 StepVerifier/WebTestClient 验证各 Advisor 的触发顺序、短路路径(安全拦截时不调用模型)、降级路径(RAG 失败时跳过)与异常传播、上下文是否正确传递。

顺序是"安全、上下文、观测"的编排。测试要验证"顺序正确 + 短路/降级正确 + 异常传播正确"。用响应式测试与 mock 验证 Advisor 链行为,是保障正确性的关键。

#
★★

14. DTO 版本协商、灰度切换与回滚的工程实践是怎样的,如何验证向下兼容

DTO 版本协商、灰度切换与回滚的工程实践是怎样的,如何验证向下兼容?

  • DTO 版本策略
  • 灰度与回滚
  • 兼容性验证

DTO 版本协商:引入版本字段(如 schemaVersion)或媒体类型版本(Accept: application/vnd.x+json;version=1),新旧客户端可并存。灰度切换:新 DTO 改造通过双写/影子对比(新旧并行,比较结果)验证,再逐步灰度到全量。回滚:保留旧 DTO 与映射,支持按版本回滚。向下兼容验证:新增字段默认值、不删旧字段、不改变类型语义;用契约测试(新旧 schema 对比)与兼容性测试保证旧客户端可读新响应。构建"版本矩阵"测试覆盖新旧组合。

DTO 演进的工程实践是"版本化 + 灰度 + 回滚 + 兼容验证"。向下兼容靠"增量字段默认值 + 契约测试 + 影子对比"。回滚能力靠版本映射保留。这是稳定演进 DTO 的关键。

#
★★

15. Micrometer Observation API 与 OpenTelemetry 在 Spring AI 2.0 中应如何同时启用而不重复埋点

Micrometer Observation API 与 OpenTelemetry 在 Spring AI 2.0 中应如何同时启用而不重复埋点?

  • Observation 与 OTel 集成
  • 埋点去重
  • 桥接机制

Micrometer Observation 是统一观测抽象,OpenTelemetry 是具体的 trace 实现。Spring AI 2.0 用 Observation API 埋点,通过 Micrometer Tracing 的 OTel Bridge 把 Observation 自动转换为 OTel span,从而"一次埋点、双向输出"(指标 + trace)。避免重复埋点:不要在应用层同时手动创建 Observation 与 OTel span,而是用 Observation 作为唯一埋点源,让 OTel 桥接自动生成 span;指标通过 Observation 的 timer/counter 输出,trace 通过桥接生成。启用步骤:引入 spring-boot-starter-actuator + micrometer-tracing-bridge-otel + OTel exporter,配置 Observation 自动装配。

去重的核心是"Observation 单一埋点源 + OTel 桥接自动转换"。避免在同一路径上既手动 Observation 又手动 OTel,否则重复。架构上让 Observation 成为统一入口,兼顾指标与 trace。

#
★★

16. Spring AI 流式响应如何通过 Observation API 记录 TTFT、TPOT、Token 等低基数指标

Spring AI 流式响应如何通过 Observation API 记录 TTFT、TPOT、Token 等低基数指标?

  • Observation 指标
  • 低基数设计
  • 流式时序指标

通过 Observation API 在流式响应生命周期中埋点:TTFT(首 token 延迟)在收到第一个 chunk 时记录,TPOT(每 token 时间)在流式过程中计算,Token 数(usage)在流结束时记录。指标应低基数(不带高基数标签,如用户 ID、完整 prompt),只带模型、Provider、业务类型等低基数标签,避免监控系统过载。用 Observation 的 timer 记录 TTFT/TPOT,用 counter/histogram 记录 token 数,并将这些指标与 span 关联(通过 Observation 的 traceId)。流式场景注意在 doOnNext/doFinally 中更新相关指标。

低基数指标设计是"可观测性工程"的要点:TTFT/TPOT/Token 是时序与计费关键指标,但标签必须低基数以免撑爆监控。用 Observation 统一埋点,让指标与 trace 关联,同时保持低基数。

#
★★

17. Java 应用的依赖版本(Spring Boot、Spring AI、LangChain4j)应如何锁定与升级,避免 Provider 兼容性回归

Java 应用的依赖版本(Spring Boot、Spring AI、LangChain4j)应如何锁定与升级,避免 Provider 兼容性回归?

  • 版本锁定
  • 升级流程
  • 兼容性回归

版本锁定:用 BOM 与依赖分析统一管理版本,锁死 Spring Boot、Spring AI、LangChain4j 及向量库驱动,避免隐性版本漂移。升级:遵循"升级评估 → 契约测试 → 兼容回归 → 灰度 → 回滚准备"流程,重点关注 Provider 兼容性(不同版本对模型 API、流事件、工具格式的适配差异)。兼容性回归用契约测试覆盖各 Provider 的请求/响应、流事件、错误码;用灰度验证生产行为;保留回滚。升级记录版本变更与影响,纳入审计。

依赖治理是"锁定 + 受控升级"。锁定避免漂移,受控升级(评估→测试→灰度→回滚)避免兼容性回归。Provider 兼容性是 Java AI 应用版本升级特有的高风险点,需契约测试把守。

#
★★

18. 本地容器化的模型(Ollama、LocalAI)在 Java 测试中如何快速启动并断言输出

本地容器化的模型(Ollama、LocalAI)在 Java 测试中如何快速启动并断言输出?

  • 容器化模型启动
  • 测试断言
  • 确定性控制

用 Testcontainers 启动 Ollama/LocalAI 容器,拉取模型镜像,在测试中运行。为快速与确定性:用较小的模型(如 qwen/tiny 模型)、预热容器、固定采样参数(temperature=0)提高确定性;断言输出时用"包含/匹配"而非精确相等(模型输出有随机性),或对结构化输出做 schema 断言。测试用 JUnit 集成,容器作为 @BeforeAll 启动,关闭时清理。对需要确定性的场景,用 MockLLM/WireMock 替代真实模型,本地模型用于端到端冒烟。

本地模型测试的关键是"快速启动 + 确定性断言"。Testcontainers 管理容器生命周期,小模型 + 固定采样提高确定性,断言用宽松匹配。确定性严格时用 MockLLM 替代,真实模型用于冒烟。

#
★★

19. Java AI 应用的发布门禁应包含哪些硬指标(Prompt 校验、Schema 通过、安全分类)

Java AI 应用的发布门禁应包含哪些硬指标(如 Prompt 校验、Schema 通过、安全分类)?

  • 发布门禁指标
  • Prompt 与 Schema 校验
  • 安全分类

发布门禁应包含硬指标:Prompt 校验通过率(模板不缺失参数、不违反约束)、结构化输出 Schema 通过率(金标准集上输出合法结构)、安全分类正确率(安全/敏感内容识别准确)、回归测试通过率、以及关键性能指标(TTFT/P95 不超阈值)。门禁在 CI 中自动执行,任一硬指标不达标即阻断发布。还应有金标准集回归(行为不退化)与红队测试(对抗输入不越界)。指标要可量化、可阈值化、可审计。

门禁是"质量红线"。Prompt 校验、Schema 通过、安全分类是 AI 应用特有的硬指标,必须可量化并纳入 CI 自动阻断。金标准集与红队测试覆盖"行为正确"与"安全边界"两维度。

#
★★

20. Java 应用的混沌测试应如何覆盖模型返回错误 JSON、向量库 504、工具超时三类典型故障

Java 应用的混沌测试应如何覆盖模型返回错误 JSON、向量库 504、工具超时三类典型故障?

  • 故障注入
  • 混沌测试设计
  • 降级验证

用 Chaos 工具(Toxiproxy、故障注入)分别注入三类故障:模型返回错误 JSON(用 MockLLM 注入畸形输出)→ 验证反序列化容错与重试;向量库 504 → 验证 RAG 降级(跳过检索/缓存);工具超时 → 验证工具调用超时、取消与降级。混沌测试验证应用在故障下的行为:是否优雅降级、是否记录错误、是否恢复。测试随机化故障组合与顺序,观察系统稳定性。关键断言:故障时请求不崩溃、有明确降级、有监控告警、恢复后自动回正常。

混沌测试是"故障注入 + 降级验证"。三类典型故障(错误 JSON、向量库 504、工具超时)分别对应容错、降级、超时三条链路。测试要验证"故障下可用 + 恢复后正常 + 有观测"。

#
★★

21. Spring AI 2.0 升级破坏既有 API 时,应如何保留双版本共存并按业务粒度路由回退

Spring AI 2.0 升级破坏既有 API 时,应如何保留双版本共存并按业务粒度路由回退?

  • 双版本共存
  • 业务粒度路由
  • 回退方案

升级破坏 API 时,可为旧版与新版各维护一套适配实现(Adapter 模式),通过 Bean 别名或不同包共存,运行时按业务粒度路由(如按业务类型、租户、灰度比例)选择新旧实现。回退时按业务粒度切换回旧实现,无需整体回滚。关键是:新旧实现接口一致(同为领域接口),配置中心可动态切换路由规则,双版本共享同一领域契约与测试。影子对比(新旧并行跑)验证新版行为后放量。

双版本共存 + 业务粒度路由是"平滑升级 + 可回退"的关键。Adapter 让新旧实现共用领域接口,配置中心按业务粒度切回退,避免破坏性升级的停机。影子对比保障切换前的正确性。

#
★★

22. Java 应用遥测数据应如何脱敏(Prompt、Token、用户输入)

Java 应用遥测数据应如何脱敏(Prompt、Token、用户输入)?

  • 遥测脱敏
  • 敏感字段识别
  • 脱敏策略

遥测(日志、trace、指标)中的 Prompt、Token、用户输入可能含敏感信息(PII、密钥、业务秘密)。脱敏策略:对 Prompt/用户输入做字段级脱敏(掩码、哈希、截断),不记录完整内容;对 Token 记录数量而非内容;对密钥/令牌识别并替换为占位符;日志/span 中只保留低基数、低敏感信息。脱敏在埋点前完成(统一 Filter/切面),对 trace 的 span attribute 做脱敏配置。脱敏策略要可配置、可审计,并分级(生产只记脱敏,开发可记完整)。

脱敏要"在源头做"。Prompt/Token/用户输入在进入遥测前统一脱敏,避免敏感信息随日志/trace 泄露。脱敏与审计结合,满足合规与安全。核心是"记录必要信息,隐藏敏感信息"。

#
★★

23. Java 应用的发布流程应如何集成 Prompt 单元测试、金标准集回归与红队对抗三类门禁

Java 应用的发布流程应如何集成 Prompt 单元测试、金标准集回归与红队对抗三类门禁?

  • 三类门禁
  • 发布集成
  • 自动化

Prompt 单元测试:验证 Prompt 模板结构、参数插值、约束满足(不因变量导致缺失/越界)。金标准集回归:用固定输入-期望输出集验证模型行为不退化(输出结构、语义、关键内容)。红队对抗:用对抗输入(越权、注入、敏感内容)验证安全分类与拒绝。三类门禁在 CI 中按序执行:Prompt 单元测试(快)→ 金标准回归(中)→ 红队(慢),任一失败阻断发布。金标准集与红队集需随业务演进维护,门禁结果为可审计证据。

三类门禁覆盖"结构正确、行为不退化、安全边界"三个维度,且成本递增,适合分层集成。发布流程把它们作为硬门禁,保证每次发布都经过质量与安全验证。

#
★★

24. RAG 检索如何使用数据库 RLS、租户过滤和用户权限,避免 Advisor 只拼接未授权上下文

RAG 检索如何使用数据库 RLS、租户过滤和用户权限,避免 Advisor 只拼接未授权上下文?

  • 检索期权限过滤
  • RLS 与租户隔离
  • 授权上下文

避免"只拼接未授权上下文"的关键是"检索期过滤"而非"检索后二次过滤"。检索时就用当前用户/租户的权限约束查询:向量库/数据库用 RLS(行级安全)或显式租户/权限过滤条件,把检索范围限制在用户有权访问的文档集。Advisor 只接收已过滤的检索结果,不再拼接未授权内容。用户权限(角色、ACL、文档级权限)在检索时注入查询过滤器,确保每个结果都经过授权校验。检索期过滤避免"先把全部结果拼进 Prompt 再过滤"导致的泄露与 token 浪费。

权限必须在检索期(数据访问层)强制,而非检索后(应用层)过滤。检索后过滤不可靠(可能把未授权内容已拼入上下文)。RLS/租户过滤/ACL 注入让检索结果天然受限,Advisor 只拼已授权内容。

#
★★

25. RAG 检索结果注入 Prompt 时,如何保证租户隔离而非依赖 Advisor 后的二次过滤

RAG 检索结果注入 Prompt 时,如何保证租户隔离,而不是依赖 Advisor 后的二次过滤?

  • 租户隔离
  • 检索期过滤
  • 二次过滤的陷阱

租户隔离必须在检索期通过租户过滤实现:向量检索/数据库查询时强制带上当前租户条件,使检索结果只属于当前租户。依赖 Advisor 后的二次过滤风险在于:未授权内容可能已被拼入 Prompt 或经 embedding 计算,二次过滤不可靠且浪费。实现:检索服务接收租户上下文,构造过滤条件(元数据字段 = 租户 ID),向量库/DB 用 RLS 或查询过滤强制隔离。Advisor 只负责组装已过滤的检索结果,不承担隔离职责。对租户 ID 做校验,防止越权读取。

租户隔离是"数据面的强制约束",必须在检索期(数据访问层)应用。二次过滤是"应用面的兜底",不可靠。核心是让检索查询天然带租户边界,从源头保证隔离。

#
★★

26. 多个 Advisor 串联时(LoggingAdvisor → RAGAdvisor → SafetyAdvisor → ChatMemoryAdvisor)的执行顺序与上下文传递如何设计,异常时如何降级?

多个 Advisor 串联时(如 LoggingAdvisor → RAGAdvisor → SafetyAdvisor → ChatMemoryAdvisor)的执行顺序与上下文传递如何设计,异常时如何降级?

  • Advisor 顺序设计
  • 上下文传递
  • 异常降级

顺序设计:LoggingAdvisor 最外层(记录请求/响应,含 trace),ChatMemoryAdvisor 注入历史(应早于 RAG 以合并上下文),RAGAdvisor 注入检索上下文,SafetyAdvisor 在最终 Prompt 前做安全过滤(可软/硬拦截)。上下文通过 Advisor 链传递的 context(Map)在各 Advisor 间共享(如检索结果、记忆、安全标记)。异常降级:Logging/RAG/Memory 失败可降级(跳过或记录),Safety 失败应默认"拒绝"(降级为安全响应),最终模型调用失败走全局错误处理。降级策略按 Advisor 的重要性配置,关键安全 Advisor 不降级。

顺序以"上下文组装 + 安全边界"为准则:记忆→RAG→安全→模型。上下文在链中传递,异常降级要区分"可降级"(RAG/记忆/日志)与"不可降级"(安全)。降级策略需与业务风险匹配。

#
★★

27. Spring AI MessageChatMemoryAdvisor 使用的会话存储(InMemory、JdbcChatMemory、RedisChatMemory)如何选型与扩展

Spring AI MessageChatMemoryAdvisor 使用的会话存储(InMemory、JdbcChatMemory、RedisChatMemory)如何选型与扩展?

  • 会话存储选型
  • 持久化与并发
  • 扩展

选型依据:InMemory 适合单实例、测试、原型(无持久化、重启丢失);JdbcChatMemory 适合需要持久化、事务一致、多实例共享的数据库场景;RedisChatMemory 适合高并发、分布式、低延迟场景(支持 TTL、多实例共享)。扩展:可通过实现 ChatMemory 接口自定义存储(如向量库、对象存储),附加 TTL、容量上限、会话清理等策略。多实例部署必须用共享存储(Jdbc/Redis)而非 InMemory,避免会话隔离与数据丢失。选型考虑持久化需求、并发规模、运维成本。

会话存储选型是"持久化、并发、分布式"的权衡。单实例原型用 InMemory,需持久化用 Jdbc,高并发分布式用 Redis。扩展通过实现 ChatMemory 接口,附加容量与 TTL 策略。多实例必须共享存储。

#
★★

28. spring-ai-session 与 spring-ai-agent-utils 属于 community 而非 Spring AI 2.0 core,这对依赖治理意味着什么?

spring-ai-session 与 spring-ai-agent-utils 属于 community 而非 Spring AI 2.0 core,这对依赖治理意味着什么?

  • community 模块的性质
  • 依赖治理
  • 风险与锁定

community 模块不由 core 团队保证相同的发布节奏、兼容性与支持,可能版本滞后、API 变动、缺少长期维护。对依赖治理意味着:使用 community 模块时要锁定版本、关注其与 core 的兼容性、评估其维护活跃度与许可证;不能用 core 的版本语义想当然地假设 community 模块同步更新;升级时需单独验证 community 模块的兼容性;必要时评估是否可替换为自研或 core 功能。记录的依赖要纳入 SCA 与版本审计。

community 模块是"非核心依赖",治理需更谨慎:锁定版本、单独验证兼容、评估维护风险。不能假设其与 core 同步或受同等支持。这是供应链治理的一部分。

#
★★

29. Java DTO 上的 Jakarta Validation(@NotNull、@Size)与 JSON Schema 校验应如何分工

Java DTO 上的 Jakarta Validation(@NotNull、@Size)与 JSON Schema 校验应如何分工?

  • 两类校验职责
  • 分工边界
  • 协同

JSON Schema 校验用于"模型输出结构"验证——在模型调用层校验输出是否符合 Schema(字段类型、必填、枚举、结构),并反馈给模型重试;Jakarta Validation 用于"业务语义"校验——在 DTO 上做业务规则校验(@NotNull、@Size、@Pattern、@Min/@Max),在 Service 层执行。分工:JSON Schema 管"模型生成的结构合法性",Jakarta Validation 管"DTO 的业务语义合法性"。两者可互补:Schema 在接口边界校验,Jakarta 在业务层边界校验。结构化输出验证通常用 Schema,业务数据校验用 Jakarta。

分工是"生成结构"与"业务语义"的区分。JSON Schema 约束模型输出格式并支持重试,Jakarta Validation 约束业务规则。两者在不同边界(模型层 vs 服务层)协作,避免重复但职责清晰。

#
★★

30. Spring AI 2.0 自定义 Advisor 时,call() 与 observe() 方法分别适合什么场景

Spring AI 2.0 自定义 Advisor 时,call() 与 observe() 方法分别适合什么场景?

  • call() 与 observe() 的职责
  • 同步/响应式场景
  • 模型观测

自定义 Advisor 时,call() 用于拦截模型调用本身(before/after 的执行逻辑,如注入上下文、修改请求、处理结果);observe() 用于观测模型调用(记录指标、span、调用统计),是对模型调用的可观测钩子。通常 call() 做业务/横切增强(RAG、记忆、安全),observe() 做可观测性(记录调用、token、延迟)。实现对二者分别实现,让业务逻辑与观测逻辑分离。observe() 特别适合记录模型调用级的指标而不影响业务流。

call() 是"执行拦截",observe() 是"观测钩子"。业务增强用 call(),指标/span 用 observe()。分离让可观测性与业务逻辑解耦,也便于复用与测试。

#
★★

31. Java 端的 RAG QuestionAnswerAdvisor 与 LangChain4j 的 RetrievalAugmentor 在实现复杂度上各自优势

Java 端的 RAG QuestionAnswerAdvisor 与 LangChain4j 的 RetrievalAugmentor 在实现复杂度上各自优势?

  • 两种 RAG 抽象
  • 复杂度与灵活性
  • 选型

Spring AI 的 QuestionAnswerAdvisor 是 Advisor 形式,与 Spring AI 生态集成,通过 Advisor 链注入检索上下文,实现相对轻量、声明式,适合已用 Spring AI 的团队,配置简单但定制能力有限。LangChain4j 的 RetrievalAugmentor 提供更丰富的 RAG 配置(检索器、重排、路由、多种注入策略),功能更强大、灵活,但配置复杂、学习成本高。选型:简单场景用 QuestionAnswerAdvisor,复杂 RAG 管线(混合检索、重排、多源)用 RetrievalAugmentor。复杂度换取灵活性是主要权衡。

取舍是"简单 vs 灵活"。QuestionAnswerAdvisor 易上手、与 Spring AI 一致;RetrievalAugmentor 功能强、配置复杂。按 RAG 复杂度与团队熟悉度选择,避免过度设计或能力不足。

#
★★

32. Spring AI 2.0 中 ChatClient 流式响应的取消、超时与异常如何在多 Advisor 链路下被一致传播与观测

Spring AI 2.0 中 ChatClient 流式响应的取消、超时与异常如何在多 Advisor 链路下被一致传播与观测?

  • 取消/超时/异常传播
  • 多 Advisor 链路
  • 一致观测

在多 Advisor 链路下,取消、超时与异常应沿响应式链一致传播:取消通过 Subscription.cancel() 传播到各 Advisor 与底层 WebClient;超时通过配置的 timeout 传播并触发 onErrorResume;异常通过 onErrorResume 沿链传播并映射为业务错误。每个 Advisor 都应尊重取消/错误信号(不在取消后继续处理),并在 doFinally 中统一结束观测(span 结束、指标记录)。观测通过 Observation 在链外层统一建立,记录取消/超时/异常类型,保证多 Advisor 下 trace 完整。测试用 StepVerifier 验证取消/错误的传播与观测。

一致传播的关键是"响应式信号(取消/错误/完成)沿链传递 + 观测统一"。Advisor 不得吞掉或忽略取消/错误,观测在链外层统一收口。这是多 Advisor 复杂链路下可观测与正确性的基础。

#
★★

33. 如何用 WireMock/MockLLM、本地模型容器和真实沙箱分别测试 Provider 适配器

如何用 WireMock/MockLLM、本地模型容器和真实沙箱分别测试 Provider 适配器?

  • 测试金字塔
  • 各层测试用途
  • 取舍

测试金字塔分层:WireMock/MockLLM 用于单元/契约测试——精确控制请求/响应、流事件、错误,验证适配器逻辑与错误映射,快而稳定;本地模型容器(Ollama/LocalAI)用于集成测试——端到端验证适配器与真实 HTTP 协议、流式、解析,接近真实但较慢;真实沙箱用于验收/冒烟——用真实 Provider 验证最终行为、鉴权、配额、真实模型输出,但成本高、不稳定。取舍:单元测试覆盖大部分逻辑,集成测试覆盖协议,沙箱验证真实行为。测试分布在金字塔,成本与真实性平衡。

三层测试覆盖"逻辑、协议、真实行为"。Mock 精确可控、容器接近真实、沙箱真实但贵。按金字塔分层,控制成本与稳定性,同时保证适配器在真实环境可靠。

#
★★

34. 如何用 StepVerifier 或 WebTestClient 验证流事件顺序、半包、错误、取消和资源释放

如何用 StepVerifier 或 WebTestClient 验证流事件顺序、半包、错误、取消和资源释放?

  • 响应式测试
  • 流事件验证
  • 错误/取消/资源

StepVerifier 用于验证 Flux:检查事件顺序(expectNext 按序)、半包/分块(expectNext 多次)、错误(expectError 及错误类型)、取消(verifyThenAssertThat 后检查取消)、以及资源释放(用 concatWith/doFinally 断言清理逻辑)。WebTestClient 用于验证 HTTP 层:SSE 流格式、状态码、错误响应、流式内容。测试要点:用 StepVerifier 逐步消费事件断言顺序,用 verifyTimeout 验证取消,用 doFinally 断言资源释放。测试覆盖"正常流、错误流、取消流"三类。

StepVerifier 是响应式流的断言工具,能验证顺序、半包、错误、取消与资源释放。WebTestClient 覆盖 HTTP/SSE 层。二者结合验证流式端到端的正确性,是响应式测试的关键。

#
★★

35. 怎样用 Toxiproxy 或 Chaos 工具注入延迟、断连、429 和半开连接,验证退避与断路器

怎样用 Toxiproxy 或 Chaos 工具注入延迟、断连、429 和半开连接,验证退避与断路器?

  • 故障注入工具
  • 延迟/断连/429/半开
  • 退避与断路器验证

用 Toxiproxy 在 Provider 与客户端之间注入故障:延迟(toxics latency)、断连(disconnect)、LIMIT_DATA/429(模拟限流)、半开连接(half-open)。验证退避:注入延迟/429 后,确认客户端按指数退避重试而非立即重试;验证断路器:注入持续失败后,确认断路器打开(快速失败、不调用 Provider)、一段时间后半开(允许少量探针)、恢复后关闭。断言:故障期间请求快速失败、退避生效、恢复后正常。记录指标(重试次数、熔断状态、恢复时间)。

Chaos 注入让"故障路径"可复现。Toxiproxy 在代理层注入延迟/断连/限流/半开,验证退避与断路器行为。断言"故障下快速失败、退避、熔断、恢复"是容错工程的关键。

#

36. 模型、Prompt 或 Advisor 变更如何通过 Argo Rollouts/Flagger 灰度,并以质量与可靠性指标回滚

模型、Prompt 或 Advisor 变更如何通过 Argo Rollouts/Flagger 灰度,并以质量与可靠性指标回滚?

  • 灰度发布
  • 质量/可靠性指标
  • 自动回滚

用 Argo Rollouts/Flagger 做 Canary 发布:新版本(含模型配置、Prompt、Advisor 变更)先以少量流量灰度,通过配置、指标比对(成功率、P95 延迟、Token 成本、错误率、Schema 通过率)与金标准回归监控质量。当指标在阈值内则逐步放量,超出阈值自动回滚到稳定版本。关键是把"质量指标"(金标准通过率、Schema 通过率、安全分类)与"可靠性指标"(成功率、P95、错误率)纳入灰度分析,实现"指标驱动自动回滚"。模型/Prompt/Advisor 变更作为可版本化配置,随代码一起灰度。

Canary 是"小流量验证 + 指标分析 + 自动回滚"。质量与可靠性指标共同决定放量/回滚,避免"功能正常但质量退化"的隐蔽回归。指标驱动使灰度自动、可审计。

#

37. WireMock / MockLLM 模拟 Provider 响应时,如何精确控制流事件顺序、错误位置与延迟

WireMock / MockLLM 模拟 Provider 响应时,如何精确控制流事件顺序、错误位置与延迟?

  • Mock 精确控制
  • 流事件与错误位置
  • 延迟注入

用 WireMock 的 stub 配置精确控制:响应体(按序拼接流事件)、错误位置(在特定 chunk 后返回错误状态/错误事件)、延迟(fixedDelay 或 delayDistribution)、以及通过自定义 ResponseTransformer 动态生成流。MockLLM 可配置多轮响应序列、错误与延迟。验证客户端:流事件顺序是否正确解析、错误位置是否正确触发异常、延迟是否影响超时。这样能复现"半包、错位、中途错误、超时"等边界场景,做确定性测试。

Mock 的价值是"确定性复现边界"。通过配置响应体、错误位置、延迟,可精确测试流事件顺序、错误处理与超时。这比真实模型更可控,是契约测试与边界测试的基础。

#

38. Argo Rollouts / Flagger 在 AI 应用发布中应基于哪些指标(成功率、P95 延迟、Token 成本)

Argo Rollouts / Flagger 在 AI 应用发布中应基于哪些指标(成功率、P95 延迟、Token 成本)?

  • 灰度指标
  • 质量与成本
  • 分析维度

灰度分析应基于多维指标:成功率(请求成功率、流式完成率)、P95 延迟(TTFT、总延迟)、Token 成本(每请求 token 数、成本变化)、错误率(4xx/5xx、Provider 错误)、金标准回归通过率、Schema 通过率、安全分类。这些指标在 Canary 阶段与基线对比,超出阈值自动回滚。成本指标尤其重要(模型/Prompt 变更可能抬高 token 成本)。指标需低基数、可关联版本,用于灰度分析。

灰度指标覆盖"可靠性、性能、成本、质量"四维。AI 应用特有成本与质量指标(Token 成本、Schema 通过率)应纳入分析,避免只靠 QPS/成功率。多指标联动决定放量与回滚。

#

39. Java 应用的 Spring Boot Actuator 应暴露哪些 AI 健康指标(Provider 连通性、向量库状态、模型版本)

Java 应用的 Spring Boot Actuator 应暴露哪些 AI 健康指标(Provider 连通性、向量库状态、模型版本)?

  • Actuator 健康指标
  • Provider/向量库/模型
  • 可观测性

Actuator 应暴露:Provider 连通性(各 Provider 可达性、延迟、配额余量)、向量库状态(连接、索引可用、检索延迟)、模型版本(当前模型与版本、配置)、以及关键运行指标(QPS、延迟、Token 消耗、错误率、熔断状态)。通过自定义 HealthIndicator 实现 Provider/向量库/模型的健康检查,自定义 Metrics 暴露 token 与延迟。健康检查用于就绪探针与监控,指标用于容量与成本观测。注意健康检查要轻量(避免每次真实调用模型),区分"存活"与"就绪"。

AI 健康指标是多维的:Provider、向量库、模型、成本、性能。Actuator 通过自定义 HealthIndicator 与 Metrics 暴露,用于探针与监控。健康检查要轻量、分层,避免过度检测拖慢。

#

40. Spring AI 2.0 测试模块(spring-ai-test)

Spring AI 2.0 测试模块(spring-ai-test)提供了哪些测试支持?

  • spring-ai-test 功能
  • 测试工具
  • 使用方式

spring-ai-test 提供测试支持:Mock 模型(mock 的 ChatModel/EmbeddingModel,返回固定/序列化响应)、测试工具断言、为测试提供一致的模型返回,便于单元/集成测试。它让测试无需真实 Provider,可控制响应、验证调用与解析。常用于 Advisor 测试、RAG 测试、Prompt 模板测试。配合 Mockito 做依赖隔离与桩替换。它提供"确定性、可复用"的测试模型,是 Spring AI 应用测试的基础。

spring-ai-test 解决"测试需要模型"的难题,提供可控制响应的 Mock 模型,让测试确定、快速、无外部依赖。与 Mockito 结合可隔离 Advisor/RAG 依赖,是 Spring AI 测试的关键工具。

#

41. WireMock 与 MockLLM、本地模型容器、真实沙箱在测试金字塔中各承担什么角色,应如何取舍

WireMock 与 MockLLM、本地模型容器、真实沙箱在测试金字塔中各承担什么角色,应如何取舍?

  • 测试金字塔分层
  • 各层角色
  • 取舍

WireMock 承担契约/单元测试(模拟 HTTP 响应,精确控制,最快最稳);MockLLM 承担适配器/逻辑测试(模拟模型输出,控制内容);本地模型容器承担集成测试(真实协议/流式,接近真实);真实沙箱承担验收/冒烟(真实 Provider 行为)。取舍:Mock 层数量多、成本低、稳定;容器层数量少、成本高、接近真实;沙箱最少、最贵、最不稳定。金字塔原则:大部分测试用 Mock,少部分用容器/沙箱,平衡成本、稳定性与真实性。

测试金字塔是"分层覆盖 + 成本平衡"。Mock 覆盖大部分逻辑,容器覆盖协议,沙箱验证真实。角色分工明确,取舍基于成本与真实性需求,避免过度依赖真实/过多 Mock。

#

42. 灰度发布中 Prompt、Embedding、Advisor 变更应如何与代码版本绑定并支持秒级回滚

灰度发布中 Prompt、Embedding、Advisor 变更应如何与代码版本绑定并支持秒级回滚?

  • 版本绑定
  • Prompt/Embedding/Advisor 版本化
  • 秒级回滚

Prompt、Embedding、Advisor 应作为可版本化配置与代码版本绑定:配置中心或制品库中维护版本号,代码/配置引用固定版本;Embedding 模型/向量索引版本独立管理。灰度时按版本切换,回滚时通过配置中心秒级切回旧版本(配置开关/路由),无需重新发布代码。关键是"版本隔离 + 配置驱动 + 双版本并存":新旧 Prompt/Embedding/Advisor 版本同时存在,路由规则决定使用哪个,回滚即切换路由。Embedding 版本回滚需配合向量索引兼容(双写/影子)。

秒级回滚靠"配置驱动 + 版本并存"。版本与代码绑定保证可追溯,配置中心切换实现秒级回滚。Embedding 回滚需处理向量索引版本兼容,避免新旧向量混用。

#

43. Java 测试应如何使用 spring-ai-test 加 Mockito 做 Advisor 与 RAG 的依赖隔离与桩替换

Java 测试应如何使用 spring-ai-test 加 Mockito 做 Advisor 与 RAG 的依赖隔离与桩替换?

  • 依赖隔离
  • Mockito 桩替换
  • Advisor/RAG 测试

用 spring-ai-test 的 Mock 模型(ChatModel/EmbeddingModel)替换真实模型,用 Mockito 对 Advisor 依赖(如向量库、检索器、记忆存储)做桩替换,隔离外部依赖。测试 Advisor:注入真实 Advisor 与 Mock 模型,验证 Advisor 的上下文注入、顺序、短路与降级。测试 RAG:用 Mock 检索器返回固定结果,验证检索上下文注入与授权过滤。这样测试聚焦业务逻辑,不依赖真实 Provider/向量库,快速稳定。

测试隔离的核心是"替换外部依赖"。spring-ai-test 提供 Mock 模型,Mockito 桩替换检索/存储/记忆,让 Advisor 与 RAG 逻辑可独立测试。聚焦逻辑、快速稳定是高价值测试的关键。

#

44. Spring Boot Actuator 健康检查与 Provider 真实连通性检查应如何分层,以避免误报与漏报

Spring Boot Actuator 健康检查与 Provider 真实连通性检查应如何分层,以避免误报与漏报?

  • 健康检查分层
  • 误报与漏报
  • 就绪/存活

健康检查应分层:存活探针(进程活着、基础组件可用)与就绪探针(依赖就绪,如 Provider 连通、向量库可用)。避免误报:就绪探针用真实但轻量的连通性检查(如 Provider 的轻量 ping/配额查询),而非每次真实模型调用(成本高、波动大);避免漏报:存活探针覆盖基础,就绪探针覆盖关键依赖。分层做法:基础健康(Actuator 默认)负责进程/JVM;自定义 HealthIndicator 负责 Provider/向量库,用轻量检查 + 缓存 + 超时,避免误报(瞬时波动)与漏报(不检查)。健康检查结果用于 K8s 探针与监控。

分层是"存活 vs 就绪 + 轻量 vs 真实"。存活探针防误杀(进程活着自愈),就绪探针防流量到不可用实例。用轻量连通性检查 + 缓存避免误报(瞬时波动)与漏报(不检查)。这是健康检查设计的关键。