SpringAI入門及淺實踐,實戰 Spring? AI 調用大模型、提示詞工程、對話記憶、Adv?isor 的使用

上一次寫AI學習筆記已經好久之前了,溫習溫習,這一章講講關于Spring? AI 調用大模型、對話記憶、Adv?isor、結構化輸出、自定義對話記憶?、Prompt 模板的相關知識點。

快速跳轉到你感興趣的地方

  • 一、提示詞工程(Prompt)
    • 1. 基本概念 (提示詞、提示詞工程)
    • 2. 分類 (基于角色、功能)
    • 3. Prompt 優化技巧
  • 二、對話記憶(多輪對話實現)
    • 1. 使用 Chat Client 實現基礎對話功能
    • 2. Advisor 顧問的使用
  • 三、SpringAI會話記憶、Advisor實戰
    • 1. 使用 InMemoryChatMemory:內存存儲 實現對話記憶
    • 2. 自定義Advisor的使用
    • 3. 使用自定義 Advisor 實現自定義日志 Advisor
  • 四、結語(會不斷補充,可以收藏一下)

一、提示詞工程(Prompt)

1. 基本概念 (提示詞、提示詞工程)

提示詞就是用戶輸入給AI的指令,但是寫好提示詞,是一件十分不容易的事情。準確的提示詞能夠讓AI清楚的明白你所要達到的目的,從而生成滿意的內容。
提示詞工程就是通過優化輸入給AI模型的指令或問題(即“提示詞”),以提升模型輸出的準確性和相關性。其核心在于理解模型的行為模式,并通過結構化語言引導模型生成更符合預期的結果。

2. 分類 (基于角色、功能)

按照角色來分類可以分為如下三類:

  • 用戶 Prompt
    是用戶直接向 AI 提出的具體需求或問題,例如請求寫詩、解答問題或生成代碼。其核心是傳遞用戶的具體意圖,要求 AI 執行明確的任務。
  • 系統 Prompt
    是開發者或平臺設定的隱藏指令,用于定義 AI 的角色、行為邊界和回答風格。它不直接面向用戶,但決定了 AI 如何響應用戶 Prompt。例如,設定 AI 為“專業詩人”或“情感顧問”會直接影響生成內容的專業性、語氣和結構。
  • 助手 Prompt
    在多輪對話中,助手 Prompt(即 AI 的歷史回復)會成為后續交互的上下文。預設的助手消息能引導對話方向,例如在客服場景中提前聲明服務范圍。這種機制增強了對話連貫性,但也需注意避免因歷史信息導致回答偏差。

按照功能來分可以分為:

  • 指令型提?示詞: 明確告訴 AI? 模型需要執行的任務,?通常以命令式語句開頭。
將上述中文文本翻譯為英文
  • 對話型?提示詞: 模擬?自然對話,以問答形式?與 AI 模型交互。
你認為AI會在取代人類嗎?
  • 創意型?提示詞 引導 AI 模型?進行創意內容生成,如?故事、詩歌、廣告文案等。
寫一首描寫愛情的詩歌,贊美矢志不渝偉大的愛情
  • 角色扮?演提示詞 ?讓 AI 扮演特定?角色或人物進行回答。
你是一位使用Java的程序員,使用java編寫一個貪吃蛇游戲
  • 少樣本?學習提示詞 提供一些示例?,引導 AI 理解所?需的輸出格式和風格。
將以下句子改寫為正式商務語言:
示例1:
原句:這個想法不錯。
改寫:該提案展現了相當的潛力和創新性。示例2:
原句:我們明天見。
改寫:期待明日與您會面,繼續我們的商務討論。現在請改寫:這個價格太高了。

3. Prompt 優化技巧

網上和 Pro?mpt 優化相關的資源非常豐富,幾乎各大主流 AI ?大模型和 AI 開發框架官?方文檔都有相關的介紹。Spring AI 提示工程指南,智譜 AI Prompt 設計指南等等
這里講講我學習整理后的一些心得

這是springAI的提示詞編寫教程中的重點,其實重點在三個方面:
在開發提示時,重要的是要集成幾個關鍵組件,以確保清晰度和有效性:

  • 指令:向AI提供清晰而直接的指令,類似于你與人溝通的方式。這種清晰度對于幫助AI“理解”預期內容至關重要。
  • 外部環境:在必要時,為人工智能的反應提供相關的背景信息或具體指導。這種“外部環境”構成了提示,并幫助AI掌握整個場景。
  • 用戶輸入:這是最直接的部分——用戶的直接請求或問題

