SpringBoot封裝AI模組,快速實現智慧化!

👉 這是一個或許對你有用的社群
🐱 一對一交流/面試小冊/簡歷最佳化/求職解惑,歡迎加入芋道快速開發平臺知識星球。下面是星球提供的部分資料:
👉這是一個或許對你有用的開源專案
國產 Star 破 10w+ 的開源專案,前端包括管理後臺 + 微信小程式,後端支援單體和微服務架構。
功能涵蓋 RBAC 許可權、SaaS 多租戶、資料許可權、商城、支付、工作流、大屏報表、微信公眾號、ERPCRMAI 大模型等等功能:
  • Boot 多模組架構:https://gitee.com/zhijiantianya/ruoyi-vue-pro
  • Cloud 微服務架構:https://gitee.com/zhijiantianya/yudao-cloud
  • 影片教程:https://doc.iocoder.cn
【國內首批】支援 JDK 17/21 + SpringBoot 3.3、JDK 8/11 + Spring Boot 2.7 雙版本 

國內支援SDK呼叫的優秀開源AI平臺
  • 智譜AI(ZhipuAI): 智譜AI是一家專注於大模型技術的公司,由清華大學計算機系知識工程實驗室技術成果轉化而來。智譜AI提供了包括對話模型、視覺模型、程式碼生成模型等多種AI模型,並提供了開放平臺供開發者使用和整合。智譜AI的SDK可以用於快速整合其AI能力,如對話、影像識別等功能。
  • 百度飛槳(PaddlePaddle): 百度飛槳是中國首個開源深度學習平臺,提供豐富的API和SDK,支援多種深度學習模型的開發和部署。
  • 騰訊AI Lab: 騰訊AI Lab提供了多種AI技術和服務,包括計算機視覺、語音識別、自然語言處理等領域的SDK和API。
  • 阿里雲機器學習平臺PAI: 阿里雲提供的機器學習平臺PAI支援多種機器學習演算法和模型,提供了SDK供開發者呼叫。
  • 華為ModelArts: 華為雲ModelArts是一個全流程模型生產服務,提供豐富的API和SDK,支援模型的訓練、部署和管理。
註釋:本文以智譜AI為例,其他開源AI平臺同理

匯入依賴

<dependency>
<groupId>

cn.bigmodel.openapi

</groupId>
<artifactId>

oapi-java-sdk

</artifactId>
<version>

release-V4-2.3.0

</version>
</dependency>

基於 Spring Boot + MyBatis Plus + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/ruoyi-vue-pro
  • 影片教程:https://doc.iocoder.cn/video/

獲取API key(注意保密)

官網的個人中心,找到專案管理下的API keys。
基於 Spring Cloud Alibaba + Gateway + Nacos + RocketMQ + Vue & Element 實現的後臺管理系統 + 使用者小程式,支援 RBAC 動態許可權、多租戶、資料許可權、工作流、三方登入、支付、簡訊、商城等功能
  • 專案地址:https://github.com/YunaiV/yudao-cloud
  • 影片教程:https://doc.iocoder.cn/video/

測試Demo

測試是否呼叫AI成功,注意API key要換成自己的。
@SpringBootTest
publicclassZhiPuAiTest

{

@Test
publicvoidtest()

{

        String apiKey = 

"自己的apikey"

;

// 建立客戶端

        ClientV4 client = 

new

 ClientV4.Builder(apiKey).build();

// 構造請求

        List<ChatMessage> messages = 

new

 ArrayList<>();

        ChatMessage chatMessage = 

new

 ChatMessage(ChatMessageRole.USER.value(), 

"作為一名營銷專家,請為智譜開放平臺創作一個吸引人的slogan"

);

        messages.add(chatMessage);

        String requestId = String.valueOf(System.currentTimeMillis());

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()

                .model(Constants.ModelChatGLM4)

                .stream(Boolean.FALSE)

                .invokeMethod(Constants.invokeMethod)

                .messages(messages)

                .requestId(requestId)

                .build();

// 呼叫

        ModelApiResponse invokeModelApiResp = client.invokeModelApi(chatCompletionRequest);

        System.out.println(

"model output:"

 + invokeModelApiResp.getMsg());

    }

}

