基于AI大模型实现大学生智能记账助手

 

作者简介:Java领域优质创作者、CSDN博客专家 、CSDN内容合伙人、掘金特邀作者、阿里云博客专家、51CTO特邀作者、多年架构师设计经验、多年校企合作经验,被多个学校常年聘为校外企业导师,指导学生毕业设计并参与学生毕业答辩指导,有较为丰富的相关经验。期待与各位高校教师、企业讲师以及同行交流合作

主要内容:Java项目、Python项目、前端项目、PHP、ASP.NET、人工智能与大数据、单片机开发、物联网设计与开发设计、简历模板、学习资料、面试题库、技术互助、就业指导等

业务范围:免费功能设计、开题报告、任务书、中期检查PPT、系统功能实现、代码编写、论文编写和辅导、论文降重、长期答辩答疑辅导、腾讯会议一对一专业讲解辅导答辩、模拟答辩演练、和理解代码逻辑思路等

收藏点赞不迷路  关注作者有好处

文末获取源码 

BS-AI-019

一,环境介绍

语言环境:Java:  jdk1.8

数据库:Mysql: mysql5.7

应用服务器:Tomcat:  tomcat8.5.31

开发工具:IDEA或eclipse

技术:springboot+mysql+VUE+AI大模型

二,项目简介

大学生记账助手系统是一款专为大学生群体量身打造的个人财 务管理 Web 应用。聚焦大学生理财需求,通过便捷的记账操作、智 能的计划管理、直观的数据统计分析、智能预算管理、AI 用户画像 分析以及 AI 智能助手服务,帮助用户清晰掌握收支情况,逐步养成 科学理财习惯,提升财务管理能力。系统深度融合 AI 技术与财务管 理场景,兼顾实用性与易用性,为大学生提供全流程、智能化的理 财解决方案。

用户体验设计:

1. 高颜值+强适配 UI 设计

○ 采用现代化渐变背景、卡片式布局与微交互动画(按钮 hover 效果、页面切换过渡),视觉体验舒适;

○ 全页面响应式设计,完美适配 PC 端(≥1200px)、平板 (768-1199px);

○ 统一设计规范:面包屑导航明确当前位置、按钮样式统一 (主按钮/次要按钮/文本按钮区分)、提示消息统一位置(顶部 居中),降低用户学习成本。

2. 拟人化 AI 助手

○ 猫头鹰形象设计可爱,悬浮状态不遮挡核心功能区,跟随用 户鼠标上下滑动;

○ 智能记忆功能:记住用户记账习惯、预算偏好、常用提问类 型,后续交互更贴合用户需求;

○ 多场景主动服务:除常规问候与提醒外,在用户长时间未记 账时推送"好久没记录收支啦,是否需要我帮你快速记账?",在 理财计划到期前 3 天主动提醒。

3. 沉浸式数据可视化

○ 基于 ECharts 5.4.3 实现多样化图表(饼图、柱状图、折线 图、环形图、直方图),支持动态加载动画与交互效果(点击筛 选、悬浮显示详情);

○ 预算管理页面图表联动:点击预算进度环某分类,支出饼图 自动高亮对应分类,数据关联更直观;

○ 图表支持导出数据。

创新功能设计:

全流程智能预算管理

○ 从预算设置(参考数据辅助)→进度监控(可视化展示)→ 风险预警(多级提醒)→优化建议(AI 生成),形成闭环管 理;

○ 分类预算精细化控制,满足用户个性化需求(如"考研党可 增加学习资料分类预算");

○ 预算调整支持"一键重置"与"批量修改",操作高效便捷。

2. AI 驱动的用户画像体系

○ 无需用户手动填写,基于行为数据自动生成,画像维度全面 且贴合大学生场景;

○ 分析报告动态更新(每月 1 日自动刷新),支持查看历史画 像变化,跟踪理财习惯改善效果;

○ 个性化建议落地性强(如"你的奶茶支出占比过高,建议设 置每周奶茶消费上限 2 次"),而非泛化指导。

3. 高效便捷的一键记账

○ 解决传统记账"步骤繁琐、容易遗漏"痛点,OCR 识别覆盖主 流账单类型(外卖小票、超市收据、支付截图);