只要說明白這三點,就算是一個合適的提示詞,但是是遠遠不夠的,這里我用AI整理出了優化的重點,感興趣的可以看一下。


清晰具體地定義需求,避免模糊指令,確保模型準確理解任務目標明確指定輸出格式,如JSON或特定結構,便于后續處理或解析將復雜任務拆解為多個簡單子任務,逐步遞進完成,提高準確率使用分隔符區分不同輸入部分,避免混淆,如"""文本內容"""在需要推理的問題中要求展示思維鏈,分步驟呈現推導過程通過少樣本示例引導模型模仿特定風格或行為模式控制輸出長度,設定字數限制或篇幅要求,確保簡潔性對長文本采用分段歸納再整合的方法,突破上下文限制在技術性任務中先讓模型自主生成答案,再進行評估驗證必要時隱藏詳細推理過程,直接輸出最終結果或結構化數據利用外部工具增強能力,如API查詢實時數據或訪問知識庫在長對話中定期總結關鍵信息,保持上下文連貫性角色扮演方式可提升專業領域回答的準確性為系統提示設定明確的行為模式和任務規范### 優化Prompt的技巧清晰具體地定義需求,避免模糊指令,確保模型準確理解任務目標明確指定輸出格式,如JSON或特定結構,便于后續處理或解析將復雜任務拆解為多個簡單子任務,逐步遞進完成,提高準確率使用分隔符區分不同輸入部分,避免混淆,如"""文本內容"""在需要推理的問題中要求展示思維鏈,分步驟呈現推導過程通過少樣本示例引導模型模仿特定風格或行為模式控制輸出長度,設定字數限制或篇幅要求,確保簡潔性對長文本采用分段歸納再整合的方法,突破上下文限制在技術性任務中先讓模型自主生成答案,再進行評估驗證必要時隱藏詳細推理過程,直接輸出最終結果或結構化數據利用外部工具增強能力,如API查詢實時數據或訪問知識庫在長對話中定期總結關鍵信息,保持上下文連貫性角色扮演方式可提升專業領域回答的準確性為系統提示設定明確的行為模式和任務規范### 優化Prompt的技巧清晰具體地定義需求,避免模糊指令,確保模型準確理解任務目標明確指定輸出格式,如JSON或特定結構,便于后續處理或解析將復雜任務拆解為多個簡單子任務,逐步遞進完成,提高準確率使用分隔符區分不同輸入部分,避免混淆,如"""文本內容"""在需要推理的問題中要求展示思維鏈,分步驟呈現推導過程通過少樣本示例引導模型模仿特定風格或行為模式控制輸出長度,設定字數限制或篇幅要求,確保簡潔性對長文本采用分段歸納再整合的方法,突破上下文限制在技術性任務中先讓模型自主生成答案,再進行評估驗證必要時隱藏詳細推理過程,直接輸出最終結果或結構化數據利用外部工具增強能力,如API查詢實時數據或訪問知識庫在長對話中定期總結關鍵信息,保持上下文連貫性角色扮演方式可提升專業領域回答的準確性為系統提示設定明確的行為模式和任務規范

二、對話記憶(多輪對話實現)

1. 使用 Chat Client 實現基礎對話功能

參考 Spring AI 的官方文檔,了解到 Spring AI 提供了 ChatClient API 來和 AI 大模型交互。

ChatClient 是使用 ChatClient.Builder 對象創建的。您可以為任何 ChatModel Spring Boot 自動配置獲取一個自動配置的 ChatClient.Builder 實例,也可以通過編程方式創建一個

這是官方提供的通過構造器注入的事例:

// 方式1:使用構造器注入
@RestController
class MyController {private final ChatClient chatClient;public MyController(ChatClient.Builder chatClientBuilder) {this.chatClient = chatClientBuilder.build();}@GetMapping("/ai")String generation(String userInput) {return this.chatClient.prompt().user(userInput).call().content();}
}

使用建造者模式

// 方式2:使用建造者模式
ChatClient chatClient = ChatClient.builder(chatModel).defaultSystem("you are a helpful AI").build();

