官方文檔https://docs.spring.io/spring-ai/reference/api/vectordbs.html
以使用ollama為例
ollama基本命令
ollama 列出所有命令
ollama pull model_name:version 下載模型
ollama list 查看已下載模型列表
ollama show model_name:version 查看模型元數據
ollama re model_name:version 刪除模型
ollama ps 查看正在運行的模型
ollama run model_name 啟動模型
瀏覽器查看模型元數據列表
模型ymal配置項模板
spring:
data:
redis:
url: redis://localhost:6379
ai:
ollama:
base-url: localhost:11434
chat:
options:
model: moondream:latest
temperature: 0.8
init:
pull-model-strategy: never
embedding:
enabled: true
model: mxbai-embed-large
vectorstore:
redis:
index: my-index
prefix: customer-history
initialize-schema: true
model注入模板
@Autowired
private OllamaChatModel ollamaChatModel;
@Autowired
private OllamaEmbeddingModel ollamaEmbeddingModel;
@Autowired
private RedisVectorStore vectorStore;
響應式識別圖片 使用advisor、vector-store、tools 模板
//ARG記憶檢索向量數據庫 顧問
VectorStoreChatMemoryAdvisor vectorMemoryAdvisor =
VectorStoreChatMemoryAdvisor.builder(vectorStore).build();
//執行日志 顧問
SimpleLoggerAdvisor loggerAdvisor = new SimpleLoggerAdvisor();
//解析圖片輸入
UserMessage userMessage = new UserMessage(message,
new Media(MimeTypeUtils.IMAGE_JPEG, imageFile.getResource()));
ChatClient chatClient = ChatClient.builder(this.ollamaChatModel).build();
return chatClient.prompt(new Prompt(userMessage))
.advisors(List.of(vectorMemoryAdvisor, loggerAdvisor))
.system("你是一個圖片識別專家,可以識別任何圖片并描述內容")
.user(message)
.tools(new MyTool())
.stream()
.content();
vector-store 自定義配置模板
@Bean
public JedisPooled jedisPooled() {
return new JedisPooled("localhost", 6379);
}
@Bean
public VectorStore vectorStore(JedisPooled jedisPooled, EmbeddingModel embeddingModel) {
return RedisVectorStore.builder(jedisPooled, embeddingModel)
.indexName("custom-index") // Optional: defaults to "spring-ai-index"
.prefix("custom-prefix") // Optional: defaults to "embedding:"
.metadataFields( // Optional: define metadata fields for filtering
MetadataField.tag("country"),
MetadataField.numeric("year"))
.initializeSchema(true) // Optional: defaults to false
.batchingStrategy(new TokenCountBatchingStrategy()) // Optional: defaults to TokenCountBatchingStrategy
.build();
}
vector-store 使用模板
// 存儲
Document documentV1 = new Document(
"AI and Machine Learning Best Practices",
Map.of(
"docId", "AIML-001",
"version", "1.0",
"lastUpdated", "2024-01-01"
)
);
Document documentV2 = new Document(
"AI and Machine Learning Best Practices - Updated",
Map.of(
"docId", "AIML-001",
"version", "2.0",
"lastUpdated", "2024-02-01"
)
);
vectorStore.add(List.of(documentV1,documentV2));
// 查詢
SearchRequest request = SearchRequest.builder()
.query("AI and Machine Learning")
.filterExpression("docId == 'AIML-001'")
.build();
List<Document> results = vectorStore.similaritySearch(request);
//刪除
Filter.Expression expression1 = new Filter
.Expression(Filter.ExpressionType.EQ
, new Filter.Key("docId"), new Filter.Value("AIML-001"));
Filter.Expression expression2 = new Filter
.Expression(Filter.ExpressionType.EQ
, new Filter.Key("version"), new Filter.Value("1.0"));
Filter.Expression deleteOldVersion = new Filter
.Expression(Filter.ExpressionType.AND, expression1, expression2);
vectorStore.delete(deleteOldVersion);
vectorStore.delete("docId == 'AIML-001' AND version == '1.0'");
vectorStore.delete("key == 'value'");
RAG(檢索增強)
org.springframework.ai.chat.client.advisor.RetrievalAugmentationAdvisor
使用vector-store之前 => 對用戶輸入優化、分解、翻譯、附加上下文
使用vector-store之后 => 對結果排名、壓縮、篩選
官方文檔https://docs.spring.io/spring-ai/reference/api/retrieval-augmented-generation.html
ETL(提取、轉化、加載 )主要定義接口
//提取(pdf、doc、markdown、html、json)
public interface DocumentReader extends Supplier<List<Document>> {
default List<Document> read() {
return get();
}
}
//轉化(文本過長分塊、提取關鍵字寫進元數據、生成摘要、填充模板)
public interface DocumentTransformer extends Function<List<Document>, List<Document>> {
default List<Document> transform(List<Document> transform) {
return apply(transform);
}
}
//主要是利用vertor-store的實現去存儲數據
public interface DocumentWriter extends Consumer<List<Document>> {
default void write(List<Document> documents) {
accept(documents);
}
}
promptTmeplate 模板
PromptTemplate promptTemplate = new PromptTemplate("Tell me a {adjective} joke about {topic}");
Prompt prompt = promptTemplate.create(Map.of("adjective", adjective, "topic", topic));
return chatClient.call(prompt).getResult();
響應評估(evaluation)
@FunctionalInterface
public interface Evaluator {
EvaluationResponse evaluate(EvaluationRequest evaluationRequest);
}
//內置實現類 RelevancyEvaluator FactCheckingEvaluator
void testEvaluation() {
String userText = "What is the purpose of Carina?";
ChatResponse response = ChatClient.builder(chatModel)
.build().prompt()
.advisors(new QuestionAnswerAdvisor(vectorStore))
.user(userText)
.call()
.chatResponse();
String responseContent = response.getResult().getOutput().getContent();
RelevancyEvaluator relevancyEvaluator = new RelevancyEvaluator(ChatClient.builder(chatModel));
EvaluationRequest evaluationRequest = new EvaluationRequest(userText,
(List<Content>) response.getMetadata().get(QuestionAnswerAdvisor.RETRIEVED_DOCUMENTS), responseContent);
EvaluationResponse evaluationResponse = relevancyEvaluator.evaluate(evaluationRequest);
assertTrue(evaluationResponse.isPass(), "Response is not relevant to the question");
}
tools模板
public class MyTool {
@Tool(description = "Get the current date and time in the user's timezone")
String getCurrentDateTime() {
return LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
}
}
類型模板
MessageType 用來表示不同身份(user、system、assistant、tool)
MimeType 用來表示內容類型(img、text、json、octet-stream)