三、模型调用与工具集成

项目仓库:https://github.com/vasc-language/ai-code-mother

项目预览:https://www.joinoai.cloud

13. MyBatis Flex 和 MyBatis Plus 的区别?为什么在项目中选择它?

核心区别
  • 定位与风格:MyBatis Plus偏向“增强型ORM+脚手架”,提供ServiceImpl、自动填充、代码生成器、通用CRUD;MyBatis Flex更偏“下一代MyBatis增强DSL”,强调轻量、表达力强、对复杂查询(多表、子查询、动态列)支持更好。
  • 查询DSL能力:
    • Flex:QueryWrapper + TableDef 强类型列引用、链式拼装、多表 JOIN/子查询原生支持,复杂条件表达简洁;
    • Plus:QueryWrapper 足以覆盖大多数单表/简单多表场景,复杂 JOIN 往往回落至 XML 或自定义插件。
  • 运行期开销:
    • Flex:更少的运行期拦截器与元对象处理,分页等以工具/方法形式提供,整体更“轻”;
    • Plus:内置较多特性(自动填充、逻辑删除、分页拦截器等),开箱即用但运行期更“重”。
  • 代码生成与生态:两者均有代码生成器;Flex 在表达复杂 SQL 时模板更简洁,Plus 在脚手架与社区资料上更丰富。
项目选择与理由
  • 代码与依赖事实:本项目已引入 mybatis-flex-spring-boot3-startermybatis-flex-codegen,服务层大量使用 com.mybatisflex.*(见pom.xmlservice/implmapper)。
  • 业务诉求:
    • 需要在生成类业务中做灵活查询与分页,偏好简洁的强表达力 DSL;
    • 保持运行期开销小、可控,方便与 LangChain4j、工作流并发调度协同;
    • 复杂查询可直写 DSL/表定义而非大量 XML;
  • 结论:选 MyBatis Flex,获得轻量、强 DSL、多表/子查询友好的特性,同时保留与 MyBatis 原生 XML 的互通弹性。

14. 什么是策略模式?你如何使用策略模式处理代码解析逻辑?

定义
  • 策略模式通过在运行时选择不同“算法/策略”以完成同一类任务,避免在调用处充斥 if/else 或 switch,提升可扩展性与可测试性。
在本项目中的应用(代码解析)
  • 背景:大模型输出既可能是 Markdown 代码块、也可能是分隔标记的多文件内容,或是工具流已将内容落盘;不同生成类型(HTML / MULTI_FILE / VUE_PROJECT)解析路径各异。
  • 方案:定义统一策略接口与上下文执行器,根据生成类型或输出特征动态选择解析策略。

关键接口与约定(说明性签名):

interface CodeParseStrategy {
    CodeParseResult parse(String rawStreamOrText);
}

final class CodeParseResult {
    List<CodeFile> files;  // 解析出的文件清单
    String plainText;      // 若需要的纯文本
}

// 典型策略
class MarkdownFenceCodeStrategy implements CodeParseStrategy {}
class MultiFileTaggedStrategy implements CodeParseStrategy {}
class ToolAwareNoopStrategy implements CodeParseStrategy {} // 工具已落盘,仅抽取摘要

// 选择器
class CodeParserExecutor {
    CodeParseStrategy choose(CodeGenTypeEnum type, String content);
    CodeParseResult execute(CodeGenTypeEnum type, String content);
}

选择规则示例:

  • VUE_PROJECT 且出现工具调用标记 → ToolAwareNoopStrategy(以工具流为主、解析为辅)
  • 内容包含 fence codeMarkdownFenceCodeStrategy
  • 出现自定义文件分隔标记/JSON 计划 → MultiFileTaggedStrategy

15. 什么是模板方法模式?你如何使用模板方法模式处理文件保存逻辑?

定义
  • 模板方法在抽象基类中定义稳定流程骨架,将可变步骤留给子类实现(钩子/抽象方法),保证流程一致、实现差异可扩展。