○ 支持批量上传多张账单图片,系统自动批量解析、生成多条 记账草稿,用户批量确认即可完成记账;

○ 识别结果错误时,支持手动修正并记忆用户修正习惯(如某 商家多次被误识别,后续自动校正)。

4. 智能化计划管理

○ 循环计划支持灵活配置(如"每月 5 日执行,连续 12 次 "),到期自动提醒并重置进度;

○ 计划关联记账记录,自动计算完成进度(如"每月存 1000 元 "计划,自动统计当月存款金额);15

○ 新增"计划分享"功能,支持生成海报分享至社交平台,邀请 好友一起打卡完成理财计划。

技术保障:

1 高效架构设计

○ 采用"前端组件化+后端微服务思想",用户中心与管理中心 通过 iframe 实现模块化隔离,页面加载无需整页刷新,响应速 度提升 40%;

○ 核心业务逻辑分层清晰(Controller→Service→DAO),通 过 Spring Boot 自动配置简化开发,支持快速迭代;

○ 引入 Redis 缓存热点数据(如用户画像、预算数据、理财产 品列表),查询响应时间≤300ms。

2. 全方位安全防护

○ 身份认证:基于 Session+Token 双重验证,未登录用户访问 受保护页面自动跳转至登录页,Token 有效期 2 小时(无操作自 动过期);

○ 数据安全:密码采用 BCrypt 加密存储(不可逆),敏感信 息(手机号、邮箱)脱敏展示,数据库传输采用 SSL 加密;

○ 操作防护:关键操作(删除、修改)需二次确认,防止误操 作;接口层面添加防重复提交机制(基于 Token+时间戳),抵 御恶意请求。

3. AI 技术深度集成16

○ 集成阿里云通义千问大模型,支持流式响应(边生成边展示 回答),对话延迟≤1 秒,提升交互流畅度;

○ OCR 服务优化:针对校园场景账单(如食堂小票、打印店收 据)进行模型训练,识别准确率比通用 OCR 提升 15%;

○ 自然语言处理(NLP)支持意图识别(查询、咨询、设 置)、关键词提取,精准理解用户需求,无需严格句式。

特色功能优势:

1 精细化权限管控

○ 三级角色权限体系(系统管理员>普通管理员>普通用 户),权限颗粒度细化至功能按钮(如普通管理员无"删除用户" 权限);

○ 基于 RBAC 模型设计,权限分配灵活,支持按角色批量授 权,新增管理员时可快速复制已有角色权限。

2. 完善的数据生态

○ 核心数据模块(记账、计划、预算、画像)均支持完整的增 删改查操作,操作日志自动记录(谁、何时、操作内容),可追 溯可审计;

○ 数据验证机制全面:前端实时校验(格式、必填项)+后端 参数校验(合法性、范围)+数据库约束(唯一性、非空),多 层保障数据准确性;

○ 支持数据备份与恢复(系统管理员权限),自动备份频率为 每日凌晨,保留近 30 天备份记录。

3. 便捷的文件处理

○ 支持多类型文件上传(图片、PDF),文件大小限制 10MB, 格式校验+病毒扫描双重防护,防止恶意文件上传;

○ 上传文件自动存储至阿里云 OSS,支持 CDN 加速访问,图片 自动压缩优化(保持清晰度前提下减小体积),提升页面加载速 度;

○ 支持文件在线预览(如账单图片、PDF 格式分析报告),无 需下载本地。

三,系统展示

管理员后台管理界面

四,核心代码展示

package com.it.controller;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.*;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.client.RestTemplate;

import javax.servlet.http.HttpServletRequest;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

@RestController
@RequestMapping("/api")
public class AIController {
    
    // Java 8 兼容的字符串重复方法(替代 String.repeat())
    private String repeatString(String str, int count) {
        if (count <= 0) return "";
        StringBuilder sb = new StringBuilder();
        for (int i = 0; i < count; i++) {
            sb.append(str);
        }
        return sb.toString();
    }
    