ChatC?lient 支持多種響應格式,比如返?回 ChatRes?ponse 對象、?返回實體對象、流式返回:

// ChatClient支持多種響應格式
// 1. 返回 ChatResponse 對象(包含元數據如 token 使用量)
ChatResponse chatResponse = chatClient.prompt().user("Tell me a joke").call().chatResponse();// 2. 返回實體對象(自動將 AI 輸出映射為 Java 對象)
// 2.1 返回單個實體
record ActorFilms(String actor, List<String> movies) {}
ActorFilms actorFilms = chatClient.prompt().user("Generate the filmography for a random actor.").call().entity(ActorFilms.class);// 2.2 返回泛型集合
List<ActorFilms> multipleActors = chatClient.prompt().user("Generate filmography for Tom Hanks and Bill Murray.").call().entity(new ParameterizedTypeReference<List<ActorFilms>>() {});// 3. 流式返回(適用于打字機效果)
Flux<String> streamResponse = chatClient.prompt().user("Tell me a story").stream().content();// 也可以流式返回ChatResponse
Flux<ChatResponse> streamWithMetadata = chatClient.prompt().user("Tell me a story").stream().chatResponse();

可以給 C?hatClient 設置默認參數,比如系?統提示詞,還可以在對?話時動態更改系統提示?詞的變量,類似模板的概念:

// 定義默認系統提示詞
ChatClient chatClient = ChatClient.builder(chatModel).defaultSystem("You are a friendly chat bot that answers question in the voice of a {voice}").build();// 對話時動態更改系統提示詞的變量
chatClient.prompt().system(sp -> sp.param("voice", voice)).user(message).call().content());

2. Advisor 顧問的使用

Advisor在Spring AI中扮演著類似AOP(面向切面編程)中顧問的角色,用于在 AI 模型調用前后添加邏輯以增強 AI 的能力。它允許開發者在不修改核心代碼的情況下,對AI請求進行預處理或后處理,例如日志記錄、對話記憶、RAG等。

  • 前置增強:調用 AI 前改寫一下 Prompt 提示詞、檢查一下提示詞是否安全
  • 后置增強:調用 AI 后記錄一下日志、處理一下返回的結果

比如對話記憶顧問 Me?ssageChatMemoryAdv?isor 可以幫助我們實現多輪對話能?力,省去了自己維護對話列表的麻煩。

var chatClient = ChatClient.builder(chatModel).defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory), // 對話記憶 advisornew QuestionAnswerAdvisor(vectorStore)    // RAG 檢索增強 advisor).build();String response = this.chatClient.prompt()// 對話時動態設定攔截器參數,比如指定對話記憶的 id 和長度.advisors(advisor -> advisor.param("chat_memory_conversation_id", "678").param("chat_memory_response_size", 100)).user(userText).call().content();

Advisors 的原理圖如下:
在這里插入圖片描述
在這里插入圖片描述
實際開發中,往往我們會用到多個攔截器,組合在一起相當于一條攔截器鏈條(責任鏈模式的設計思想)。每個攔截器是有順序的,通過 getOrder() 方法獲取到順序,得到的值越低,越優先執行。

想要實現對話記憶功能,可以使用 Spring? AI 的 ChatMe?moryAdvisor,?它主要有幾種內置的實現方式:

  • MessageChatMemoryAdvisor:從記憶中檢索歷史對話,并將其作為消息集合添加到提示詞中
  • PromptChatMemoryAdvisor:從記憶中檢索歷史對話,并將其添加到提示詞的系統文本中
  • VectorStoreChatMemoryAdvisor:可以用向量數據庫來存儲檢索歷史對話

Messag?eChatMemoryAdvisor 和 Pro?mptChatMemor?yAdvisor 用法類?似,但是略有一些區別:

  1. Messag?eChatMemoryAdvisor 將對話歷史作為一系列獨?立的消息添加到提示中,保留原始?對話的完整結構,包括每條消息的?角色標識(用戶、助手、系統)
[{"role": "user", "content": "你好"},{"role": "assistant", "content": "你好!有什么我能幫助你的嗎?"},{"role": "user", "content": "講個笑話"}
]
  1. PromptC?hatMemoryAdvisor 將對話歷史添加到提示詞的系統文本部?分,因此可能會失去原始的消息邊界。???????????????????
