小学校园网站建设,公司官网制作百度,公司网站开发费用怎么做账,网站所有二级目录前言
IDEA启动#xff01;大模型的title想必不用我多说了#xff0c;多少公司想要搭上时代前言技术的快车#xff0c;感受科技的魅力。现在大模型作为降本增效的强大工具#xff0c;基本上公司大多人都想要部署开发一把#xff0c;更多的想要利用到这些模型放到生产中来提…前言
IDEA启动大模型的title想必不用我多说了多少公司想要搭上时代前言技术的快车感受科技的魅力。现在大模型作为降本增效的强大工具基本上公司大多人都想要部署开发一把更多的想要利用到这些模型放到生产中来提高生产力。但是对于我们开发者来说找到实际落地场景可以说是产品的活我们需要思考如何高效维护AI这个模块如何建立项目层级结构才能更好的解耦。正巧最近遇到了这个需求来和大家分享项目搭建流程此项目将运用到我个人开发的网页和网站上面感兴趣的同学可以去体验一下再来看看项目设计结构会更有心得。
项目顶层架构
首先AI这块应该在业务体系中应该较大的模块AI落地应用的场景不限于AI客服问答还可以应用在知识库管理、数据快速展示、ChatBI等一系列场景但是目前我们的项目这块是用于Web应用上面的所以采用一般也是JAVAWeb层级结构那么我们就很好确定后端技术栈。 技术选型 Spring Boot: 作为项目的核心框架用于快速构建 RESTful API 和管理依赖。 MyBatis-Plus: 用于数据库持久化操作简化了 MyBatis 的使用并提供了基本的 CRUD 方法。 AI SDK: 用于与AI 服务进行交互处理 AI 模型的调用和返回结果。 Lombok: 用于减少样板代码如 getter、setter、构造函数等。 MySQL: 作为数据库用于存储 AI 会话数据。
我这里调用的是阿里通义千问的模型当然每个厂商的AI SDK都大差不差调用规则基本都是一致的通过查阅SDK的返回参数就能很轻松的调用
核心流程
API 请求处理: 前端或客户端通过 TongyiChatReqDto 提交用户的 prompt问题到后端。 后端的 AliyunTongyiServicelmpl 使用阿里云的 dashscope API 调用将用户的问题提交给 AI 模型。
API 响应处理: dashscope API 返回 AI 的响应封装在 AiResponse DTO 中。 后端通过 AiResponseToPoConverter 将 AiResponse 转换为 AiChatTongyiRespPo 实体类。
数据持久化: 转换后的实体对象 AiChatTongyiRespPo 通过 AiChatTongyiRespRepository 保存到本地的 MySQL 数据库中。 数据持久化包括存储 AI 的会话 ID、返回文本、结束状态、模型编号、输入和输出 tokens 等信息。
业务处理: 后端返回封装好的 TongyiChatRespDto 响应对象包含 AI 的回复文本供前端展示。
顶层设计
首先应该有两个模块一层为处理Web端数据回传将用户在前端提交的文本数据处理里面可以加入敏感词检测、不符对话逻辑过滤等一系列业务逻辑然后把这些内容提交到AI交互模块在数据落库方面还需要能够记录每次对话内容的交互数据这部分的数据尽量偏业务方向不需要记录AI返回的Tokens状态等数据只需要记录表层与用户交互的数据比如对返回的文本点赞评分等。
另一层为处理与AI数据交互需要将我们处理过需要交互的数据提交到AI SDK的接口上获取返回的数据这部分数据也需要记录因为后续我们可能会去做一些不同AI反馈效果也可能会去进行大模型多模态的应用所以要尽可能的低耦合多划分层级对后面后续维护项目很重要。之后还需要能够记录能够帮助我们调优AI性能的数据比如每次传输的tokens数量响应时间等数据。
项目实现
AI通信层
我们先来处理与AI通信交互这层功能 api这一模块实现与AI接口的交互也就是查阅相关SDK文档找到AI返回的数据格式获取到了数据之后记录到数据库之中并且通过api传输给其他服务确定层级有 1. config 包 Configuration.java: 负责项目的配置管理通常用于定义和加载一些项目启动时所需的配置类、Bean、服务或者第三方服务的连接配置。 Properties.java: 用于加载和存储配置文件如 application.yml 或 application.properties中的属性主要用于配置 API 相关的信息比如 apiKey 和 chatAppId。通常使用 Spring 的 ConfigurationProperties 注解将配置文件中的内容映射为 Java 对象。
2. dal包 AiChatRespPo.java: 持久化对象PO用于映射到数据库表 ai_request。这个类的实例代表从数据库读取或保存到数据库的一条记录。它包含 AI 会话相关的数据如 requestId、prompt、text、finishReason、modelId、inputTokens、outputTokens 等字段通常与 MyBatis-Plus 或其他持久化框架一起使用。
3. domain包 AiResponse.java: 数据传输对象DTO用于封装从阿里云 Dashscope API 返回的 AI 响应数据并在应用层之间传递。该类包含 AI 响应的相关信息如 requestId、text、finishReason、usage模型使用信息。DTO 的作用是将数据从服务层传递到表示层或反之不涉及业务逻辑或持久化操作。
4. domain 包 EvaluateEnum.java: 枚举类用于定义用户对 AI 响应的评价状态可能包含 满意、不满意 等选项。枚举类在代码中提供了一种类型安全的方式来表示固定的常量集。
5. exception 包 NetworkException.java: 自定义异常类用于处理网络或 API 调用过程中的错误。自定义异常可以使异常处理更具语义化并且能够在捕获异常时提供更多的上下文信息比如错误码或详细的错误消息。
6. repository 包 AiChatRespRepository.java: 自定义的 Repository 接口定义了保存 AiChatTongyiRespPo 实体对象的方法。这个接口负责抽象数据持久化操作隐藏了底层的数据访问细节。实现该接口的类负责实际的数据操作逻辑通常使用 MyBatis-Plus 或其他持久化技术。
7. repository.impl 包 AiChatRespRepositoryImpl.java: 该类实现了 AiChatTongyiRespRepository 接口负责将 AiChatTongyiRespPo 实体对象保存到数据库中。它使用 MyBatis-Plus 或其他 ORM 框架来执行数据持久化操作并管理数据库事务。
8. service包 AliyunTongyiServicelmpl.java: 这是核心的业务逻辑实现类处理与阿里云 Dashscope AI 服务的交互。它通过阿里云 API 发起请求获取 AI 模型的响应数据然后将该数据通过转换器AiResponseToPoConverter转换为持久化对象并保存到数据库中。同时它还负责处理请求和响应的各种业务逻辑和异常情况。
基于上述内容我们可以来先设计DTO
DTO
public class AiResponse {/*** AI单条会话ID*/private String requestId;/*** 提问内容*/private String prompt;/*** AI返回的文本*/private String text;/*** 完成原因*/private String finishReason;/*** 模型信息*/private ListApplicationUsage.ModelUsage usage;
public AiResponse(String requestId,String prompt, String text, String finishReason, ApplicationUsage usage) {this.requestId requestId;this.prompt prompt;this.text text;this.finishReason finishReason;this.usage usage ! null ? usage.getModels() : null;}
}
这部分查阅SDK看返回数据格式把这部分最简单先做了。然后设计数据落表
数据表
CREATE TABLE ai_request (id bigint NOT NULL AUTO_INCREMENT COMMENT 主键标识,request_id varchar(50) NOT NULL COMMENT 会话ID,prompt longtext COMMENT 提问内容,text longtext COMMENT 返回文本,finishReason varchar(5) NOT NULL COMMENT 结束状态,model_code varchar(50) NOT NULL COMMENT 模型编号,input_tokens bigint NOT NULL COMMENT 输入tokens,output_tokens bigint NOT NULL COMMENT 输出tokens,create_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT 创建时间,update_time datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT 修改时间,PRIMARY KEY (id)
) ENGINEInnoDB DEFAULT CHARSETutf8mb4 COLLATEutf8mb4_0900_ai_ci COMMENT智能客服应答表;
有了表之后我们建立相应的转换和po层
po
public class AiChatTongyiRespPo {/*** 主键id*/TableId(value id, type IdType.AUTO)private Long id;
/*** 提问内容*/TableField(value prompt)private String prompt;
/*** 返回编号*/TableField(value request_id)private String requestId;
/*** 返回文本*/TableField(value text)private String text;
/*** 结束状态*/TableField(value finish_reason)private String finishReason;
/*** 模型编号*/TableField(value model_id)private String modelId;
/*** 输入tokens*/TableField(value input_tokens)private String inputTokens;
/*** 输出tokens*/TableField(value output_tokens)private String outputTokens;
}
再来写convert
convert
public static AiChatTongyiRespPo convert(AiResponse aiResponse) {AiChatTongyiRespPo po new AiChatTongyiRespPo();ApplicationUsage.ModelUsage modelUsage aiResponse.getUsage().get(0);// 将 DTO 中的数据映射到 PO 中po.setRequestId(aiResponse.getRequestId());po.setPrompt(aiResponse.getPrompt());po.setText(aiResponse.getText());po.setFinishReason(aiResponse.getFinishReason());po.setModelId(modelUsage.getModelId());po.setInputTokens(String.valueOf(modelUsage.getInputTokens()));po.setOutputTokens(String.valueOf(modelUsage.getOutputTokens()));
return po;}
再来写实现层就好写了
service
public TongyiChatRespDto chat(TongyiChatReqDto dto) {try {// 构建API调用参数ApplicationParam param ApplicationParam.builder().apiKey(aliyunProperties.getTongyi().getApiKey()).appId(aliyunProperties.getTongyi().getChatAppId()).prompt(dto.getPrompt()).build();Application application new Application();ApplicationResult result application.call(param);// 创建返回对象AiResponse response new AiResponse(result.getRequestId(), dto.getPrompt(), result.getOutput().getText(), result.getOutput().getFinishReason(), result.getUsage());// 将 AiResponse 转换为实体类 AiChatTongyiRespPoAiChatTongyiRespPo po AiResponseToPoConverter.convert(response);aiChatTongyiRespRepository.saveAiResponse(po);return new TongyiChatRespDto().setReply(result.getOutput().getText());
到现在写service就很好写了通过层级划分DTO、Service、Repository、PO 等清晰分离了不同的职责保证了代码的可维护性和扩展性。引入 Converter 模块将 DTO 转换为实体对象简化了业务层的逻辑并实现了代码的复用。这一框架实现了从用户输入到 AI 模型响应再到数据持久化的全链路处理下一章我们继续完善前端通信部分。