AI 旅游助手
✅完成 AI 旅游助手 部署上线; 线上地址:http://159.75.74.182/ GitHub:https://github.com/StarsTears/prodigal-ai-travel

该系统支持
- 高德MCP
- 查询当前位置
- 给指定邮箱发送消息
- 图片搜索
- 天气查询
- 获取当前IP
- PDF生成工具
fix
- 获取ip地址-修复之前获取的是服务器出口ip;现已调整为获取用户当前位置;
模型是使用阿里云的免费额度;逐步完善该系统! 后续继续学习AI 相关知识,以及开始看面试鸭了😭
若使用 qwen3.6-plus 模型;需在开启多模态;
不开启enable-thinking: true 会报以下错误:
org.springframework.ai.retry.NonTransientAiException: HTTP 400 - {"request_id":"f9354ca8-b0ca-9580-a18e-85cd2677f648","code":"InvalidParameter","message":"url error, please check url! For details, see: https://help.aliyun.com/zh/model-studio/error-code#error-url"} 模型名称与API端点不匹配:例如调用纯文本模型时使用了多模态接口,或者调用多模态模型时使用了纯文本接口。 解决方案:通过DashScope使用qwen3.6-plus、qwen3-vl-plus等多模态模型时:需使用 MultiModalConversation.call() 或 multimodal-generation 端点。若使用 spring-ai-alibaba 框架,请确认是否设置多模态参数 withMultiModel
▼xml复制代码dashscope: api-key: sk-XXXXX chat: options: model: qwen3.6-plus temperature: 0.7 enable-thinking: true multi-model: true embedding: options: model: text-embedding-v2
使用 mini max 模型:
相关依赖
▼xml复制代码<!--mini max--> <dependency> <groupId>org.springframework.ai</groupId> <artifactId>spring-ai-starter-model-minimax</artifactId> </dependency>
配置文件:
▼xml复制代码ai: minimax: api-key: sk-XXXXXXX chat: options: model: MiniMax-M2.7 temperature: 0.7
构造 Client:
▼java复制代码@Configuration public class AIClient { @Resource private ToolCallback[] allTools; @Resource private ToolCallbackProvider toolCallbackProvider; @Bean ChatClient minimaxAiClient(MiniMaxChatModel chatModel) { // 基于内存会话记忆 InMemoryChatMemoryRepository inMemoryChatMemoryRepository = new InMemoryChatMemoryRepository(); MessageWindowChatMemory chatMemory = MessageWindowChatMemory .builder() .chatMemoryRepository(inMemoryChatMemoryRepository) .build(); MessageChatMemoryAdvisor messageChatMemoryAdvisor = MessageChatMemoryAdvisor.builder(chatMemory).build(); return ChatClient.builder(chatModel) .defaultSystem(TravelConstant.SYSTEM_PROMPT) .defaultAdvisors(new LoggerAdvisor(), messageChatMemoryAdvisor, new SystemMessageFirstAdvisor()) .defaultToolCallbacks(allTools) .defaultToolCallbacks(toolCallbackProvider) .build(); } }
其中 system 的prompt 需排在 会话记忆 最前 ;否则会报如下错误:
invalid params, chat content has invalid message role: system
▼java复制代码public class SystemMessageFirstAdvisor implements BaseAdvisor { @Override public int getOrder() { return Advisor.DEFAULT_CHAT_MEMORY_PRECEDENCE_ORDER + 1; } @Override public ChatClientRequest before(ChatClientRequest chatClientRequest, AdvisorChain advisorChain) { List<Message> messages = chatClientRequest.prompt().getInstructions(); List<Message> system = new ArrayList<>(); List<Message> rest = new ArrayList<>(); for (Message m : messages) { if (m.getMessageType() == MessageType.SYSTEM) { system.add(m); } else { rest.add(m); } } List<Message> ordered = new ArrayList<>(system.size() + rest.size()); ordered.addAll(system); ordered.addAll(rest); return chatClientRequest.mutate() .prompt(chatClientRequest.prompt().mutate().messages(ordered).build()) .build(); } @Override public ChatClientResponse after(ChatClientResponse chatClientResponse, AdvisorChain advisorChain) { return chatClientResponse; } }
编写测试文件
▼java复制代码@Service public class MinimaxServiceImpl implements AIService { @Resource @Qualifier("minimaxAiClient") ChatClient minimaxAiClient; @Override public String doChat(String message,String conversationId) { ChatResponse chatResponse = minimaxAiClient.prompt() .user(message) //对话Id、关联对话数 .advisors(spec -> spec.param(ChatMemory.CONVERSATION_ID, conversationId) .param("TOP_K", 20)) .call() .chatResponse(); return chatResponse.getResult().getOutput().getText(); } } @Test void doChat() { String chatId = UUID.fastUUID().toString(); String message = "你好!我是Prodigal!请问今天几号"; String result = minimaxService.doChat(message, chatId); log.info(result); Assertions.assertNotNull( result); message = "获取当前位置。明天天气咋样?"; result = minimaxService.doChatWithMCPSSE(message, chatId,"IP"); log.info(result); Assertions.assertNotNull( result); message = "我是谁?"; result = minimaxService.doChat(message, chatId); log.info(result); Assertions.assertNotNull( result); }


