☰
SpringBoot整合讯飞星火大模型:构建自然语言转SQL的数据分析助手
2026/10/3 3:13:15 网站建设 项目流程

最近在搞内部数据平台的一个小需求:运营同学天天找开发写 SQL 拉数,重复又机械。我寻思正好把大模型接进来,做一个人人都能查数的智能数据分析助手。项目代号就叫“星火助手”,技术栈是讯飞星火大模型 + SpringBoot,核心链路一句话就能说清:自然语言问题 -> 大模型生成 SQL -> 数据库执行 -> 结果再交给大模型总结成人话。

这个标题听起来挺唬人,实际拆开也就三件事:怎么把 SpringBoot 和大模型 API 接起来,怎么让大模型产出可信的 SQL,怎么把查询结果安全地跑出来。下面就从项目设计思路、环境准备、核心代码、安全校验到常见坑位,一条龙讲清楚。适合正在做内部数据查询、报表平台,或者想在自己系统里塞一个“问数机器人”的后端同学参考。

1. 项目概览与整体设计思路

1.1 这个助手到底能做什么

先给个直观画面。以前运营想查“上个月华东区销量前 10 的商品”,流程是提工单、找开发、写 SQL、跑数据、再回邮件,运气好半小时,运气不好半天。接上星火助手之后,运营直接在对话框里把这句话打出来,后端把这句话交给星火大模型,模型基于我们配置的表结构返回一版 SELECT 语句,程序校验通过后去 MySQL 执行,再把查询结果交给模型做二次总结,最后返回给前端:

“上个月华东区销量前 10 的商品分别是:A 商品 1250 件、B 商品 986 件……整体环比增长 12.3%,建议关注榜单头部商品的库存情况。”

整个过程不到 10 秒。这就是这个项目的核心能力:自然语言转 SQL(NL2SQL)+ 查询结果自动解读。它可以嵌入企业微信、飞书机器人,也可以做成一个独立的前端页面,算是用大模型做内部提效最典型的落地场景之一。

1.2 架构设计和技术选型背后的考量

先看整体链路:

  • 用户请求打到 SpringBoot 接口
  • 接口组装 system prompt(包含表结构说明)和用户问题,调用讯飞星火 API
  • 模型返回 JSON 格式的 SQL,后端解析出来
  • SQL 校验器做安全校验(只允许 SELECT 类查询、禁止多条语句)
  • 通过 JdbcTemplate 执行查询,结果集转成 List<Map>
  • 带着 SQL 和查询结果再次调用星火 API,让模型生成业务结论
  • 返回给前端展示

技术选型上,我纠结过几个点:

第一,大模型 API 为什么选星火而不是别的?核心原因是国内访问稳定、接入门槛低,而且它提供了 OpenAI 兼容的 HTTP 接口,不需要去啃 WebSocket 那套复杂的鉴权流程。申请之后拿 APIKey 就能调,对 SpringBoot 项目非常友好。如果你之前用过 OpenAI 的 message 结构,上手星火基本零成本。

第二,后端框架为什么用 SpringBoot?不用多解释,生态成熟。数据源、连接池、事务、定时任务、监控都有现成方案,团队招人也好招。做数据分析助手这类中后台服务,SpringBoot 是最稳妥的选择,没有必要为了“新”去冒险。

第三,为什么不要“前端直接把问题发给大模型、拿到 SQL 后由前端直连数据库”?这个一定要控制住。前端直连数据库等于把连接串暴露给浏览器,等于裸奔。而且大模型生成的 SQL 可能有幻觉,必须有一层后端校验和拦截才能执行。数据库链接、权限、审计这些都应该留在服务端。

这里用一个类比帮助你理解:大模型就像一个“懂数据库但偶尔犯迷糊的实习生”。你给他一份清楚的表结构说明,他能帮你写 SQL,但你绝不能直接给他一个生产库账号让他随便跑。你得在旁边加一个“安全员”角色,检查他写的每一句话,确认没问题了才放行。后面代码里那个 SqlValidator,就是这个安全员。

2. 环境准备与项目初始化

2.1 申请星火API密钥与开通服务

