AIAI-学习记录
FANSEAAI-Learning
AI的应用方面

Agent+Function Calling

Rag Embeddings

开发框架选择



对话机器人
基本调用
- 引入依赖
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 
 | <dependency><groupId>org.springframework.ai</groupId>
 <artifactId>spring-ai-openai-spring-boot-starter</artifactId>
 </dependency>
 
 <dependencyManagement>
 <dependencies>
 <dependency>
 <groupId>org.springframework.ai</groupId>
 <artifactId>spring-ai-bom</artifactId>
 <version>${spring-ai.version}</version>
 <type>pom</type>
 <scope>import</scope>
 </dependency>
 </dependencies>
 </dependencyManagement>
 
 | 
- 配置Client
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 
 | @Configurationpublic class CommonConfiguration {
 @Bean
 public ChatClient chatClient(OpenAiChatModel model){
 return ChatClient
 .builder(model)
 .defaultSystem("你是一个AI助手,名字叫帆帆,你要热心回答用户的问题")
 .build();
 }
 }
 
 
 | 
- 生成会话
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 
 | public class AiController {
 private final ChatClient chatClient;
 
 
 @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
 public Flux<String> chat(String prompt){
 return chatClient.prompt()
 .user(prompt)
 .stream()
 .content();
 }
 }
 
 
 | 
会话日志/记忆

- 配置Advisor
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 
 | @Configurationpublic class CommonConfiguration {
 
 
 @Bean
 public ChatMemory chatMemory(){
 
 return new InMemoryChatMemory();
 }
 
 
 @Bean
 public ChatClient chatClient(OpenAiChatModel model, ChatMemory chatMemory){
 return ChatClient
 .builder(model)
 .defaultAdvisors(
 new MessageChatMemoryAdvisor(chatMemory),
 new SimpleLoggerAdvisor()
 )
 .defaultSystem("你是一个可爱的AI助手,名字叫帆帆,你要热心回答用户的问题")
 .build();
 }
 }
 
 
 | 
- 在对话回复API中加入会话ID
| 12
 3
 4
 5
 6
 7
 8
 9
 
 | @RequestMapping(value = "/chat",produces = "text/html;charset=utf-8")
 public Flux<String> chat(String prompt,String chatId){
 return chatClient.prompt()
 .user(prompt)
 .advisors(a -> a.param(CHAT_MEMORY_CONVERSATION_ID_KEY,chatId))
 .stream()
 .content();
 }
 
 | 
会话历史
会话历史其实保存在InMemoryChatMemory,但是他包含其他不需要的消息类型,需要过滤处理

| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 
 | @Datapublic class MessageVo {
 private String role;
 private String content;
 
 
 public MessageVo(Message message) {
 switch (message.getMessageType()) {
 case USER:
 this.role = "user";break;
 case ASSISTANT:
 this.role = "assistant";break;
 default:
 this.role = "";break;
 }
 this.content = message.getText();
 }
 }
 
 
 | 
| 12
 3
 4
 5
 
 | @GetMapping("/{type}/{chatId}")public List<MessageVo> getHistoryChat(@PathVariable String type, @PathVariable String chatId){
 List<Message> messages = chatMemory.get(chatId, Integer.MAX_VALUE);
 return messages.stream().map(MessageVo::new).toList();
 }
 
 | 