在本项目中的应用(文件保存)
  • 背景:HTML 单文件、传统多文件、Vue 工程三类保存步骤高度相似:校验 → 解析根目录 → 写盘(幂等/覆盖策略)→ 生成后处理(如依赖、构建)。

抽象流程(说明性签名):

abstract class AbstractCodeFileSaver {
    public final SaveResult save(Long appId, List<CodeFile> files) {
        preCheck(appId, files);
        Path root = resolveRoot(appId);
        writeFiles(root, files);     // 统一处理:已存在且内容一致则跳过;不同则覆盖/新建
        postProcess(root);           // 如:生成 README、触发构建、生成预览链接
        return summary(root, files); // 统一汇总
    }

    protected abstract void postProcess(Path root);
    protected void preCheck(Long appId, List<CodeFile> files) {}
    protected Path resolveRoot(Long appId) { /* 依据 appId 隔离 */ }
    protected void writeFiles(Path root, List<CodeFile> files) { /* 幂等写入 */ }
}

class HtmlFileSaver extends AbstractCodeFileSaver { /* 精简后处理 */ }
class MultiFileProjectSaver extends AbstractCodeFileSaver { /* 校验目录结构 */ }
class VueProjectSaver extends AbstractCodeFileSaver { /* 依赖/构建钩子 */ }

错误处理策略:

  • 写入采用“临时目录 → 原子替换”或“逐文件幂等”避免中途失败造成不一致;
  • 捕获 IO 异常后回滚或标记失败,向前端流式回报失败详情;
  • 对非法路径、越权写入做白名单校验。

16. LangChain4j 在项目中有什么作用?你是如何将 AI 大模型能力集成到业务代码中的?

作用
  • 统一接入多家大模型(OpenAI/通义/百川等),提供对话、工具调用、流式回调、记忆、结构化输出等能力;
  • 与 Spring 生态良好集成,便于在服务中以接口方式注入与调用。
集成方式
  • 模型与流式:ChatLanguageModel / StreamingResponseHandler 对接流式生成,将 token 与工具事件映射为 SSE 事件;
  • 工具:通过 @Tool 描述工具签名,LangChain4j 负责生成/校验 ToolExecutionRequest
  • 记忆:集成 Redis 作为 ChatMemoryStore,用于短期会话记忆;
  • 服务封装:AiCodeGeneratorService 将提示词工程、记忆、工具集合与模型实例组装为可复用服务;
  • 自定义流构建:OpenAiStreamingResponseBuilder 用于对 OpenAI 风格增量消息进行工具信息组帧,完善事件粒度。

17. 如何实现将 AI 大模型的输出稳定地转换为结构化对象?

关键策略
  • 强约束提示词:要求输出为 JSON/特定标签,并提供最小可行示例;
  • 模式/Schema:基于目标 Java Bean 生成 JSON Schema 或约束字段(必填、枚举、范围);
  • 解析与修复:先做快速 JSON 解析,失败则尝试“轻量修复”(补全括号、转义),仍失败则触发一次“Re-Ask”让模型纠偏;
  • 校验与回退:用 Bean Validation(Jakarta Validation)做业务校验,不通过则降级为宽松解析或默认值策略;
  • 幂等与可观测:落库前做去重/版本化,记录解析失败率、重试次数与样本。

说明性流程:

raw → detect fenced json → parse(JSON) → validate(bean) →
    ok: return
    fail: tryPatch → reParse →
        ok: return
        fail: reAsk(model, schemaHint) → parse → validate →
            ok: return
            fail: fallback(defaults/log)

LangChain4j 配合点:

  • 使用结构化输出解析器/编解码器(基于 POJO 映射)与 AiServices 将回复直接映射为接口返回;
  • StreamingResponseHandler/普通响应回调中统一做解析与校验,减少散落逻辑。

18. 什么是 AI 智能路由?你如何利用 AI 根据用户需求自动选择最合适的代码生成方案?

定义
  • 智能路由指根据用户意图、约束与环境,自动选择最合适的模型/生成类型/工具与执行路径的能力。
