編程新范式,當(dāng)Spring Boot遇上OpenAI
2023年,AI技術(shù)已經(jīng)成為一個(gè)熱點(diǎn)話題,影響了許多領(lǐng)域,特別是編程領(lǐng)域。人們?cè)絹?lái)越意識(shí)到AI技術(shù)的重要性,包括Spring社區(qū)在內(nèi)。
隨著GenAI(I(General Artificial Intelligence))技術(shù)的不斷發(fā)展,簡(jiǎn)化具有AI功能的應(yīng)用程序的創(chuàng)建成為一個(gè)非常重要的課題和迫切需求?!癝pring AI”就是在這種背景下誕生的,旨在簡(jiǎn)化具有AI功能應(yīng)用程序的開(kāi)發(fā),使其成為簡(jiǎn)單直觀的過(guò)程,避免不必要的復(fù)雜性。
本文介紹Spring AI和使用Spring AI的一些提示工程技巧,幫助開(kāi)發(fā)人員在使用Spring AI框架中時(shí)更好地構(gòu)建提示信息,以便利用好Spring AI的功能。
1 Spring AI介紹
Spring AI由M K Pavan Kumar創(chuàng)建和撰寫
Spring AI是一個(gè)旨在簡(jiǎn)化AI應(yīng)用程序開(kāi)發(fā)的項(xiàng)目,它借鑒了已知的Python項(xiàng)目LangChain和LlamaIndex的經(jīng)驗(yàn)。然而,Spring AI不只是這些項(xiàng)目的復(fù)制品。Spring AI的核心理念是,未來(lái)的生成式AI應(yīng)用將擴(kuò)展到各種編程語(yǔ)言的用戶群體,不再只局限于Python語(yǔ)言的愛(ài)好者。這意味著,開(kāi)發(fā)人員無(wú)需專門學(xué)習(xí)Python語(yǔ)言就可以開(kāi)發(fā)AI應(yīng)用,可以使用他們熟悉的語(yǔ)言來(lái)構(gòu)建AI應(yīng)用。
Spring AI的核心是提供構(gòu)建AI驅(qū)動(dòng)應(yīng)用程序的基本構(gòu)建塊。這些構(gòu)建塊具有彈性,可以輕松交換組件,幾乎不需要對(duì)代碼進(jìn)行任何修改。例如,Spring AI引入了兼容OpenAI和Azure OpenAI的ChatClient接口。
Spring AI的核心是為創(chuàng)建AI驅(qū)動(dòng)的應(yīng)用程序提供基本的構(gòu)建塊。這些構(gòu)建塊具有彈性,允許組件的平滑交換,幾乎不需要對(duì)編碼進(jìn)行任何修改。例如,Spring AI引入了兼容OpenAI和Azure OpenAI的ChatClient接口。
但Spring AI不僅僅是這些基本構(gòu)建塊,還關(guān)注提供更高級(jí)的解決方案,例如“關(guān)于自己文檔的問(wèn)答”或“使用文檔進(jìn)行交互式聊天”等典型場(chǎng)景。隨著應(yīng)用程序需求的增長(zhǎng),Spring AI計(jì)劃與Spring生態(tài)系統(tǒng)的其他部分密切合作,包括Spring Integration,Spring Batch和Spring Data等。
2 創(chuàng)建Spring Boot項(xiàng)目和編寫OpenAI控制器示例
先在IDE中生成Spring Boot項(xiàng)目,在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)建提示信息
提示類是一個(gè)消息對(duì)象序列的結(jié)構(gòu)化持有者,每個(gè)消息都代表提示的一部分。這些消息在提示中扮演著不同的角色和目的,內(nèi)容也各不相同。包括用戶問(wèn)題、AI生成的響應(yīng)以及相關(guān)上下文細(xì)節(jié)等等。這種設(shè)置有助于進(jìn)行復(fù)雜和精細(xì)的人機(jī)交互,因?yàn)樘崾居啥鄠€(gè)具有特定功能的消息組成。
@GetMapping("/completion")
public String completion(@RequestParam(value = "message") String message){
return this.aiClient.generate(message);
}
然而,aiClient的generate方法并不僅僅接受純文本作為參數(shù),它也可以接受Prompt類的對(duì)象作為參數(shù),如下所示?,F(xiàn)在,這個(gè)方法返回的是AiResponse類型的實(shí)例,不是簡(jiǎn)單的文本。
@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è)重載的構(gòu)造函數(shù),可以接受不同角色和意圖的Message類型實(shí)例序列作為參數(shù)。這樣可以更好地組織和管理提示信息,方便后續(xù)的處理和使用。下面是一個(gè)示例代碼,展示了如何使用這個(gè)重載構(gòu)造函數(shù)來(lái)合并所有內(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 測(cè)試應(yīng)用程序
可以使用市場(chǎng)上任何可用的開(kāi)放工具來(lái)測(cè)試應(yīng)用程序,例如postman、insomnia和Httpie等等。