封裝通用AI模組

application.yml配置API key

#  ai 配置
ai:
api-key:自己的key

定義AI配置類

@Configuration
@ConfigurationProperties

(prefix = 

"ai"

)

@Data
publicclassAiConfig

{

/**

     * apiKey

     */

private

 String apiKey;

@Bean
public ClientV4 getClientV4()

{

returnnew

 ClientV4.Builder(apiKey).build();

    }

}

封裝通用的AI請求模組

AiManager類提供了多種方法來執行同步和流式請求,包括穩定和不穩定答案的同步請求,以及可以根據隨機數溫度引數自定義的同步請求。這些方法允許以簡化的方式傳遞系統和使用者訊息,或者直接傳遞一個訊息列表。

/**

 * 通用 AI 呼叫能力

 */


@Component
publicclassAiManager

{

@Resource
private

 ClientV4 clientV4;

// 穩定的隨機數
privatestaticfinalfloat

 STABLE_TEMPERATURE = 

0.05f

;

// 不穩定的隨機數
privatestaticfinalfloat

 UNSTABLE_TEMPERATURE = 

0.99f

;

/**

     * 同步請求(答案不穩定)

     *

     * 

@param

 systemMessage

     * 

@param

 userMessage

     * 

@return

     */


public String doSyncUnstableRequest(String systemMessage, String userMessage)

{

return

 doRequest(systemMessage, userMessage, Boolean.FALSE, UNSTABLE_TEMPERATURE);

    }

/**

     * 同步請求(答案較穩定)

     *

     * 

@param

 systemMessage

     * 

@param

 userMessage

     * 

@return

     */


public String doSyncStableRequest(String systemMessage, String userMessage)

{

return

 doRequest(systemMessage, userMessage, Boolean.FALSE, STABLE_TEMPERATURE);

    }

/**

     * 同步請求

     *

     * 

@param

 systemMessage

     * 

@param

 userMessage

     * 

@param

 temperature

     * 

@return

     */


public String doSyncRequest(String systemMessage, String userMessage, Float temperature)

{

return

 doRequest(systemMessage, userMessage, Boolean.FALSE, temperature);

    }

/**

     * 通用請求(簡化訊息傳遞)

     *

     * 

@param

 systemMessage

     * 

@param

 userMessage

     * 

@param

 stream

     * 

@param

 temperature

     * 

@return

     */


public String doRequest(String systemMessage, String userMessage, Boolean stream, Float temperature)

{

        List<ChatMessage> chatMessageList = 

new

 ArrayList<>();

        ChatMessage systemChatMessage = 

new

 ChatMessage(ChatMessageRole.SYSTEM.value(), systemMessage);

        chatMessageList.add(systemChatMessage);

        ChatMessage userChatMessage = 

new

 ChatMessage(ChatMessageRole.USER.value(), userMessage);

        chatMessageList.add(userChatMessage);

return

 doRequest(chatMessageList, stream, temperature);

    }

/**

     * 通用請求

     *

     * 

@param

 messages

     * 

@param

 stream

     * 

@param

 temperature

     * 

@return

     */


public String doRequest(List<ChatMessage> messages, Boolean stream, Float temperature)

{

// 構建請求

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()

                .model(Constants.ModelChatGLM4)

                .stream(stream)

                .temperature(temperature)

                .invokeMethod(Constants.invokeMethod)

                .messages(messages)

                .build();

try

 {

            ModelApiResponse invokeModelApiResp = clientV4.invokeModelApi(chatCompletionRequest);

return

 invokeModelApiResp.getData().getChoices().get(

0

).toString();

        } 

catch

 (Exception e) {

            e.printStackTrace();

thrownew

 BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());

        }

    }

/**

     * 通用流式請求(簡化訊息傳遞)

     *

     * 

@param

 systemMessage

     * 

@param

 userMessage

     * 

@param

 temperature

     * 

@return

     */


public Flowable<ModelData> doStreamRequest(String systemMessage, String userMessage, Float temperature)

