feat(ai): 新增多模态与结构化输出功能支持
- 引入 Cassandra作为聊天记忆存储后端 - 配置 DashScope 多模态模型支持图文输入- 新增结构化输出控制器,支持 Bean、Map、List 等格式转换 - 添加文生图接口,集成阿里百炼图像生成能力 - 更新应用配置以支持多模态及持久化聊天记录 - 升级依赖项,引入 DashScope SDK 和 Cassandra 支持库 - 创建 ActorFilmography 和 Book 数据模型用于结构化响应 - 调整 ChatClient 配置以适配新的多模态与记忆逻辑
This commit is contained in:
@@ -0,0 +1,127 @@
|
||||
package com.hanserwei.airobot.controller;
|
||||
|
||||
import com.hanserwei.airobot.model.ActorFilmography;
|
||||
import com.hanserwei.airobot.model.Book;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.ai.chat.client.ChatClient;
|
||||
import org.springframework.ai.chat.prompt.Prompt;
|
||||
import org.springframework.ai.chat.prompt.PromptTemplate;
|
||||
import org.springframework.ai.converter.BeanOutputConverter;
|
||||
import org.springframework.ai.converter.ListOutputConverter;
|
||||
import org.springframework.ai.converter.MapOutputConverter;
|
||||
import org.springframework.core.convert.support.DefaultConversionService;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RequestParam;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@RestController
|
||||
@RequestMapping("/v8/ai")
|
||||
public class StructuredOutputController {
|
||||
|
||||
@Resource
|
||||
private ChatClient chatClient;
|
||||
|
||||
/**
|
||||
* 示例1: BeanOutputConverter - 获取演员电影作品集
|
||||
*
|
||||
* @param name
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/actor/films")
|
||||
public ActorFilmography generate(@RequestParam(value = "name") String name) {
|
||||
// 一次性返回结果
|
||||
return chatClient.prompt()
|
||||
.user(u -> u.text("""
|
||||
请为演员 {actor} 生成包含5部代表作的电影作品集,
|
||||
只包含 {actor} 担任主演的电影,不要包含任何解释说明。
|
||||
""")
|
||||
.param("actor", name))
|
||||
.call()
|
||||
.entity(ActorFilmography.class);
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例2: MapOutputConverter - 获取编程语言信息
|
||||
* @param language
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/language-info")
|
||||
public Map<String, Object> getLanguageInfo(@RequestParam(value = "lang") String language) {
|
||||
|
||||
String userText = """
|
||||
请提供关于编程语言 {language} 的结构化信息,包含以下字段:"
|
||||
name (语言名称), "
|
||||
popularity (流行度排名,整数), "
|
||||
features (主要特性,字符串数组), "
|
||||
releaseYear (首次发布年份). "
|
||||
不要包含任何解释说明,直接输出 JSON 格式数据。
|
||||
""";
|
||||
|
||||
return chatClient.prompt()
|
||||
.user(u -> u.text(userText).param("language", language))
|
||||
.call()
|
||||
.entity(new MapOutputConverter());
|
||||
}
|
||||
|
||||
/**
|
||||
* 示例3: ListOutputConverter - 获取城市列表
|
||||
* @param country
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/city-list")
|
||||
public List<String> getCityList(@RequestParam(value = "country") String country) {
|
||||
|
||||
return chatClient.prompt()
|
||||
.user(u -> u.text(
|
||||
"""
|
||||
列出 {country} 的8个主要城市名称。
|
||||
不要包含任何编号、解释或其他文本,直接输出城市名称列表。
|
||||
""")
|
||||
.param("country", country))
|
||||
.call()
|
||||
.entity(new ListOutputConverter(new DefaultConversionService()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 使用低级 API 的 BeanOutputConverter - 获取书籍信息
|
||||
* @param bookTitle
|
||||
* @return
|
||||
*/
|
||||
@GetMapping("/book-info")
|
||||
public Book getBookInfo(@RequestParam(value = "name") String bookTitle) {
|
||||
|
||||
// 使用 BeanOutputConverter 定义输出格式
|
||||
BeanOutputConverter<Book> converter = new BeanOutputConverter<>(Book.class);
|
||||
|
||||
// 提示词模板
|
||||
String template = """
|
||||
请提供关于书籍《{bookTitle}》的详细信息:
|
||||
1. 作者姓名
|
||||
2. 出版年份
|
||||
3. 主要类型(数组)
|
||||
4. 书籍描述(不少于50字)
|
||||
|
||||
不要包含任何解释说明,直接按指定格式输出。
|
||||
{format}
|
||||
""";
|
||||
|
||||
// 创建 Prompt
|
||||
PromptTemplate promptTemplate = new PromptTemplate(template);
|
||||
Prompt prompt = promptTemplate.create(Map.of(
|
||||
"bookTitle", bookTitle,
|
||||
"format", converter.getFormat()
|
||||
));
|
||||
|
||||
// 调用模型并转换结果
|
||||
String result = chatClient.prompt(prompt)
|
||||
.call()
|
||||
.content();
|
||||
|
||||
// 结构化转换
|
||||
return converter.convert(result);
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user