編程新范式,當Spring Boot遇上OpenAI
2023年,AI技術(shù)已經(jīng)成為一個熱點話題,影響了許多領(lǐng)域,特別是編程領(lǐng)域。人們越來越意識到AI技術(shù)的重要性,包括Spring社區(qū)在內(nèi)。
隨著GenAI(I(General Artificial Intelligence))技術(shù)的不斷發(fā)展,簡化具有AI功能的應(yīng)用程序的創(chuàng)建成為一個非常重要的課題和迫切需求?!癝pring AI”就是在這種背景下誕生的,旨在簡化具有AI功能應(yīng)用程序的開發(fā),使其成為簡單直觀的過程,避免不必要的復雜性。
本文介紹Spring AI和使用Spring AI的一些提示工程技巧,幫助開發(fā)人員在使用Spring AI框架中時更好地構(gòu)建提示信息,以便利用好Spring AI的功能。
1 Spring AI介紹
Spring AI由M K Pavan Kumar創(chuàng)建和撰寫
Spring AI是一個旨在簡化AI應(yīng)用程序開發(fā)的項目,它借鑒了已知的Python項目LangChain和LlamaIndex的經(jīng)驗。然而,Spring AI不只是這些項目的復制品。Spring AI的核心理念是,未來的生成式AI應(yīng)用將擴展到各種編程語言的用戶群體,不再只局限于Python語言的愛好者。這意味著,開發(fā)人員無需專門學習Python語言就可以開發(fā)AI應(yīng)用,可以使用他們熟悉的語言來構(gòu)建AI應(yīng)用。
Spring AI的核心是提供構(gòu)建AI驅(qū)動應(yīng)用程序的基本構(gòu)建塊。這些構(gòu)建塊具有彈性,可以輕松交換組件,幾乎不需要對代碼進行任何修改。例如,Spring AI引入了兼容OpenAI和Azure OpenAI的ChatClient接口。
Spring AI的核心是為創(chuàng)建AI驅(qū)動的應(yīng)用程序提供基本的構(gòu)建塊。這些構(gòu)建塊具有彈性,允許組件的平滑交換,幾乎不需要對編碼進行任何修改。例如,Spring AI引入了兼容OpenAI和Azure OpenAI的ChatClient接口。
但Spring AI不僅僅是這些基本構(gòu)建塊,還關(guān)注提供更高級的解決方案,例如“關(guān)于自己文檔的問答”或“使用文檔進行交互式聊天”等典型場景。隨著應(yīng)用程序需求的增長,Spring AI計劃與Spring生態(tài)系統(tǒng)的其他部分密切合作,包括Spring Integration,Spring Batch和Spring Data等。
2 創(chuàng)建Spring Boot項目和編寫OpenAI控制器示例
先在IDE中生成Spring Boot項目,在application.properties文件中保留以下內(nèi)容:
spring.ai.openai.api-key=<YOUR\_OPENAI\_API\_KEY>
下面編寫名為OpenAIController.java的控制器:
package com.vas.springai.controller;
import org.springframework.ai.client.AiClient;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
@RestController
@RequestMapping("/api/v1")
public class OpenAIController {
private final AiClient aiClient;
public OpenAIController(AiClient aiClient) {
this.aiClient = aiClient;
}
}
3 使用Prompt類構(gòu)建提示信息
提示類是一個消息對象序列的結(jié)構(gòu)化持有者,每個消息都代表提示的一部分。這些消息在提示中扮演著不同的角色和目的,內(nèi)容也各不相同。包括用戶問題、AI生成的響應(yīng)以及相關(guān)上下文細節(jié)等等。這種設(shè)置有助于進行復雜和精細的人機交互,因為提示由多個具有特定功能的消息組成。
@GetMapping("/completion")
public String completion(@RequestParam(value = "message") String message){
return this.aiClient.generate(message);
}
然而,aiClient的generate方法并不僅僅接受純文本作為參數(shù),它也可以接受Prompt類的對象作為參數(shù),如下所示?,F(xiàn)在,這個方法返回的是AiResponse類型的實例,不是簡單的文本。
@GetMapping("/completion")
public AiResponse completion(@RequestParam(value = "message") String message){
PromptTemplate promptTemplate = new PromptTemplate("translate the given english sentence sentence into french {query}");
Prompt prompt = promptTemplate.create(Map.of("query", message));
return this.aiClient.generate(prompt);
}
此外,Prompt類還提供了一個重載的構(gòu)造函數(shù),可以接受不同角色和意圖的Message類型實例序列作為參數(shù)。這樣可以更好地組織和管理提示信息,方便后續(xù)的處理和使用。下面是一個示例代碼,展示了如何使用這個重載構(gòu)造函數(shù)來合并所有內(nèi)容。
package com.vas.springai.controller;
import org.springframework.ai.client.AiClient;
import org.springframework.ai.client.Generation;
import org.springframework.ai.prompt.Prompt;
import org.springframework.ai.prompt.PromptTemplate;
import org.springframework.ai.prompt.SystemPromptTemplate;
import org.springframework.ai.prompt.messages.Message;
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("/api/v1")
public class OpenAIController {
private final AiClient aiClient;
public OpenAIController(AiClient aiClient) {
this.aiClient = aiClient;
}
@GetMapping("/completion")
public List<Generation> completion(@RequestParam(value = "message") String message) {
String systemPrompt = """
You are a helpful AI assistant that helps people translate given text from english to french.
Your name is TranslatePro
You should reply to the user's request with your name and also in the style of a professional.
""";
SystemPromptTemplate systemPromptTemplate = new SystemPromptTemplate(systemPrompt);
Message systemMessage = systemPromptTemplate.createMessage();
PromptTemplate promptTemplate = new PromptTemplate("translate the given english sentence sentence into french {query}");
Message userMessage = promptTemplate.createMessage(Map.of("query", message));
Prompt prompt = new Prompt(List.of(systemMessage, userMessage));
return this.aiClient.generate(prompt).getGenerations();
}
}
4 測試應(yīng)用程序
可以使用市場上任何可用的開放工具來測試應(yīng)用程序,例如postman、insomnia和Httpie等等。