SDK
| 12
 3
 4
 5
 6
 7
 8
 9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 
 | import java.util.ArrayList;import java.util.Arrays;
 import java.util.Collections;
 import java.util.List;
 import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversation;
 import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationParam;
 import com.alibaba.dashscope.aigc.multimodalconversation.MultiModalConversationResult;
 import com.alibaba.dashscope.common.MultiModalMessage;
 import com.alibaba.dashscope.common.Role;
 import com.alibaba.dashscope.exception.ApiException;
 import com.alibaba.dashscope.exception.NoApiKeyException;
 import com.alibaba.dashscope.exception.UploadFileException;
 import com.alibaba.dashscope.utils.JsonUtils;
 
 public class Main {
 private static final String modelName = "qwen-audio-turbo-latest";
 public static void MultiRoundConversationCall() throws ApiException, NoApiKeyException, UploadFileException {
 MultiModalConversation conv = new MultiModalConversation();
 MultiModalMessage systemMessage = MultiModalMessage.builder().role(Role.SYSTEM.getValue())
 .content(Arrays.asList(Collections.singletonMap("text", "You are a helpful assistant."))).build();
 MultiModalMessage userMessage = MultiModalMessage.builder().role(Role.USER.getValue())
 .content(Arrays.asList(Collections.singletonMap("audio", "https://dashscope.oss-cn-beijing.aliyuncs.com/audios/welcome.mp3"),
 Collections.singletonMap("text", "这段音频在说什么?"))).build();
 List<MultiModalMessage> messages = new ArrayList<>();
 messages.add(systemMessage);
 messages.add(userMessage);
 MultiModalConversationParam param = MultiModalConversationParam.builder()
 .model(modelName)
 .messages(messages)
 .build();
 MultiModalConversationResult result = conv.call(param);
 System.out.println("第一轮回复:"+JsonUtils.toJson(result));
 
 messages.add(result.getOutput().getChoices().get(0).getMessage());
 MultiModalMessage msg = MultiModalMessage.builder().role(Role.USER.getValue())
 .content(Arrays.asList(Collections.singletonMap("text", "简单介绍这家公司。"))).build();
 messages.add(msg);
 
 param.setMessages((List)messages);
 result = conv.call(param);
 System.out.println("第二轮回复:"+JsonUtils.toJson(result));
 }
 public static void main(String[] args) {
 try {
 MultiRoundConversationCall();
 } catch (ApiException | NoApiKeyException | UploadFileException e) {
 System.out.println(e.getMessage());
 }
 System.exit(0);
 }
 }
 
 | 
FuctionCall

Tool 主要用于:
- 信息检索。此类别中的工具可用于从外部源(如数据库、Web 服务、文件系统或 Web 搜索引擎)检索信息。目标是增强模型的知识,使其能够回答其他方式无法回答的问题。因此,它们可用于检索增强生成 (RAG) 方案。例如,工具可用于检索给定位置的当前天气、检索最新的新闻文章或查询数据库以获取特定记录。
- 采取行动。此类别中的工具可用于在软件系统中执行作,例如发送电子邮件、在数据库中创建新记录、提交表单或触发工作流。目标是自动执行原本需要人工干预或显式编程的任务。例如,可以使用工具为与聊天机器人交互的客户预订航班,在网页上填写表单,或在代码生成场景中实现基于自动测试 (TDD) 的 Java 类。
重要参数
- returnDirect:默认为false,开启时AI Model识别调用tool的结果将直接返回给客户端,而不是给AI Model进行处理返回

MCP
核心特点

五大功能


RAG
大模型学习文档内容
与其功能类似的还有:知识图谱

RAG通过学习过的文档数据库提取出问题的部分答案(context),将其与用户的问题一并发给大语言模型。大语言模型就会遵循context来规范输出的答案,避免幻觉的产生。回答也会参考文档向量数据库的内容
相当于把答案告诉AI,让他做开卷考试
缺点:
- 检索精度不高:基于相似度会检索出无关内容,大模型仅仅只有总结的作用
- 多轮检索能力弱
- 缺乏大局观

缺陷
- 仅仅起到文本总结作用,推理能力弱:RAG的支持能力也很考验大模型的长文本理解能力 
- 用户查询与知识库文本的语义偏差导致检索到无关或低质量文档 - 
- 用户搜索苹果手机,但是可能会搜出水果 
 
- 知识边界限制 
优化思路
索引层面
- 拆分更小的chunks:检索时避免检索出来更多无关内容,减少幻觉;缺点是检索速度较慢√


- 对chunks的摘要进行向量存储:避免文本块多余信息或用户提问中其他无关细节的影响;缺点是减少了文本块细节