    // 创建RestTemplate的方法,每次调用时创建新实例以确保连接正确管理
    private RestTemplate createRestTemplate() {
        // 配置HTTP客户端超时时间
        org.springframework.http.client.SimpleClientHttpRequestFactory factory = 
            new org.springframework.http.client.SimpleClientHttpRequestFactory();
        factory.setConnectTimeout(10000); // 连接超时10秒
        factory.setReadTimeout(60000);    // 读取超时60秒
        
        RestTemplate restTemplate = new RestTemplate(factory);
        // 配置字符编码支持UTF-8
        org.springframework.http.converter.StringHttpMessageConverter stringConverter = 
            new org.springframework.http.converter.StringHttpMessageConverter(java.nio.charset.StandardCharsets.UTF_8);
        restTemplate.getMessageConverters().set(1, stringConverter);
        
        return restTemplate;
    }
    
    // 阿里通义千问API配置
    // 获取API Key:https://dashscope.console.aliyun.com/ → API-KEY管理
    // 注意:API Key通常以 sk- 开头,如果您的Key是 lm- 开头,可能需要使用不同的端点
    // 尝试使用原生DashScope API端点(如果兼容模式不工作)
    // 通义星尘API配置(根据官方文档)
    // 使用兼容OpenAI格式的端点
    private static final String ALIBABA_API_URL = "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions";
    private static final String ALIBABA_MODEL = "qwen-turbo"; // 可选: qwen-turbo, qwen-plus, qwen-max
    
    // 从配置文件读取API Key(如果配置了的话)
    @Value("${ai.alibaba.api.key:}")
    private String alibabaApiKey;
    
    // 获取API Key(优先级:环境变量 > 配置文件 > 硬编码备用)
    private String getApiKey() {
        // 优先级1:从环境变量读取(推荐方式,符合通义星尘文档)
        String envApiKey = System.getenv("DASHSCOPE_API_KEY");
        if (envApiKey != null && !envApiKey.trim().isEmpty()) {
            String cleanKey = envApiKey.trim();
            System.out.println("Using API Key from environment variable (DASHSCOPE_API_KEY), length: " + cleanKey.length());
            return cleanKey;
        }
        
        // 优先级2:从配置文件读取
        if (alibabaApiKey != null && !alibabaApiKey.trim().isEmpty() && !alibabaApiKey.equals("YOUR_ALIBABA_API_KEY")) {
            String cleanKey = alibabaApiKey.trim().replace("\n", "").replace("\r", "");
            System.out.println("Using API Key from config file (application.properties), length: " + cleanKey.length());
            return cleanKey;
        }
        
        // 优先级3:硬编码备用(仅用于测试,生产环境应删除)
        String hardcodedKey = "lm-aqD98gWnHIthNAdLYXfHBg==";
        System.out.println("Using hardcoded API Key (fallback for testing), length: " + hardcodedKey.length());
        System.out.println("WARNING: Using hardcoded API Key. Please configure DASHSCOPE_API_KEY environment variable or application.properties");
        return hardcodedKey;
    }
    