以下是之前的對話歷史:
用戶: 你好
助手: 你好!有什么我能幫助你的嗎?
用戶: 講個笑話
現在請繼續回答用戶的問題。

一般情況下,更建議使用 MessageChatMemoryAdvisor 更符合大多數現代 LLM 的對話模型設計,能更好地保持上下文連貫性。

使用 Chat Memory構造ChatMemoryAdvisor
上述 ChatMemoryAdvisor 都依賴 Chat Memory 進行構造,Chat Memory 負責歷史對話的存儲,定義了保存消息、查詢消息、清空消息歷史的方法。
在這里插入圖片描述
Sprin?g AI 內置了幾種 Chat Me?mory,可以將對?話保存到不同的數據?源中,比如:

  • InMemoryChatMemory:內存存儲
  • CassandraChatMemory:在 Cassandra 中帶有過期時間的持久化存儲
  • Neo4jChatMemory:在 Neo4j 中沒有過期時間限制的持久化存儲
  • JdbcChatMemory:在 JDBC 中沒有過期時間限制的持久化存儲
  • 自定義數據源存儲

三、SpringAI會話記憶、Advisor實戰

1. 使用 InMemoryChatMemory:內存存儲 實現對話記憶

  1. 首先初始化 ChatC?lient 對象。使用 Spring 的構造器注入方式來注入阿里大模型dashscopeChatMod?el 對象,并使用該對象來初始化 ChatCli?ent。初始化時指定默認的系統 Prompt 和基于內存?的對話記憶 Advisor。代碼如下:
@Component
@Slf4j
public class App {private final ChatClient chatClient;private static final String SYSTEM_PROMPT = "your system prompt";public LoveApp(ChatModel dashscopeChatModel) {// 初始化基于內存的對話記憶ChatMemory chatMemory = new InMemoryChatMemory();chatClient = ChatClient.builder(dashscopeChatModel).defaultSystem(SYSTEM_PROMPT).defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory)).build();}
}
  1. 編寫對話方法,調用 chatClient 對象,傳入用戶 Pr?ompt,并且給 advi?sor 指定對話 id 和對話?記憶大小。代碼如下:
public String doChat(String message, String chatId) {ChatResponse response = chatClient.prompt().user(message).advisors(spec -> spec.param(CHAT_MEMORY_CONVERSATION_ID_KEY, chatId).param(CHAT_MEMORY_RETRIEVE_SIZE_KEY, 10)).call().chatResponse();String content = response.getResult().getOutput().getText();log.info("content: {}", content);return content;
}
  1. 編寫單元測試,測試多輪對話:
@SpringBootTest
class AppTest {@Resourceprivate App app;@Testvoid testChat() {String chatId = UUID.randomUUID().toString();// 第一輪String message = "你好,我是wangdong.";String answer = app.doChat(message, chatId);Assertions.assertNotNull(answer);// 第二輪message = "我想學習springAI!!!";answer = app.doChat(message, chatId);Assertions.assertNotNull(answer);// 第三輪message = "你記得我叫啥嗎?";answer = app.doChat(message, chatId);Assertions.assertNotNull(answer);}
}

第一輪:
在這里插入圖片描述
第二輪:
在這里插入圖片描述
第三輪:
在這里插入圖片描述
這樣我們就完成了基于內存的會話記憶,但是這樣還是有弊端,一旦程序重啟,我們的會話還是會丟失,還需要別的方法來優化會話記憶

2. 自定義Advisor的使用

自定義Adcisor 和 Spring AOP 比較相似,我們可以通過編寫攔截?器或切面對請求和響應進行處理?,比如記錄請求響應日志、鑒權等。

Spring ?AI 的 Advisor 就可以理解為攔截器,可以對?調用 AI 的請求進行增強?,比如調用 AI 前鑒權、?調用 AI 后記錄日志。

官方已經提供了一些 Advisor,但可能無法滿足我們實際的業務需求,這時我們可以使用官方提供的 自定義 Advisor 功能。按照下列步驟操作即可。

  1. 自定義的Advisor要實現這兩個接口CallAroundAdvisor StreamAroundAdvisor
public class CustomAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {//實現方法...
}

在這里插入圖片描述