这一步没什么技术含量,但很多人卡在找入口上。我走了一遍完整流程:

  1. 打开讯飞开放平台控制台,用手机号注册登录。
  2. 在“创建新应用”里随便填个应用名称,比如“数据分析助手”,类型选 Web 后端,创建完成。
  3. 进入应用的“星火认知大模型”服务页面,开通服务。新用户一般有免费额度,个人学习完全够用。
  4. 在服务详情里找到 APIKey、APISecret、APPID 三个值。
  5. 确认接口调用地址。新版接口的 base 路径是https://spark-api-open.xf-yun.com/v1,和 OpenAI 兼容的调用方式在同一个风格线上。

这里强调三点:

  • APIKey 和 APISecret 等同于账号密码,不要写死在代码里,更不要提交到 Git。建议用环境变量注入,或者接入 Nacos、Apollo 这类配置中心。
  • 模型版本要选对。免费额度对应的模型和个人申请擅长的模型可能不一致,调用时报 model not found 或鉴权失败,八成是这里没对上。可以参考下面这张表:
模型标识适用场景说明
lite轻量问答、简单提取便宜,速度快,适合测试
generalv3.0通用对话、NL2SQL性价比高,大多数业务够了
generalv3.5复杂推理、长文本准确率更高,价格也高一些
4.0Ultra复杂任务、高精度最新模型,成本最高,生产环境慎用
  • 我自己的项目中,nl2sql 这种偏结构化的任务用generalv3.5效果最好,虽然贵一点,但 SQL 出错率低,能省掉大把排查时间;总结结果这种轻任务用generalv3.0就够。

2.2 搭建SpringBoot工程与基础依赖

工程可以从 IDEA 的 Spring Initializr 或 start.spring.io 生成,然后手动加依赖。用 SpringBoot 2.7.18 作为基线版本,兼容 JDK 8,也方便团队老项目统一。pom.xml里除了常规的 web 和 jdbc 之外,我加了 OkHttp 作为 HTTP 客户端,Hutool 处理部分工具方法,MySQL 驱动用 8.0 版本。

<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>2.7.18</version> <relativePath/> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-jdbc</artifactId> </dependency> <dependency> <groupId>mysql</groupId> <artifactId>mysql-connector-java</artifactId> <version>8.0.33</version> </dependency> <dependency> <groupId>com.squareup.okhttp3</groupId> <artifactId>okhttp</artifactId> <version>4.12.0</version> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <optional>true</optional> </dependency> </dependencies>

2.3 关于SpringBoot版本与JDK版本的忠告

这里必须单独说一节,因为我在部署阶段被版本问题坑得不轻。网上很多教程默认大家用 JDK 8 + SpringBoot 2.x,但现在新创建的项目一开 IDEA 就是 JDK 21,Spring Initializr 默认拉到 SpringBoot 3.3/3.4。版本一下子跳上去,两个问题立刻出现:

第一,包名变了。SpringBoot 3.x 用的jakarta.*,2.x 用的是javax.*。如果你参照 2.x 的代码写了import javax.annotation.Resource;,在 3.x 项目里直接编译不过,得改成jakarta.annotation.Resource。

第二,第三方依赖兼容性。SpringBoot 3.x 基于 Spring Framework 6,要求 JDK 17 以上,一些老的 MyBatis、ShardingSphere 版本没跟上,运行期会报NoSuchMethodError或ClassNotFoundException。

所以我的建议非常直接:团队如果都是 JDK 8 背景,项目用 2.7.18 最稳;如果是新团队、新系统,直接用 JDK 17 + SpringBoot 3.2+,别上 JDK 21,部分第三方工具在 21 上还有兼容性摩擦。版本匹配参考这个表:

使用场景JDK 版本SpringBoot 版本
老项目维护、JDK8 环境82.7.x
新内部系统、云原生173.1.x / 3.2.x
追求最新特性213.3.x / 3.4.x

配置文件我放在application.yml,星火相关的配置统一用spark前缀,方便后续用@ConfigurationProperties装配。数据库账号单独建立一个只读账号,密码从环境变量注入。

spring: datasource: url: jdbc:mysql://localhost:3306/analytics?useUnicode=true&characterEncoding=utf8&useSSL=false username: readonly_user password: ${DB_PASSWORD} spark: api-key: ${SPARK_API_KEY} url: https://spark-api-open.xf-yun.com/v1/chat/completions model: generalv3.5 max-tokens: 2048 temperature: 0.3