    /**
     * AI聊天接口
     * @param requestBody 请求体,包含message和history
     * @return AI回复
     */
    @RequestMapping(value = "/chat", method = RequestMethod.POST, consumes = "application/json")
    @ResponseBody
    public Map<String, Object> chat(@RequestBody Map<String, Object> requestBody, HttpServletRequest request) {
        // 从请求体中提取参数
        String message = (String) requestBody.get("message");
        String history = null;
        if (requestBody.containsKey("history")) {
            Object historyObj = requestBody.get("history");
            if (historyObj instanceof List) {
                // 如果是List,转换为JSON字符串
                history = JSON.toJSONString(historyObj);
            } else if (historyObj instanceof String) {
                history = (String) historyObj;
            }
        }
        Map<String, Object> result = new HashMap<>();
        
        try {
            // 获取当前登录用户信息
            com.it.entity.Member member = (com.it.entity.Member) request.getSession().getAttribute("sessionmember");
            String userName = null;
            if (member != null) {
                userName = member.getTname(); // 获取用户真实姓名
                if (userName == null || userName.trim().isEmpty()) {
                    userName = member.getUname(); // 如果没有真实姓名,使用用户名
                }
                System.out.println("当前登录用户: " + userName + " (ID: " + member.getId() + ")");
            } else {
                System.out.println("用户未登录");
            }
            
            // 解析历史对话
            List<Map<String, String>> messages = new ArrayList<>();
            
            // 构建系统提示词(包含用户信息)
            StringBuilder systemContent = new StringBuilder();
            systemContent.append("你是一个专业的记账本AI助手,擅长帮助用户管理财务、提供理财建议、解答记账相关问题。");
            if (userName != null && !userName.trim().isEmpty()) {
                systemContent.append("当前与你对话的用户是:").append(userName).append("。");
                systemContent.append("请在对话中自然地使用用户的名字,让对话更加亲切和个性化。");
            }
            systemContent.append("请用友好、专业的语气回答用户的问题。");
            
            // 添加系统提示词(针对记账本助手)
            Map<String, String> systemMsg = new HashMap<>();
            systemMsg.put("role", "system");
            systemMsg.put("content", systemContent.toString());
            messages.add(systemMsg);
            
            // 添加历史对话
            if (history != null && !history.isEmpty()) {
                try {
                    List<Map> historyList = JSON.parseArray(history, Map.class);
                    for (Map item : historyList) {
                        Map<String, String> msg = new HashMap<>();
                        msg.put("role", (String) item.get("role"));
                        msg.put("content", (String) item.get("content"));
                        messages.add(msg);
                    }
                } catch (Exception e) {
                    // 历史对话解析失败,忽略
                }
            }
            
            // 添加当前用户消息
            Map<String, String> userMsg = new HashMap<>();
            userMsg.put("role", "user");
            userMsg.put("content", message);
            messages.add(userMsg);
            
            // 调用阿里通义千问API
            String aiResponse = null;
            String apiKey = getApiKey();
            
            // 调试:输出API Key的前几个字符(用于确认是否读取成功)
            System.out.println("\n========== 新的聊天请求 ==========");
            System.out.println("请求时间: " + new java.util.Date());
            System.out.println("用户消息: " + message);
            System.out.println("历史消息数量: " + messages.size());
            System.out.println("API Key length: " + (apiKey != null ? apiKey.length() : 0));
            System.out.println("API Key prefix: " + (apiKey != null && apiKey.length() > 5 ? apiKey.substring(0, 5) + "..." : "null"));
            
            // 如果API Key已配置,调用真实API;否则使用模拟回复
            if (apiKey != null && !apiKey.equals("YOUR_ALIBABA_API_KEY") && !apiKey.isEmpty()) {
                try {
                    aiResponse = callAlibabaQwen(messages, apiKey);
                } catch (Exception e) {
                    System.out.println("❌ API调用过程中发生异常: " + e.getClass().getName());
                    System.out.println("异常信息: " + e.getMessage());
                    e.printStackTrace();
                    throw e; // 重新抛出异常,让外层catch处理
                }
            } else {
                // 使用模拟回复(用于测试或API未配置时)
                System.out.println("Using mock response - API Key not configured");
                aiResponse = getMockResponse(message);
            }
            
            if (aiResponse != null && !aiResponse.isEmpty()) {
                result.put("success", true);
                result.put("message", aiResponse);
            } else {
                result.put("success", false);
                result.put("message", "抱歉,AI服务暂时无法响应,请稍后再试。");
            }
            
        } catch (Exception e) {
            e.printStackTrace();
            result.put("success", false);
            result.put("message", "服务异常:" + e.getMessage());
        }
        
        return result;
    }
    