{

        List<ChatMessage> chatMessageList = 

new

 ArrayList<>();

        ChatMessage systemChatMessage = 

new

 ChatMessage(ChatMessageRole.SYSTEM.value(), systemMessage);

        chatMessageList.add(systemChatMessage);

        ChatMessage userChatMessage = 

new

 ChatMessage(ChatMessageRole.USER.value(), userMessage);

        chatMessageList.add(userChatMessage);

return

 doStreamRequest(chatMessageList, temperature);

    }

/**

     * 通用流式請求

     *

     * 

@param

 messages

     * 

@param

 temperature

     * 

@return

     */


public Flowable<ModelData> doStreamRequest(List<ChatMessage> messages, Float temperature)

{

// 構建請求

        ChatCompletionRequest chatCompletionRequest = ChatCompletionRequest.builder()

                .model(Constants.ModelChatGLM4)

                .stream(Boolean.TRUE)

                .temperature(temperature)

                .invokeMethod(Constants.invokeMethod)

                .messages(messages)

                .build();

try

 {

            ModelApiResponse invokeModelApiResp = clientV4.invokeModelApi(chatCompletionRequest);

return

 invokeModelApiResp.getFlowable();

        } 

catch

 (Exception e) {

            e.printStackTrace();

thrownew

 BusinessException(ErrorCode.SYSTEM_ERROR, e.getMessage());

        }

    }

}

使用AI賦能專案

設計Prompt的常用技巧

Prompt是一種向語言模型提供輸入的方法,它透過特定的提示或指令引導模型生成預期的輸出。在自然語言處理中,簡而言之,Prompt是一種高效利用語言模型能力的技術手段。
  • 技巧一  定義 System Prompt
用於設定AI助手行為模式的工具,包括角色設定、語言風格、任務模式和針對特定問題的具體行為指導。
示例:
你擅長從文字中提取關鍵資訊,精確、資料驅動,重點突出關鍵資訊,根據使用者提供的文字片段提取關鍵資料和事實,將提取的資訊以清晰的 JSON 格式呈現。
  • 技巧二  讓 AI 進行角色扮演
讓 AI 扮演角色、可以更準確地模仿該角色的行為和對話方式。
示例:
作為一個量子物理學家,解釋量子物理學的基本原理,並簡要介紹其在現代科技中的應用。
  • 技巧三  提供具體的細節要求
在 Prompt 中新增要求模型輸出內容的細節和背景資訊。
示例:
我對太陽系的行星非常感興趣,特別是土星。請提供關於土星的基本資訊,包括其大小、組成、環系統和任何獨特的天文現象。
  • 技巧四  使用分隔符標示不同的輸入部分
示例:
請基於以下內容:
""" 要總結的文章內容"""
提煉核心觀點和綱要
  • 技巧五  思維鏈提示
要求模型分步驟解答問題,還要求其展示其推理過程的每個步驟。透過這種方式,可以減少不準確結果的可能性,並使使用者更容易評估模型的響應。
示例:
作為一個 AI 助手,你的任務是幫助使用者解決複雜的數學問題。對於每個問題,你需要首先獨立解決它,然後比較和評估使用者的答案,並最終提供反饋。在這個過程中,請展示你的每一步推理過程。我有一個數學問題需要幫助:"""問題是:一個農場有雞和牛共 35 頭,腳總共有 94 只。雞和牛各有多少頭?我的答案是雞有 23 頭,牛有 12 頭"""。
  • 技巧六  少樣本學習
可以作為進行少樣本學習的示例。這些樣本可以用來引導模型模仿特定的行為和語言風格。
模仿這種風格
1、三杯雞在鍋中歡躍,是歲月的篝火,是浪漫的樂章。
2、燉排骨的滋味,是冬日的棉被,是鄉土的迴響。
3、紅燒勤魚的鮮香,是海洋的密語,是大海的情書。
生成新的句子。

專案中呼叫AI(實戰)

  • 定義Prompt常量