配置类的写法也很固定:

@Data @Component @ConfigurationProperties(prefix = "spark") public class SparkProperties { private String apiKey; private String url; private String model; private Integer maxTokens; private Double temperature; }

顺带说一句,@ConfigurationProperties是 SpringBoot 自动配置机制里很核心的一环,它会把配置文件的属性绑定到 bean 上。原理是ConfigurationPropertiesBindingPostProcessor在 bean 初始化前解析注解,再通过 Binder 把属性值写入对象字段。平时不用深究,但面试常问,知道这个流程就行。

3. 核心代码实现:对接星火 API

3.1 从 HTTP 客户端开始

老一代的星火接口是 WebSocket 协议,需要先用 HMAC-SHA256 生成带签名的 URL,再建立长连接接收流式数据,代码非常绕。后来平台推出了 OpenAI 兼容的 HTTP 接口,鉴权只需要在请求头加Authorization: Bearer {APIKey},消息体也是标准的messages结构,对后端同学友好太多。

我这里就用这个 HTTP 接口。HTTP 客户端选型上,RestTemplate 虽然 Spring 自带,但 OkHttp 在连接复用、超时控制、拦截器扩展上都更顺手,所以我选用 OkHttp。先把三个基础的 DTO 定义出来,代码很简单,但代表请求与响应结构,后续所有业务都建立在这几个类上:

@Data public class ChatMessage { private String role; // system / user / assistant private String content; } @Data public class ChatRequest { private String model; private Double temperature; private Integer max_tokens; private Boolean stream; private List<ChatMessage> messages; } @Data public class ChatResponse { private String id; private Integer created; private String model; private List<Choice> choices; @Data public static class Choice { private Integer index; private Message message; } @Data public static class Message { private String role; private String content; } }

3.2 请求消息体与关键参数

调用星火 API 时,消息体有几个参数直接影响输出质量,值得专门说明:

  • temperature:控制随机性,NL2SQL 这种确定性任务我设 0.1~0.3,太高会让模型“发挥”出各种奇怪的 SQL;文本总结可以提到 0.5 左右。
  • max_tokens:限制生成最大长度,SQL 生成任务 1024 足够,总结任务设 2048。
  • stream:是否流式返回。如果只是后端接口内部调用,直接设 false 拿完整结果最省事;如果要给前端实时展示打字机效果,再开流式。
  • messages:与大模型对话的消息列表,遵循 OpenAI 的格式。第一轮通常是 system,定义大模型的角色和约束;后续是 user 和 assistant 交替的上下文。

封装好调用方法,核心逻辑集中在SparkApiClient.chat()里,负责拼装请求、发送、解析响应:

@Service @RequiredArgsConstructor public class SparkApiClient { private final SparkProperties properties; private final ObjectMapper objectMapper; private OkHttpClient buildClient() { return new OkHttpClient.Builder() .connectTimeout(10, TimeUnit.SECONDS) .readTimeout(60, TimeUnit.SECONDS) .build(); } public String chat(List<ChatMessage> messages) { ChatRequest request = new ChatRequest(); request.setModel(properties.getModel()); request.setTemperature(properties.getTemperature()); request.setMax_tokens(properties.getMaxTokens()); request.setStream(false); request.setMessages(messages); String json = objectMapper.writeValueAsString(request); RequestBody requestBody = RequestBody.create( MediaType.parse("application/json; charset=utf-8"), json); Request httpRequest = new Request.Builder() .url(properties.getUrl()) .header("Authorization", "Bearer " + properties.getApiKey()) .post(requestBody) .build(); try (Response response = buildClient().newCall(httpRequest).execute()) { if (!response.isSuccessful()) { throw new RuntimeException("星火API调用失败: HTTP " + response.code() + ", body=" + response.body().string()); } String responseBody = response.body().string(); ChatResponse chatResponse = objectMapper.readValue(responseBody, ChatResponse.class); if (chatResponse.getChoices() == null || chatResponse.getChoices().isEmpty()) { throw new RuntimeException("星火API返回异常: " + responseBody); } return chatResponse.getChoices().get(0).getMessage().getContent(); } } }

注意上面的Response是 OkHttp 的okhttp3.Response,别和javax.servlet.http.HttpServletResponse混了,不然编译报错半天找不到原因。

3.3 流式输出与SSE方案

如果你的业务需要“打字机”效果,那就得用流式。HTTP 接口开启stream=true时,返回的是 SSE 格式的事件流,每一行以data:开头。SpringBoot 里最方便的做法是用SseEmitter配合 OkHttp 的异步回调,把模型吐出来的增量文本直接推给浏览器。

@GetMapping(value = "/chat-stream", produces = MediaType.TEXT_EVENT_STREAM_VALUE) public SseEmitter chatStream(@RequestParam String question) { SseEmitter emitter = new SseEmitter(0L); // 不自动超时 // 异步线程里请求星火API,拿到增量内容后 emitter.send(),结束 emitter.complete() return emitter; }

流式实现要处理的东西不少:断线重连、Token 计数、上下文保留、并发 SseEmitter 的数量控制。我个人的建议是:第一版先用非流式把链路跑通,核心逻辑稳定后再考虑用户体验层面的流式输出。毕竟一个数据分析工具,用户最关心的是答案准不准,而不是字是不是一个一个蹦出来的。

4. 数据分析助手的业务逻辑实现

4.1 提示词工程:让大模型生成靠谱的 SQL

对接完 API,真正的重头戏才开始。大模型能不能生成正确的 SQL,80% 取决于你给的 system prompt 写得是否清晰。我的做法是维护一份“表结构说明”,放进 system prompt 里,这份说明要包含字段名、字段类型、字段含义和一个示例。

以一张销售明细表为例,我实际使用的 system prompt 模板如下:

你是一个数据分析助手。现在需要根据用户的业务问题,生成 MySQL 查询语句。 数据库表结构如下: 表名:sales_detail 字段: - id BIGINT 主键 - order_no VARCHAR 订单编号 - region VARCHAR 区域,如华东、华南、华北 - product_name VARCHAR 商品名称 - category VARCHAR 商品类目 - amount DECIMAL(10,2) 销售金额 - order_time DATETIME 下单时间 约束: 1. 只能生成 SELECT 开头的查询语句,禁止 DELETE、UPDATE、DROP、INSERT。 2. 只输出 JSON 格式:{"sql": "完整的SQL语句", "reason": "生成依据"} 3. 如果问题含义不明确,输出:{"sql": null, "reason": "具体不确定点"} 4. 默认给查询结果加 LIMIT 100。 5. 当前日期可以认为是 2025-01-15,时间筛选尽量结合上下问判断。

为什么要把表结构写得这么细?因为大模型并不知道你的业务库长什么样。你不告诉它region存的是“华东”而不是“east_china”,它就可能写一个WHERE region = 'east_china',查出来结果为空还找不到原因。给足字段注释,就是给模型一副“视力正常”的眼睛,这是整个项目里性价比最高的一项投入。

另外有个实用的 trick:把用户问题和表名、字段名相关的历史正确 SQL 整理成 few-shot 示例,放到 system prompt 末尾。比如“用户问‘华东销量’,正确 SQL 是 SELECT SUM(amount) FROM sales_detail WHERE region='华东'”。模型看到几个样本之后,生成质量会明显提升。

4.2 安全执行SQL与查询结果处理

大模型生成的 SQL 不能盲跑,这是安全底线。我在执行前加了一道校验器,核心逻辑有三层:

第一层,语句白名单。只允许SELECT、SHOW、DESC、WITH开头的语句,其他一律拦截。

第二层,多条语句拦截。按分号切分,如果切分后的片段多于一段且不全是空串,直接拒绝,防止SELECT ...; DROP TABLE ...这类拼接攻击。

第三层,关键词黑名单。DELETE、UPDATE、DROP、ALTER、TRUNCATE、INSERT出现就拒绝。

public class SqlValidator { private static final List<String> DANGEROUS_KEYWORDS = Arrays.asList("delete", "update", "drop", "alter", "truncate", "insert", "replace"); public void validate(String sql) { String trimmed = sql.trim(); String lower = trimmed.toLowerCase(); String head = lower.split("\\s+")[0]; if (!head.startsWith("select") && !head.startsWith("with") && !head.startsWith("show") && !head.startsWith("desc")) { throw new IllegalArgumentException("仅允许 SELECT 查询语句"); } long semicolonCount = trimmed.chars().filter(ch -> ch == ';').count(); if (semicolonCount > 1) { throw new IllegalArgumentException("检测到多条SQL语句,已拦截"); } for (String keyword : DANGEROUS_KEYWORDS) { if (lower.contains(keyword)) { throw new IllegalArgumentException("检测到危险关键字: " + keyword); } } } }

这套校验在常规场景够用,但如果业务安全性要求高,建议用 Druid 的 SQL 解析器做 AST 级校验,它能把 SQL 解析成抽象语法树,从语法层面判断是不是一条纯查询语句,比字符串黑名单健壮得多。另外还有一个非常关键的提醒:程序里配置的数据源账号必须是只读账号,最好连SELECT INTO OUTFILE这类权限也去掉。即使前面所有校验都被绕过,数据库层面上也不会造成破坏。

执行 SQL 时,我用 Spring 自带的JdbcTemplate,查询结果直接转成List<Map<String, Object>>,这种结构后面给大模型做总结也方便。

@Service @RequiredArgsConstructor public class DataAnalysisService { private static final String TABLE_SCHEMA_PROMPT = "……上面那段表结构描述……"; private final SparkApiClient sparkApiClient; private final JdbcTemplate jdbcTemplate; private final SqlValidator sqlValidator; public AnalysisResult analyze(String question) { // 1. 生成 SQL String sql = generateSql(question); if (sql == null) { return AnalysisResult.fail("问题描述不够明确,请补充时间或区域条件"); } // 2. 校验并执行 sqlValidator.validate(sql); List<Map<String, Object>> rows = jdbcTemplate.queryForList(sql); // 3. 二次调用模型生成结论 String summary = summarize(sql, rows); return AnalysisResult.success(sql, rows, summary); } private String generateSql(String question) { List<ChatMessage> messages = Arrays.asList( new ChatMessage("system", TABLE_SCHEMA_PROMPT), new ChatMessage("user", question) ); String content = sparkApiClient.chat(messages); // 解析 content 里的 JSON,拿 sql 字段 JsonNode node = objectMapper.readTree(content); return node.has("sql") ? node.get("sql").asText() : null; } }

4.3 把结果交给模型二次加工成结论

很多人做到“生成 SQL、执行出结果”就停了,返回一坨原始表格给前端。这样用户体验并不好,用户是来问“怎么样”的,不是来看几十行数字的。所以我对模型做了一个二次调用,第一次生成 SQL,第二次生成解读。

第二次调用的 system prompt 大概是这个意思:

请根据下面的 SQL 和查询结果,用中文生成简洁的业务分析结论。 要求: 1. 提取关键数字,如总额、TOP3、环比变化。 2. 说明数据反映的趋势或异常。 3. 不要编造数据,只基于给定结果。 4. 控制在150字以内。

这一步不复杂,但带来的体验提升非常大。用户看到的不再是一堆行记录,而是一段人话“上个月华东区销量 1250 件,环比增长 12.3%,其中 A 商品贡献 32%”。而且因为结论是基于真实查询结果生成的,幻觉的概率比让大模型直接回答业务问题低得多。

5. 常见问题与避坑实录

5.1 鉴权失败与参数踩坑

这一块基本是所有接星火 API 的人都绕不过去的。我整理了几个高频错误和解决办法,直接贴表:

现象可能原因解决办法
HTTP 401APIKey 错误,或 Authorization 头格式不对检查授权头是否为Bearer+ 密钥,注意大小写和空格
报 model not found模型标识写错,或该模型未开通在控制台确认开通的模型,把model参数改成对应标识
返回 403 code=10013IP 白名单限制控制台配置服务器出口 IP,或者临时关闭白名单测试
输出内容为空 / 被截断max_tokens 太小、内容触发安全过滤增大 max_tokens,或者改 prompt 说法
调用报超时网络波动或生成时间过长调大 readTimeout,关闭流式改同步,并做重试

我在项目联调阶段遇到最崩溃的一次是 401 持续出现,检查了半小时,最后发现配置文件里 APIKey 多了一个看不见的换行符。用环境变量注入密钥时,务必检查一下是不是有隐形字符。

5.2 SpringBoot版本太高引发的依赖冲突

这部分是我基于实际踩坑整理的,也是搜索热词里最多人求助的点。比如“现在的版本是21,想回退到1.8”这个问题,如果你用的是 IDEA,可以在 Project Structure 里改 Project SDK 为 1.8,同时把 pom 里的java.version属性改成 1.8,并且确保spring-boot-starter-parent版本是 2.7.x。如果项目已经用了 SpringBoot 3.x 的代码风格,直接回退会有一堆javax.*到jakarta.*的报错,不是改个版本号就能解决。

另外,SpringBoot 3.x 里 MyBatis 相关的 starter 要使用mybatis-spring-boot-starter3.x 版本,老版本 2.x 在 Spring 6 下会报factoryBeanObjectType之类的初始化错误。OkHttp 本身不依赖 Spring,但如果项目里同时有老版本 okhttp 和新版本 okhttp,类冲突会让编译器“找到了两个同名的类”,运行期随机行为异常。统一用dependencyManagement控制版本是最省心的。

5.3 调用超时、并发控制与成本控制

接入大模型 API 和调用普通接口不一样,响应时间通常在 3~10 秒,服务端不能按普通的 1 秒超时去设置。我的 OkHttp 里连接超时 10 秒、读超时 60 秒,接口层再配合异步化处理,避免长连接占满 Tomcat 线程。

成本控制也是生产环境必须考虑的问题。每次 NL2SQL 至少消耗 1~2 千 token,二次总结再消耗几百 token,并发高的时候一个月费用相当可观。我做了三件事来控制成本:

  • 对用户问题做简单的规则预筛,如果只是查“订单总数”这类固定模板,直接走写死的 SQL,不调用大模型。
  • 同一个用户同一个问题,在项目里加了 Redis 缓存,10 分钟内复用结果,键名就是question + model。
  • 并发控制用 Semaphore 限制同时调用星火 API 的最大请求数,默认 5 个,超出就排队或提示稍后重试,防止突发的流量把调用额度打爆。

6. 效果演示与后续扩展

6.1 实际运行效果演示

接口我只暴露了一个 POST/api/analysis/query,请求体就是一个question字段。下面放两条真实测试记录:

用户问题生成的 SQL返回结论
“今年1月销售总额是多少”SELECT SUM(amount) FROM sales_detail WHERE order_time BETWEEN '2025-01-01' AND '2025-01-31'2025年1月销售总额为 358.6 万元,环比上月增长 6.2%
“销量前十的商品是哪些”SELECT product_name, SUM(amount) AS total FROM sales_detail GROUP BY product_name ORDER BY total DESC LIMIT 10销量TOP3商品为A、B、C,A贡献份额达28%,头部商品集中度较高

从维护者视角看,最让我惊喜的不是 SQL 多完美,而是当用户问题模糊时,模型会按照 prompt 里的要求返回reason,提示缺少时间范围。这比闷头查出一个空结果再让用户猜原因好太多。

6.2 后续可以往哪些方向扩展

第一版跑通之后,能做的优化方向其实非常多:

  • 把表结构映射做成可视化配置,运营自己维护字段含义,不用改代码。
  • 引入 RAG 思路,把几十张表的 schema 向量化,先检索出跟问题相关的表,再动态注入 prompt,而不是把所有表结构一股脑塞进去。表一多,prompt 会超过上下文长度。
  • 前端用 ECharts 把查询结果直接渲染成柱状图、折线图,结论文案配图表一起展示,业务价值更大。
  • 在 SQL 执行层增加预计算缓存,常见报表查询直接走结果缓存,大模型只在缓存失效时才介入。

我在实际项目中最大的体会是,接入大模型 API 只是整个项目最轻松的一步,真正花时间的全在“让模型更懂你的业务”和“让结果更可信”这两件事上。表结构维护得越细,few-shot 示例准备得越充分,模型的表现就越好。而安全校验、成本控制、结果缓存这些工程化能力,才是项目能不能真正上线的关键。

最后再分享一个小技巧:不要在项目一开始就追求所有表都能查。先挑三张核心业务表,手动造 20 组标准问答对测试,效果满意后再逐步扩表。这样既能让老业务尽快用起来,也方便你观察哪些表结构描述方式容易让模型跑偏,迭代 prompt 的效率会高很多。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询