  1. 實現核心方法

對于非流式處理 (CallAroundAdvisor),實現 aroundCall 方法:

@Override
public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {// 1. 處理請求(前置處理)AdvisedRequest modifiedRequest = processRequest(advisedRequest);// 2. 調用鏈中的下一個AdvisorAdvisedResponse response = chain.nextAroundCall(modifiedRequest);// 3. 處理響應(后置處理)return processResponse(response);
}

對于流式處理 (StreamAroundAdvisor),實現 aroundStream 方法:

@Override
public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {// 1. 處理請求AdvisedRequest modifiedRequest = processRequest(advisedRequest);// 2. 調用鏈中的下一個Advisor并處理流式響應return chain.nextAroundStream(modifiedRequest).map(response -> processResponse(response));
}
  1. 設置執行順序
    通過實現getOrder()方法指定 Advisor 在鏈中的執行順序。值越小優先級越高,越先執行:
@Override
public int getOrder() {// 值越小優先級越高,越先執行return 100; 
}
  1. 提供唯一名稱
    為每個 Advisor 提供一個唯一標識符:
@Override
public String getName() {return "魚皮自定義的 Advisor";
}

3. 使用自定義 Advisor 實現自定義日志 Advisor

雖然 Spring ?AI 已經內置了 SimpleLoggerAdvisor 日志攔截器,但是以 D?ebug 級別輸出日志,而默認 Spri?ng Boot 項目的日志級別是 Inf?o,所以看不到打印的日志信息。
雖然上述方?式可行,但如果為了更靈活地打印指定的?日志,建議自己實現?一個日志 Adv?isor。
我們可以同時參考 官方文檔 和內置的 SimpleLoggerAdvisor 源碼,結合 2 者并略做修改,開發一個更精簡的、可自定義級別的日志記錄器。默認打印 info 級別日志、并且只輸出單次用戶提示詞和 AI 回復的文本。

/*** 自定義日志 Advisor* 打印 info 級別日志、只輸出單次用戶提示詞和 AI 回復的文本*/
@Slf4j
public class MyLoggerAdvisor implements CallAroundAdvisor, StreamAroundAdvisor {@Overridepublic String getName() {return this.getClass().getSimpleName();}@Overridepublic int getOrder() {return 0;}private AdvisedRequest before(AdvisedRequest request) {log.info("AI Request: {}", request.userText());return request;}private void observeAfter(AdvisedResponse advisedResponse) {log.info("AI Response: {}", advisedResponse.response().getResult().getOutput().getText());}public AdvisedResponse aroundCall(AdvisedRequest advisedRequest, CallAroundAdvisorChain chain) {advisedRequest = this.before(advisedRequest);AdvisedResponse advisedResponse = chain.nextAroundCall(advisedRequest);this.observeAfter(advisedResponse);return advisedResponse;}public Flux<AdvisedResponse> aroundStream(AdvisedRequest advisedRequest, StreamAroundAdvisorChain chain) {advisedRequest = this.before(advisedRequest);Flux<AdvisedResponse> advisedResponses = chain.nextAroundStream(advisedRequest);return (new MessageAggregator()).aggregateAdvisedResponse(advisedResponses, this::observeAfter);}
}

上述代碼中值得關注的是 arou?ndStream 方法的返回,通過 MessageAggregator 工具類將 Flux 響應聚合成單個 AdvisedR?esponse。這對于日志記錄或其他需要觀察整個響應而非流中各?個獨立項的處理非常有用。注意,不能在 MessageAggre?gator 中修改響應,因為它是一個只讀操作。

在 App 中應用自定義的日志 Advisor:

chatClient = ChatClient.builder(dashscopeChatModel).defaultSystem(SYSTEM_PROMPT).defaultAdvisors(new MessageChatMemoryAdvisor(chatMemory),// 自定義日志 Advisor,可按需開啟new MyLoggerAdvisor(),).build();

四、結語(會不斷補充,可以收藏一下)

本章介紹了 Spring? AI 調用大模型、提示詞工程、對話記憶、Adv?isor 的基本使用,對于對話記憶的自定義和jdbc存儲,也會在這段時間加入,我會在學習中不斷整理筆記,鞏固自己學到的東西。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/90789.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/90789.shtml
英文地址,請注明出處:http://en.pswp.cn/web/90789.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

對抗攻擊-知識點

文章目錄自然圖像往往靠近機器學習分類器學習到的決策邊界&#xff08;decision boundaries&#xff09;。正交方向--改變某一個不影響其它的特征降采樣&#xff08;Feature Downsampling&#xff09;通過黑盒攻擊的持續挑戰&#xff0c;我們才能構建真正安全可靠的智能系統DCT…

7.26 作業

一、實驗要求及其拓撲圖&#xff1a; 本次實驗拓撲圖&#xff1a; 二、實驗IP地址劃分&#xff1a; 1. 公網地址&#xff08;R5 作為 ISP&#xff0c;使用公網地址&#xff09;&#xff1a; R1 與 R5 之間接口&#xff1a;15.1.1.0/24&#xff0c;R1 側為 15.1.1…

Kafka運維實戰 14 - kafka消費者組消費進度(Lag)深入理解【實戰】

目錄什么是消費者 Lag舉例說明&#xff1a;Lag 的意義&#xff1a;Lag 監控和查詢kafka-consumer-groups基本語法常用命令示例1. 查看單個消費者組的詳細信息&#xff08;最常用&#xff09;2. 列出所有消費者組&#xff08;只顯示名稱&#xff09;3. 列出所有消費者組&#xf…

設計模式(十三)結構型:代理模式詳解

設計模式&#xff08;十三&#xff09;結構型&#xff1a;代理模式詳解代理模式&#xff08;Proxy Pattern&#xff09;是 GoF 23 種設計模式中的結構型模式之一&#xff0c;其核心價值在于為其他對象提供一種間接訪問的機制&#xff0c;以控制對原始對象的訪問。它通過引入一個…

24點數學游戲(窮舉法求解表達式)

摘要本畢業設計旨在利用MATLAB技術實現一個24點數學游戲&#xff0c;采用窮舉法求解所有可能的表達式組合。通過全排列數字、枚舉運算符及括號位置&#xff0c;結合遞歸回溯算法&#xff0c;系統能夠高效地搜索所有可能的運算路徑&#xff0c;并驗證結果是否為24。實驗結果表明…

【web應用】如何進行前后端調試Debug? + 前端JavaScript調試Debug?

文章目錄一、前后端&#xff1a;后端以Debug模式運行后端項目&#xff0c;打斷點二、前后端&#xff1a;前端項目在瀏覽器中調試三、單獨前端&#xff1a;前端JavaScript調試1、控制臺輸出2、網頁調試器中添加斷點3、debugger關鍵字一、前后端&#xff1a;后端以Debug模式運行后…

FreeCAD開發樓梯參數化三維模型和鋼格柵

根據樓梯標準圖集開發各種樓梯。上行左轉&#xff0c;上行右轉&#xff0c;對應的欄桿也是配套2種。樓梯總成鋼格柵標準里的跨度和承載 扁鋼尺寸&#xff0c;輕松切換和修改參數。格柵綜合本來格柵上橫桿是冷軋扭鋼筋&#xff0c;先繪制一個圓柱&#xff0c;再做一個內切正方形…

【AcWing 836題解】合并集合

AcWing 836. 合并集合 【題目描述】 在查看解析之前&#xff0c;先給自己一點時間思考哦&#xff01; 【題解】 并查集是一種用于處理集合合并與查詢問題的數據結構&#xff0c;通常支持以下兩種操作&#xff1a; Find&#xff1a;查詢一個元素所在的集合。 Union&#xff1a…

MySQL鎖機制與MVCC原理剖析

在MySQL中&#xff0c;我們使用到了它的各種類鎖&#xff1b;按照它的維度&#xff0c;有各種鎖 從數據庫的操作粒度有&#xff0c;表鎖&#xff0c;行鎖。從數據庫的操作的類型&#xff0c;有讀鎖和寫鎖。性能上有樂觀鎖和悲觀鎖。 在上一篇文章中的事務隔離級別&#xff0c;需…

C++學習(線程相關)

目錄 一、線程庫thread 1.使用外部函數 2. 使用類的函數 3. 添加參數 二、線程庫 mutex 1.使用lock()方法 2.try_lock()方法 三、線程庫lock_guard 四、線程庫unique_lock 1.adopt_lock 2.defer_lock() 五、線程庫call_once 六、線程庫promise & future 七、c…

EPOLLONESHOT 深度解析:Linux epoll 的單次觸發機制

EPOLLONESHOT 深度解析&#xff1a;Linux epoll 的單次觸發機制 EPOLLONESHOT 是 Linux epoll 接口中的高級事件標志&#xff0c;用于實現精確的事件單次觸發控制。以下是其全面技術解析&#xff1a; 核心設計理念 #mermaid-svg-Xg5sCLdddqmKsvKG {font-family:"trebuchet…

深入解析MongoDB分片原理與運維實踐指南

深入解析MongoDB分片原理與運維實踐指南 技術背景與應用場景 隨著互聯網業務的高速發展&#xff0c;單節點MongoDB實例在數據量和訪問并發上都面臨瓶頸。為了解決數據存儲容量受限和讀寫性能下降的問題&#xff0c;MongoDB官方提供了分片&#xff08;Sharding&#xff09;方案&…

基于Django的天氣數據可視化分析預測系統

【86-Django】基于Django的天氣數據可視化分析預測系統&#xff08;完整系統源碼開發筆記詳細部署教程&#xff09;? 目錄 一、項目簡介 二、項目界面展示 三、項目視頻展示 四、技術架構 五、核心功能模塊 六、部署教程一、項目簡介 隨著全球氣候變化和極端天氣事件的頻發&am…

怎么放大單片機輸出電流

單片機作為電子系統的控制核心&#xff0c;其 I/O 口輸出電流通常較小&#xff08;一般在 10-20mA 左右&#xff09;&#xff0c;難以直接驅動繼電器、電機、大功率 LED 等需要較大工作電流的外設。因此&#xff0c;在實際應用中需通過特定電路放大單片機輸出電流&#xff0c;實…

站長百科類網站pbootcms模板(自適應手機端)+利于SEO優化(下載)

站長百科類網站pbootcms模板(自適應手機端)利于SEO優化 模板介紹&#xff1a; PbootCMS內核開發的模板&#xff0c;該模板屬于新聞資訊、新聞博客類企業使用&#xff01; 頁面簡潔簡單&#xff0c;容易管理&#xff0c;附帶測試數據&#xff01; 模板特點&#xff1a; 1、手工書…

【Golang】Go語言函數

Go語言函數 文章目錄Go語言函數Go函數特點一、函數的基本格式定義二、匿名函數三、自執行函數四、閉包函數五、延遲調用Go函數特點 無需聲明原型支持不定 變參支持多返回值支持匿名函數和閉包函數也是一種類型&#xff0c;一個函數可以賦值給變量不支持嵌套&#xff0c;一個包…

JAVA算法練習題day2

雙指針4.移動零二刷昨天的題&#xff0c;學習了新的數據結構StringBuilder。專為頻繁字符串拼接設計的可變字符串類。(https://blog.csdn.net/m0_73941339/article/details/145651287)二刷完昨天的題目&#xff0c;做到這題腦子已經轉不動了。做雙指針&#xff0c;一般雙指針初…

LLM2Rec-新國立-KDD2025-微調LLM獲得蘊含協同信息的embedding

文章目錄1. 背景與問題任務背景動機LLM2Rec 兩大步驟2. 方法2.1 Collaborative Supervised Fine-tuning&#xff08;CSFT&#xff09;2.2 Item-level Embedding Modeling2.2.1 從單向注意力 → 雙向注意力&#xff08;Bidirectional attention&#xff09;2.2.2 商品級別的對比…

前端學習9:JavaScript--對象與原型

前言&#xff1a;適合有基礎的同學入門嘗試 / 復習回憶。對象基礎&#xff1a;1.創建用戶對象const user {// 屬性&#xff08;鍵值對&#xff09;name: "小島",age: 20,isAdmin: false, }2.方法&#xff08;函數屬性&#xff09;sayHello() {console.log(你好&…

網絡:應用層

網絡&#xff1a;應用層 我們要知道&#xff0c;所有的問題解決都是在應用層。:happy: 協議是一種約定&#xff0c;也就是雙方約定好的結構化的數據。但是在讀寫數據時我們都是按字符串的方式來發送接受的&#xff0c;那么我們應該如和傳輸結構化的數據呢&#xff1f;應用層協…