參考上文設計Prompt的常用技巧,根據自己的業務需求設計Prompt,示例程式碼是需要AI生成問卷題目,僅供參考。
// AI Prompt
privatestaticfinal

 String GENERATE_QUESTION_SYSTEM_MESSAGE = 

"你是一位嚴謹的出題專家,我會給你如下資訊:\n"

 +

"```\n"

 +

"應用名稱,\n"

 +

"【【【應用描述】】】,\n"

 +

"應用類別,\n"

 +

"要生成的題目數,\n"

 +

"每個題目的選項數\n"

 +

"```\n"

 +

"\n"

 +

"請你根據上述資訊,按照以下步驟來出題:\n"

 +

"1. 要求:題目和選項儘可能地短,題目不要包含序號,每題的選項數以我提供的為主,題目不能重複\n"

 +

"2. 嚴格按照下面的 json 格式輸出題目和選項\n"

 +

"```\n"

 +

"[{\"options\":[{\"value\":\"選項內容\",\"key\":\"A\"},{\"value\":\"\",\"key\":\"B\"}],\"title\":\"題目標題\"}]\n"

 +

"```\n"

 +

"title 是題目,options 是選項,每個選項的 key 按照英文字母序(比如 A、B、C、D)以此類推,value 是選項內容\n"

 +

"3. 檢查題目是否包含序號,若包含序號則去除序號\n"

 +

"4. 返回的題目列表格式必須為 JSON 陣列"

;

  • 業務邏輯中呼叫AI
呼叫AI,使用定義好的Prompt生成題目
// AI 生成

String result = aiManager.doSyncRequest(GENERATE_QUESTION_SYSTEM_MESSAGE, userMessage, 

null

);

完整程式碼

/**

 * 生成題目的使用者訊息

 *

 * 

@param

 app

 * 

@param

 questionNumber

 * 

@param

 optionNumber

 * 

@return

 */


private String getGenerateQuestionUserMessage(App app, int questionNumber, int optionNumber)

{

    StringBuilder userMessage = 

new

 StringBuilder();

    userMessage.append(app.getAppName()).append(

"\n"

);

    userMessage.append(app.getAppDesc()).append(

"\n"

);

    userMessage.append(AppTypeEnum.getEnumByValue(app.getAppType()).getText() + 

"類"

).append(

"\n"

);

    userMessage.append(questionNumber).append(

"\n"

);

    userMessage.append(optionNumber);

return

 userMessage.toString();

}

@PostMapping

(

"/ai_generate"

)

public

 BaseResponse<List<QuestionContentDTO>> aiGenerateQuestion(

@RequestBody

 AiGenerateQuestionRequest aiGenerateQuestionRequest) {

    ThrowUtils.throwIf(aiGenerateQuestionRequest == 

null

, ErrorCode.PARAMS_ERROR);

// 獲取引數

    Long appId = aiGenerateQuestionRequest.getAppId();

int

 questionNumber = aiGenerateQuestionRequest.getQuestionNumber();

int

 optionNumber = aiGenerateQuestionRequest.getOptionNumber();

// 獲取應用資訊

    App app = appService.getById(appId);

    ThrowUtils.throwIf(app == 

null

, ErrorCode.NOT_FOUND_ERROR);

// 封裝 Prompt

    String userMessage = getGenerateQuestionUserMessage(app, questionNumber, optionNumber);

// AI 生成

    String result = aiManager.doSyncRequest(GENERATE_QUESTION_SYSTEM_MESSAGE, userMessage, 

null

);

// 擷取需要的 JSON 資訊
int

 start = result.indexOf(

"["

);

int

 end = result.lastIndexOf(

"]"

);

    String json = result.substring(start, end + 

1

);

    List<QuestionContentDTO> questionContentDTOList = JSONUtil.toList(json, QuestionContentDTO

.class)

;

return

 ResultUtils.success(questionContentDTOList);

}


歡迎加入我的知識星球,全面提升技術能力。
👉 加入方式,長按”或“掃描”下方二維碼噢
星球的內容包括:專案實戰、面試招聘、原始碼解析、學習路線。
文章有幫助的話,在看,轉發吧。
謝謝支援喲 (*^__^*)

相關文章