本项目实现
  • 路由服务:AiCodeGenTypeRoutingService#routeCodeGenType(String prompt) 返回 CodeGenTypeEnum 与置信度;
  • 决策信号:
    • 语义判断:小型分类模型或主模型 few-shot 分类(网页/多页工程/Vue 工程等);
    • 约束判断:是否允许工具、是否需要构建步骤、是否需要多文件;
    • 环境判断:预算、时延、历史成功率/失败率(监控指标)。
  • 回退策略:
    • 低置信度时降级为规则路由(例如包含package.json/vite等关键词倾向于 VUE_PROJECT);
    • 生成失败自动换路由重试一次(如从 MULTI_FILEHTML)。

19. 什么是 LangChain4j 的护航机制?你是如何利用输入拦截来防止恶意 Prompt 输入和注入攻击的?

护航机制理解
  • 护航(Guardrails)指在提示词输入/模型输出/工具执行三个关键环节设置策略与拦截,确保安全、可控与合规。
输入侧拦截方案
  • 规则过滤:对已知注入词(如“忽略所有指令/系统提示”“执行系统命令”“删除磁盘文件”等)做拒绝或降权处理;
  • 角色隔离:将系统提示与用户输入物理分离,严禁用户覆盖系统消息;
  • 模型审核:可选接入安全审核小模型/服务,对高风险输入打回并给出安全改写建议;
  • 速率与配额:结合 Redisson 限流,防止暴力探测与滥用;
  • 审计记录:对被拦截输入入库,便于后续规则迭代。

工程落点

  • AiCodeGeneratorFacade 的入口层引入 PromptInputFilter(拦截器/切面),统一做校验与打标;
  • 对通过校验的输入加“最小必要信息”原则重写,避免把路径、凭据等敏感信息直接暴露给模型;
  • 前端也做基础校验,防止明显恶意 payload 进入后端。

20. 当 AI 大模型调用工具时,可能会陷入无限循环,你是如何避免这个问题的?

多层防护
  • 提示词约束:在系统提示中明确“工具调用次数上限(如 ≤ 20)”“完成后必须调用【退出工具】”,并列出常见循环陷阱;
  • 工具幂等:FileWriteTool 等具备“内容相同跳过写入”的幂等策略,减少“写—读—再写”死循环的收益;
  • 运行期阈值:在服务端为每次会话维护 toolInvocationCount,超阈值立即终止并返回提示;
  • 重复行为检测:对同一路径的重复写入/修改计数,超过阈值发出警告或终止;
  • 工作流有穷:LangGraph4j 的图式编排不出现无出口环路,必要处添加超时与最大步数;
  • 观测与告警:对异常长会话、异常工具密度设监控,触发报警并沉淀样本优化提示词。

21. AI 零代码应用生成项目中,你如何实现工具调用信息的流式输出?

架构与流程
  • 控制器:WorkflowSseController 暴露 SSE 接口,将模型流、工具事件映射为前端可消费的消息;
  • 流构建:OpenAiStreamingResponseBuilder/StreamingResponseHandler 在收到增量 token、ToolExecutionRequestToolExecutionResult 时组装事件;
  • 前端消费:EventSource 订阅并根据 type 渲染(如 AI_RESPONSETOOL_REQUESTTOOL_EXECUTED)。

事件示例(语义):

{ "type": "AI_RESPONSE",   "content": "正在创建项目骨架..." }
{ "type": "TOOL_REQUEST",  "tool": "write_file", "args": { "path": "src/App.vue" } }
{ "type": "TOOL_EXECUTED", "result": "已写入 128 行" }
细节与保证
  • 有序性:对同一会话内事件递增编号,前端按序展示;
  • 可靠性:SSE 心跳与断线重连;
  • 安全性:工具参数脱敏(如绝对路径、凭据)。

📞 联系我们

如果您有任何问题或建议,请随时联系我们:

  • 提交 Issue
  • 发送邮件至: zrt3ljnygz@163.com
  • 微信联系: Join2049
Logo

更多推荐