    /**
     * 调用阿里通义千问API
     */
    private String callAlibabaQwen(List<Map<String, String>> messages, String apiKey) {
        System.out.println("\n" + repeatString("=", 60));
        System.out.println("🧠 AI 思考过程开始");
        System.out.println(repeatString("=", 60));
        System.out.println("📊 消息数量: " + messages.size());
        
        try {
            // 调试:检查API Key是否为空(不输出完整Key,只检查长度)
            if (apiKey == null || apiKey.isEmpty() || apiKey.equals("YOUR_ALIBABA_API_KEY")) {
                System.out.println("❌ API Key未配置");
                return "❌ API Key未配置\n\n请在 application.properties 中配置 ai.alibaba.api.key";
            }
            
            // 显示完整的对话历史
            System.out.println("\n📝 对话历史:");
            System.out.println(repeatString("-", 60));
            for (int i = 0; i < messages.size(); i++) {
                Map<String, String> msg = messages.get(i);
                String role = msg.get("role");
                String content = msg.get("content");
                String roleName = "system".equals(role) ? "系统" : 
                                 "user".equals(role) ? "用户" : "AI助手";
                System.out.println("[" + (i + 1) + "] " + roleName + ":");
                // 如果内容太长,只显示前200个字符
                if (content != null && content.length() > 200) {
                    System.out.println("    " + content.substring(0, 200) + "... (共" + content.length() + "字符)");
                } else {
                    System.out.println("    " + content);
                }
            }
            System.out.println(repeatString("-", 60));
            
            // 通义千问的input格式:可以是字符串或消息数组
            // 如果使用消息数组,需要过滤掉system角色(通义千问可能不支持system角色)
            // 将system消息的内容合并到第一个user消息中,或者作为prompt
            
            System.out.println("\n🔧 步骤1: 处理消息列表...");
            List<Map<String, String>> qwenMessages = new ArrayList<>();
            String systemPrompt = "";
            
            // 处理消息列表
            for (Map<String, String> msg : messages) {
                String role = msg.get("role");
                String content = msg.get("content");
                
                if ("system".equals(role)) {
                    // 保存系统提示词
                    systemPrompt = content;
                    System.out.println("   ✓ 提取系统提示词: " + (content.length() > 50 ? content.substring(0, 50) + "..." : content));
                } else {
                    // 添加用户和助手消息
                    Map<String, String> qwenMsg = new HashMap<>();
                    // 通义千问使用 user 和 assistant 角色
                    if ("assistant".equals(role)) {
                        qwenMsg.put("role", "assistant");
                    } else {
                        qwenMsg.put("role", "user");
                    }
                    qwenMsg.put("content", content);
                    qwenMessages.add(qwenMsg);
                }
            }
            
            System.out.println("   ✓ 处理完成,有效消息数: " + qwenMessages.size());
            
            // 如果有系统提示词,将其添加到第一个用户消息的开头
            if (!systemPrompt.isEmpty() && !qwenMessages.isEmpty()) {
                System.out.println("   ✓ 将系统提示词合并到第一个用户消息");
                Map<String, String> firstMsg = qwenMessages.get(0);
                if ("user".equals(firstMsg.get("role"))) {
                    firstMsg.put("content", systemPrompt + "\n\n" + firstMsg.get("content"));
                }
            }
            
            // 构建请求体(使用兼容OpenAI格式)
            System.out.println("\n🔧 步骤2: 构建API请求...");
            Map<String, Object> requestBody = new HashMap<>();
            requestBody.put("model", ALIBABA_MODEL);
            requestBody.put("messages", qwenMessages); // 使用messages而不是input
            requestBody.put("temperature", 0.7);
            requestBody.put("max_tokens", 2000);
            
            System.out.println("   ✓ 模型: " + ALIBABA_MODEL);
            System.out.println("   ✓ 温度参数: 0.7 (创造性)");
            System.out.println("   ✓ 最大Token数: 2000");
            
            // 设置请求头
            HttpHeaders headers = new HttpHeaders();
            headers.setContentType(MediaType.APPLICATION_JSON);
            // 确保API Key没有前后空格
            String cleanApiKey = apiKey.trim();
            
            // 根据通义星尘文档,使用Bearer认证(所有API Key都使用Bearer)
            headers.set("Authorization", "Bearer " + cleanApiKey);
            
            // 调试:输出请求信息(不输出完整API Key)
            System.out.println("   ✓ API端点: " + ALIBABA_API_URL);
            System.out.println("   ✓ API Key: " + (cleanApiKey.length() > 3 ? cleanApiKey.substring(0, Math.min(5, cleanApiKey.length())) + "..." : "N/A") + " (长度: " + cleanApiKey.length() + ")");
            System.out.println("   ✓ 认证方式: Bearer Token");
            
            // 计算请求体大小
            String requestBodyStr = JSON.toJSONString(requestBody);
            System.out.println("   ✓ 请求体大小: " + requestBodyStr.length() + " 字符");
            
            // 显示发送给API的消息摘要
            System.out.println("\n📤 发送给API的消息摘要:");
            System.out.println(repeatString("-", 60));
            for (int i = 0; i < qwenMessages.size(); i++) {
                Map<String, String> msg = qwenMessages.get(i);
                String role = msg.get("role");
                String content = msg.get("content");
                String roleName = "user".equals(role) ? "用户" : "AI助手";
                System.out.println("[" + (i + 1) + "] " + roleName + ": " + 
                    (content.length() > 100 ? content.substring(0, 100) + "..." : content));
            }
            System.out.println(repeatString("-", 60));
            
            HttpEntity<Map<String, Object>> request = new HttpEntity<>(requestBody, headers);
            
            // 发送请求 - 每次创建新的RestTemplate实例以确保连接正确管理
            System.out.println("\n🔧 步骤3: 发送API请求...");
            System.out.println("   ⏳ 正在连接API服务器...");
            long startTime = System.currentTimeMillis();
            ResponseEntity<String> response = null;
            RestTemplate restTemplate = createRestTemplate(); // 每次创建新实例
            try {
                response = restTemplate.exchange(
                    ALIBABA_API_URL,
                    HttpMethod.POST,
                    request,
                    String.class
                );
                long endTime = System.currentTimeMillis();
                long duration = endTime - startTime;
                System.out.println("   ✅ API请求成功!");
                System.out.println("   ⏱️  响应时间: " + duration + "ms (" + (duration / 1000.0) + "秒)");
            } catch (org.springframework.web.client.HttpClientErrorException e) {
                long endTime = System.currentTimeMillis();
                System.out.println("❌ HTTP客户端错误,耗时: " + (endTime - startTime) + "ms");
                System.out.println("错误状态码: " + e.getStatusCode());
                System.out.println("错误响应体: " + e.getResponseBodyAsString());
                // 直接抛出异常,由外层catch处理
                throw e;
            } catch (org.springframework.web.client.ResourceAccessException e) {
                long endTime = System.currentTimeMillis();
                System.out.println("❌ 网络连接错误,耗时: " + (endTime - startTime) + "ms");
                System.out.println("错误信息: " + e.getMessage());
                e.printStackTrace();
                throw e;
            } catch (org.springframework.web.client.RestClientException e) {
                long endTime = System.currentTimeMillis();
                System.out.println("❌ RestTemplate异常,耗时: " + (endTime - startTime) + "ms");
                System.out.println("错误信息: " + e.getMessage());
                e.printStackTrace();
                throw e;
            }
            
            // 解析响应(兼容OpenAI格式)
            System.out.println("\n🔧 步骤4: 解析API响应...");
            String responseBody = response.getBody();
            
            // 调试:输出原始响应
            if (responseBody != null) {
                System.out.println("   ✓ 响应体大小: " + responseBody.length() + " 字符");
                System.out.println("   📄 原始响应预览:");
                System.out.println("   " + repeatString("-", 58));
                String preview = responseBody.length() > 300 ? responseBody.substring(0, 300) + "..." : responseBody;
                // 分行显示,每行最多60字符
                String[] lines = preview.split("\n");
                for (String line : lines) {
                    if (line.length() > 60) {
                        for (int i = 0; i < line.length(); i += 60) {
                            System.out.println("   " + line.substring(i, Math.min(i + 60, line.length())));
                        }
                    } else {
                        System.out.println("   " + line);
                    }
                }
                System.out.println("   " + repeatString("-", 58));
            }
            
            System.out.println("   ⏳ 正在解析JSON响应...");
            JSONObject jsonResponse = JSON.parseObject(responseBody);
            System.out.println("   ✓ JSON解析成功");
            
            // 检查是否有错误(兼容OpenAI格式的错误)
            if (jsonResponse.containsKey("error")) {
                JSONObject error = jsonResponse.getJSONObject("error");
                String errorType = error.containsKey("type") ? error.getString("type") : "";
                String errorMsg = error.containsKey("message") ? error.getString("message") : "";
                
                if ("invalid_api_key".equals(errorType) || errorMsg.contains("API key")) {
                    return "❌ API Key错误或未配置\n\n" +
                           "请检查:\n" +
                           "1. application.properties 中的 ai.alibaba.api.key 是否正确\n" +
                           "2. API Key是否有效(未过期)\n" +
                           "3. 是否已重启应用\n\n" +
                           "获取API Key:https://dashscope.console.aliyun.com/\n" +
                           "错误详情:" + errorMsg;
                } else {
                    return "❌ API调用失败\n\n" +
                           "错误类型:" + errorType + "\n" +
                           "错误信息:" + errorMsg;
                }
            }
            
            // 检查是否有错误(通义千问原生格式的错误)
            if (jsonResponse.containsKey("code")) {
                String code = jsonResponse.getString("code");
                if (!"Success".equals(code)) {
                    String errorMsg = jsonResponse.getString("message");
                    String requestId = jsonResponse.containsKey("request_id") ? jsonResponse.getString("request_id") : "";
                    
                    if ("InvalidApiKey".equals(code) || "No API-key provided".equals(errorMsg)) {
                        return "❌ API Key错误或未配置\n\n" +
                               "请检查 application.properties 中的 ai.alibaba.api.key 配置\n\n" +
                               "错误详情:" + errorMsg;
                    } else {
                        return "❌ API调用失败\n\n" +
                               "错误代码:" + code + "\n" +
                               "错误信息:" + errorMsg;
                    }
                }
            }
            
            // 获取输出内容(兼容OpenAI格式)
            if (jsonResponse.containsKey("choices") && jsonResponse.getJSONArray("choices").size() > 0) {
                JSONObject choice = jsonResponse.getJSONArray("choices").getJSONObject(0);
                JSONObject message = choice.getJSONObject("message");
                String content = message.getString("content");
                
                // 调试:输出内容预览
                System.out.println("\n🔧 步骤5: 提取AI回复内容...");
                if (content != null) {
                    System.out.println("   ✓ 回复内容长度: " + content.length() + " 字符");
                    System.out.println("\n💬 AI的回复内容:");
                    System.out.println(repeatString("=", 60));
                    // 分行显示回复内容,每行最多60字符
                    String[] lines = content.split("\n");
                    for (String line : lines) {
                        if (line.length() > 60) {
                            // 如果单行太长,按60字符分段
                            for (int i = 0; i < line.length(); i += 60) {
                                System.out.println(line.substring(i, Math.min(i + 60, line.length())));
                            }
                        } else {
                            System.out.println(line);
                        }
                    }
                    System.out.println(repeatString("=", 60));
                }
                
                System.out.println("\n" + repeatString("=", 60));
                System.out.println("✅ AI 思考过程完成");
                System.out.println(repeatString("=", 60) + "\n");
                return content;
            }
            
            // 如果解析失败,返回原始响应用于调试
            return "⚠️ 响应解析失败\n\n原始响应:" + responseBody + "\n\n请检查API响应格式是否正确。";
            
        } catch (org.springframework.web.client.HttpClientErrorException e) {
            // HTTP错误(如401, 403等)
            String errorBody = e.getResponseBodyAsString();
            System.out.println("=== HTTP Error ===");
            System.out.println("Status Code: " + e.getStatusCode().value());
            System.out.println("Response Body: " + errorBody);
            System.out.println("API Key used: " + (apiKey != null ? apiKey.substring(0, Math.min(10, apiKey.length())) + "..." : "null"));
            
            try {
                JSONObject errorJson = JSON.parseObject(errorBody);
                String errorMsg = errorJson.containsKey("message") ? errorJson.getString("message") : 
                                 (errorJson.containsKey("error") ? errorJson.getJSONObject("error").getString("message") : errorBody);
                String code = errorJson.containsKey("code") ? errorJson.getString("code") : 
                            (errorJson.containsKey("error") ? errorJson.getJSONObject("error").getString("type") : String.valueOf(e.getStatusCode().value()));
                
                if (e.getStatusCode().value() == 401 || "InvalidApiKey".equals(code) || "invalid_api_key".equals(code)) {
                    return "❌ API Key认证失败 (401)\n\n" +
                           "请检查:\n" +
                           "1. application.properties 中的 ai.alibaba.api.key 是否正确配置\n" +
                           "2. 配置的API Key是否为:lm-aqD98gWnHIthNAdLYXfHBg==\n" +
                           "3. 是否已重启应用(配置更改需要重启)\n" +
                           "4. API Key是否有效(未过期、有权限)\n\n" +
                           "错误信息:" + errorMsg + "\n\n" +
                           "调试信息:请查看控制台输出的API Key前缀,确认是否正确读取\n" +
                           "获取API Key:https://dashscope.console.aliyun.com/";
                } else {
                    return "❌ HTTP错误:" + e.getStatusCode().value() + "\n\n错误代码:" + code + "\n错误信息:" + errorMsg;
                }
            } catch (Exception ex) {
                return "❌ HTTP错误:" + e.getStatusCode().value() + "\n\n响应内容:" + errorBody + "\n\n请查看控制台获取更多调试信息";
            }
        } catch (org.springframework.web.client.ResourceAccessException e) {
            System.out.println("========== API调用失败:网络连接异常 ==========");
            System.out.println("错误类型: ResourceAccessException");
            System.out.println("错误信息: " + e.getMessage());
            e.printStackTrace();
            String errorMsg = e.getMessage();
            if (errorMsg != null && errorMsg.contains("timeout")) {
                return "❌ 请求超时\n\nAPI响应时间过长(超过60秒),请稍后重试。\n\n错误详情:" + errorMsg + "\n\n提示:请查看控制台获取更多信息。";
            } else {
                return "❌ 网络连接失败\n\n无法连接到API服务器,请检查网络连接。\n\n错误详情:" + errorMsg + "\n\n提示:请查看控制台获取更多信息。";
            }
        } catch (org.springframework.web.client.RestClientException e) {
            System.out.println("========== API调用失败:RestTemplate异常 ==========");
            System.out.println("错误类型: RestClientException");
            System.out.println("错误信息: " + e.getMessage());
            e.printStackTrace();
            return "❌ API调用异常\n\n错误信息:" + e.getMessage() + "\n\n请查看控制台获取详细错误信息。";
        } catch (Exception e) {
            System.out.println("========== API调用失败:未知异常 ==========");
            System.out.println("错误类型: " + e.getClass().getName());
            System.out.println("错误信息: " + e.getMessage());
            e.printStackTrace();
            // 如果API调用失败,返回一个友好的提示
            return "❌ 服务异常\n\n错误信息:" + e.getMessage() + "\n\n" +
                   "可能的原因:\n" +
                   "1. 网络连接问题\n" +
                   "2. API Key未配置或配置错误\n" +
                   "3. API服务暂时不可用\n" +
                   "4. 请求超时\n\n" +
                   "请查看控制台获取详细错误信息。";
        } finally {
            System.out.println("========== API调用结束 ==========\n");
        }
    }
    
    /**
     * 如果不想使用OpenAI,可以使用这个简单的模拟回复(用于测试)
     */
    private String getMockResponse(String message) {
        // 简单的关键词匹配回复
        if (message.contains("记账") || message.contains("账单")) {
            return "记账是个好习惯!建议您每天记录收支,这样可以更好地了解自己的财务状况。";
        } else if (message.contains("理财") || message.contains("投资")) {
            return "理财需要谨慎,建议先学习基础知识,再根据自身情况选择合适的理财产品。";
        } else if (message.contains("养老保险")) {
            return "养老保险是重要的保障,建议您了解相关政策,合理规划养老资金。";
        } else {
            return "我是记账本AI助手,可以帮您解答记账、理财相关问题。有什么需要帮助的吗?";
        }
    }
}

五,相关作品展示

基于Java开发、Python开发、PHP开发、C#开发等相关语言开发的实战项目

基于Nodejs、Vue等前端技术开发的前端实战项目

基于微信小程序和安卓APP应用开发的相关作品

基于51单片机等嵌入式物联网开发应用

基于各类算法实现的AI智能应用

基于大数据实现的各类数据管理和推荐系统

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

qq_469603589

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值