<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12

      Loading

      混元開源之力:spring-ai-hunyuan 項目功能升級與實戰體驗

      今天咱們繼續聊聊 spring-ai-hunyuan 這個項目。上次我們兼容了 spring-ai 的 1.0.0 正式版本之后,就暫時放了一陣子,沒怎么動。最近倒是收到不少小伙伴反饋,說混元的思考鏈功能為什么不返回結果。其實,混元官方那邊提供的兼容 OpenAI 的方案,本質上就是幫大家能快速接入,方便快捷,但也難免會有一些高級特性或者參數沒辦法支持。就算官方給了參數,也未必能直接用上。

      942f4b5f09c95c39554398f80f251538

      所以最近我就抽時間重新開發了一下,專門把思考鏈的集成做了進來。同時順帶把 ASR(語音識別)和 TTS(語音合成)功能也加進去了,這樣一來,基本上跟文字生成相關的場景都給覆蓋了,功能更加完整了。

      項目的源碼開源在這兒,感興趣的小伙伴可以直接去看看:
      https://github.com/StudiousXiaoYu/spring-ai-hunyuan

      目前我還沒寫出詳細的實戰案例教程,不過今天先給大家簡單介紹一下,方便大家能快速上手。所有的案例源碼也已經全部開源了,大家可以直接 clone 到本地跑起來試試:
      https://github.com/StudiousXiaoYu/spring-ai-hunyuan-example

      項目集成

      首先,咱們需要在 pom.xml 文件中集成相應的依賴。只需要將以下依賴添加到你的 pom.xml 中就可以了:

      <dependency>
          <groupId>io.github.studiousxiaoyu</groupId>
          <artifactId>spring-ai-starter-model-hunyuan</artifactId>
          <version>${spring-ai-hunyuan.version}</version>
      </dependency>
      

      好的,這樣就搞定了,挺簡單的。現在我們已經開發到1.0.0.2版本了,除了混元生文功能外,還加入了思考鏈、文本轉語音、語音轉文本等功能。接下來,我們需要在配置文件里加上你騰訊云的秘鑰信息,具體內容如下:

      spring.ai.hunyuan.secret-id=${HUNYUAN_SECRET_ID}
      spring.ai.hunyuan.secret-key=${HUNYUAN_SECRET_KEY}
      

      申請地址如下:https://console.cloud.tencent.com/cam/capi

      你直接新建秘鑰即可。

      d33326c09c1f19d4d6ca7fe78599375d

      場景演示

      沒錯,經過這些步驟后,我們就具備了所有必要的條件,可以直接用 SpringAI 混元框架來對接混元,進行企業級開發了。這樣一來,開發流程會更加順暢,功能也能更好地滿足企業需求,效率會大大提升。

      模型注入

      首先,我們需要將本章節需要用到的所有模型先注入進來。這里簡單介紹下。

      private final ChatClient chatClient;
      
      private final HunYuanAudioTranscriptionModel audioTranscriptionModel;
      
      private final HunYuanAudioTextToVoiceModel textToVoiceModel;
      
      public ChatClientExample(ChatModel chatModel, HunYuanAudioTranscriptionModel audioTranscriptionModel, HunYuanAudioTextToVoiceModel textToVoiceModel) {
          this.chatClient = ChatClient.builder(chatModel).defaultAdvisors(new SimpleLoggerAdvisor()).build();
          this.audioTranscriptionModel = audioTranscriptionModel;
          this.textToVoiceModel = textToVoiceModel;
      }
      

      這里使用的聊天模型默認是hunyuan-pro,語音轉文本則用的是一句話識別接口,具體使用的模型是16k_zh-PY(支持中英粵三種語言)。需要注意的是,這個接口有一些限制,比如音頻時長不能超過60秒,文件大小不能超過3MB。之所以選擇這個接口,是因為目前語音轉文本技術主要集中在日常對話類應用,像大數據分析這種場景還沒有廣泛涉及,所以暫時是采用這個接口。如果你有疑問,可以參考一下官方文檔鏈接:點擊查看文檔

      至于文本轉語音,我們用的是101001(情感女聲),你可以查看音色列表來了解更多:點擊查看音色列表,如果需要更多信息,也可以參考這里:點擊查看詳細文檔

      如果你想調整模型的參數,完全可以在配置文件中做修改。我已經把參數配置開放出來,常見的參數如下:

      #聊天模型切換
      spring.ai.hunyuan.chat.options.model=
      #語音轉文本模型切換
      spring.ai.hunyuan.audio.transcription.options.engSerViceType=
      #文本轉語音模型切換
      spring.ai.hunyuan.audio.tts.options.voiceType=
      

      這只是其中的一個小例子,實際上官方提供的所有請求參數都被封裝在每個模型配置的 option 里面。如果你想了解更詳細的內容,可以直接去看看官方文檔,或者你也可以查看我寫的源碼,都會有很清楚的說明。

      基礎聊天

      先來看下最基礎的生文操作,直接使用spring ai的官方示例即可。

      對話

      這里直接看下阻塞問答和流式問答,代碼如下:

      @PostMapping("/chat")
      public String chat(@RequestParam("userInput")  String userInput) {
          String content = this.chatClient.prompt()
                  .user(userInput)
                  .call()
                  .content();
          log.info("content: {}", content);
          return content;
      }
      
      @GetMapping("/chat-stream")
      public Flux<ServerSentEvent<String>> chatStream(@RequestParam("userInput") String userInput) {
          return chatClient.prompt()
                  .user(userInput)
                  .stream()
                  .content() // 獲取原始Flux<String>
                  .map(content -> ServerSentEvent.<String>builder() // 封裝為SSE事件
                          .data(content)
                          .build());
      }
      

      因為我們采用了流式問答的方式,通常最喜歡用前端通過SSE(Server-Sent Events)來實現。所以在這個地方,我也直接返回了ServerSentEvent,這樣方便前端對接。這里雖然沒有展示具體的頁面,但示例項目中已經集成了Swagger文檔,你可以簡單瀏覽一下,看看效果如何。

      f5ee0d824ce45c4ad8d409a2cef3e5b2

      結構化對象

      另外一個要說的點是結構化對象的兼容性,簡單來說就是系統能不能返回 Java 對象的信息。接下來我們看一下具體的代碼:

      @GetMapping("/ai-Entity")
      public ActorFilms aiEntity() {
          ActorFilms actorFilms = chatClient.prompt()
                  .user("Generate the filmography for a random actor.")
                  .call()
                  .entity(ActorFilms.class);
          return actorFilms;
      }
      
      /**
       *當前用戶輸入后,返回列表實體類型的回答,ParameterizedTypeReference是一個泛型,用于指定返回的類型。
       * @return List<ActorFilms>
       */
      @GetMapping("/ai-EntityList")
      List<ActorFilms> generationByEntityList() {
          List<ActorFilms> actorFilms = chatClient.prompt()
                  .user("Generate the filmography of 5 movies for Tom Hanks and Bill Murray.")
                  .call()
                  .entity(new ParameterizedTypeReference<List<ActorFilms>>() {
                  });
          return actorFilms;
      }
      
      public record ActorFilms(String actor, List<String> movies) {
      }
      

      這個例子里,我們用了兩種不同的情況:一種是普通的單一類型,另外一種是數組類型。當然,其實其他類型的Map結構也是支持的。不過,能不能正常運行,最終還是取決于模型的能力,看它是否支持這些結構。

      目前我用的hunyuan-pro模型還沒有報錯。從返回的結果來看,大體上是沒問題的,具體效果可以參考下面的截圖:

      0bf0976f53f5cfc0617a6190f5fd2d5f

      函數調用

      另外,關于函數調用的部分,我們會提前準備好一些寫好的方法,并且把這些方法的參數暴露出來,供大模型調用。先讓我們看看代碼是怎么寫的吧。

      @PostMapping("/ai-function")
      String functionGenerationByText(@RequestParam("userInput")  String userInput) {
          HunYuanChatOptions options = new HunYuanChatOptions();
          options.setModel("hunyuan-functioncall");
          String content = this.chatClient
                  .prompt()
                  .options(options)
                  .user(userInput)
                  .tools(new DateTimeTools())
                  .call()
                  .content();
          log.info("content: {}", content);
          return content;
      }
      
      public class DateTimeTools {
      
          @Tool(description = "Get the current date and time in the user's timezone")
          String getCurrentDateTime() {
              String currentDateTime = LocalDateTime.now().atZone(LocaleContextHolder.getTimeZone().toZoneId()).toString();
              log.info("getCurrentDateTime:{}",currentDateTime);
              return currentDateTime;
          }
      
      }
      

      我這里簡單展示了一下如何獲取當前日期的工具,代碼沒有加入任何輸入參數,主要就是看看它能否正常工作。順便提一下,我在代碼里指定了當前使用的模型。之前的配置是換全局模型,但在這里,你只需要替換當前對話中使用的模型就行了。因為我們需要切換到一個支持函數調用的大模型。

      最后演示如下,如圖所示:

      745f6cb93a52a727a7b6ea7d119afa27

      思考鏈

      新集成的思考鏈來了,簡單來說,就是通過檢查大模型返回的數據,看里面有沒有包含‘思考’的內容。不過要注意,并不是所有的大模型都有這個功能,只有部分模型才會有類似的思考內容。代碼如下:

      @PostMapping("/chat-think")
      public String think(@RequestParam("userInput")  String userInput) {
          HunYuanChatOptions options = new HunYuanChatOptions();
          options.setModel("hunyuan-a13b");
          options.setEnableThinking(true);
          ChatResponse chatResponse = this.chatClient.prompt()
                  .user(userInput)
                  .options(options)
                  .call().chatResponse();
          HunYuanAssistantMessage output = (HunYuanAssistantMessage) chatResponse.getResult().getOutput();
          String think = output.getReasoningContent();
          String text = output.getText();
          log.info("think: {}", think);
          log.info("text: {}", text);
          return text;
      }
      
      @PostMapping("/stream-think")
      public Flux<ServerSentEvent<String>> streamThink (@RequestParam("userInput") String userInput){
          HunYuanChatOptions options = new HunYuanChatOptions();
          options.setModel("hunyuan-a13b");
          options.setEnableThinking(true);
          Flux<ServerSentEvent<String>> chatResponse = this.chatClient.prompt()
                  .user(userInput)
                  .options(options)
                  .stream()
                  .chatResponse()
                  .map(content -> (HunYuanAssistantMessage) content.getResult().getOutput())
                  .map(content -> {
                      String think = content.getReasoningContent();
                      String text = content.getText();
      
                      StreamResponse streamResponse;
                      if (think != null && !think.isEmpty()) {
                          streamResponse = new StreamResponse("thinking", think);
                      } else {
                          streamResponse = new StreamResponse("answer", text);
                      }
                      return ServerSentEvent.<String>builder()
                              .data(JSONUtil.toJsonStr(streamResponse))
                              .build();
                  });
          return chatResponse;
      }
      
      @Data
      @NoArgsConstructor
      public class StreamResponse {
          @JsonProperty("type")
          private String type;
          
          @JsonProperty("content")
          private String content;
          
          public StreamResponse(String type, String content) {
              this.type = type;
              this.content = content;
          }
      }
      

      同樣的,我這邊也寫了兩種方案,一個是阻塞式的,另一個是流式返回內容的。因為目前Spring AI還沒有統一的思考鏈返回字段,所以如果你想要獲取思考鏈的內容,得先把返回的信息類轉換成我自己定義的信息類,才能提取出這些數據。而且還需要注意的是,你得設置enableThinking的值才行。

      接下來我們來看一下效果,像圖上展示的那樣。

      a6018743ab6eb5b5b8bf1bc53e9f6f91

      因為我只能返回到固定的字段里,所以如果你需要以流式的方式獲取思考鏈的話,你得先定義一個格式,方便前端去截取數據。我這邊已經幫你定義好了,當前的返回樣式就是這樣的,如圖所示。

      30f8225c0de95f5d9c710830532188e0

      通過type值,前端就可以方便的定義標簽里的值了。

      圖片理解

      目前大模型已經可以支持圖片理解了,但它暫時不能直接通過文字生成圖片,這其實是另外一個功能,需要單獨進行對接。目前這個部分還沒有對接完成。以下是相關的代碼:

      @PostMapping("/chatWithPic")
      public String chatWithPic(@RequestParam("userInput")  String userInput) {
          var imageData = new ClassPathResource("/img.png");
          var userMessage = UserMessage.builder()
                  .text(userInput)
                  .media(List.of(new Media(MimeTypeUtils.IMAGE_PNG, imageData)))
                  .build();
          var hunyuanChatOptions = HunYuanChatOptions.builder().model("hunyuan-turbos-vision").build();
          String content = this.chatClient.prompt(new Prompt(userMessage, hunyuanChatOptions))
                  .call()
                  .content();
          log.info("content: {}", content);
          return content;
      }
      
      //https://cloudcache.tencent-cloud.com/qcloud/ui/portal-set/build/About/images/bg-product-series_87d.png
      @PostMapping("/chatWithPicUrl")
      public String chatWithPicUrl(@RequestParam("url")  String url,@RequestParam("userInput")  String userInput) throws MalformedURLException {
          var imageData = new UrlResource(url);
          var userMessage = UserMessage.builder()
                  .text(userInput)
                  .media(List.of(Media.builder()
                          .mimeType(MimeTypeUtils.IMAGE_PNG)
                          .data(url)
                          .build()
                  ))
                  .build();
          var hunyuanChatOptions = HunYuanChatOptions.builder().model("hunyuan-t1-vision").build();
          String content = this.chatClient.prompt(new Prompt(userMessage, hunyuanChatOptions))
                  .call()
                  .content();
          log.info("content: {}", content);
          return content;
      }
      

      目前我們支持兩種方式來上傳圖片,一種是直接使用本地圖片,另一種是通過在線的 URL 圖片都可以。不過呢,這樣的話,我們需要先構建一些用戶信息,不能再像以前那樣只傳個簡單的文本就能搞定了。咱們先看看效果如何吧。

      a110fd3f0f5b845ba8d379f0b673e577

      本地文件我也放在了案例項目中,你可以直接查看,和這個url的圖片是一致的。

      語音轉文本

      具體的注意事項前面已經說了,我們這里直接使用即可。代碼如下:

      //https://output.lemonfox.ai/wikipedia_ai.mp3
      @PostMapping("/audio2textByUrl")
      public String audio2textByUrl(@RequestParam("url")  String url) throws MalformedURLException {
          Resource resource = new UrlResource(url);
          String call = audioTranscriptionModel.call(resource);
          log.info("text: {}", call);
          return call;
      }
      
      @PostMapping("/audio2textByPath")
      public String audio2textByPath(){
          Resource resource = new ClassPathResource("/speech/speech1.mp3");
          String call = audioTranscriptionModel.call(resource);
          log.info("text: {}", call);
          return call;
      }
      

      好的,這里有兩種方式可以選擇,一種是用本地文件,另一種是用在線 URL。官方推薦使用騰訊云 COS 來存儲音頻并生成 URL 后提交請求,這樣做有幾個好處:首先,它會走內網來下載音頻,能顯著減少請求的延遲;其次,使用這種方式不會產生外網流量費用,也能幫助節省成本。

      當然,最后還是看你個人的需求和實際情況啦。效果如圖所示:

      2c8b0e2c553555fa85fe9c78d2e7b837

      文本轉語音

      這部分也是已經集成完畢,直接一行代碼即可完成調用,所有配置變動都可以寫到配置中,代碼如下:

      @PostMapping("/text2audio")
      public byte[] text2audio(@RequestParam("userInput")  String userInput) throws MalformedURLException {
          byte[] call = textToVoiceModel.call(userInput);
          FileUtil.writeBytes(call, "D:/output.mp3");
          return call;
      }
      

      前端其實可以直接讀取音頻流,然后用一個 <audio> 標簽來播放。我這邊后臺是直接生成的 MP3 文件,主要是為了測試文件是否能正常播放。經過測試,結果一切正常,播放效果也沒問題。

      小結

      這次更新的 spring-ai-hunyuan 項目在功能上做了不少增強,特別是在思考鏈、語音識別(ASR)和語音合成(TTS)方面。之前由于兼容性問題,一些高級功能可能無法完全支持,而現在這些問題已經得到解決。新的版本 1.0.0.2 增加了這些功能,增強了項目的整體能力,特別是在與文本生成相關的場景中,用戶可以更加順暢地進行開發。

      首先,項目源碼已經開源,大家可以直接從 GitHub 上查看,甚至根據提供的案例源碼快速上手。集成方面,也提供了簡單易用的依賴配置和騰訊云秘鑰設置,幫助開發者迅速搭建起開發環境。

      在實際功能上,這個版本加入了思考鏈、文本轉語音、語音轉文本等模塊,能夠讓開發者更加方便地調用大模型進行文本和語音的處理。對于語音識別和合成,使用騰訊云的接口能更好地處理音頻文件(如語音轉文字和文字轉語音)。另外,思考鏈功能的加入,更是讓模型能在生成回答的同時,帶上思考過程,提升了交互的自然度。

      具體到代碼實現上,項目的集成和配置都非常直觀,基本只需在 pom.xml 添加依賴、配置好秘鑰,并調整一些參數設置,就能實現各種功能。最基本的功能包括基于用戶輸入的聊天對話,支持流式和阻塞式問答。而在結構化對象的處理上,項目支持將聊天內容轉換成 Java 對象格式返回,非常適合數據驅動的應用場景。

      對于前端開發者來說,流式問答(SSE)可以非常方便地實現實時聊天功能,而思考鏈的集成則讓聊天更具智能化和邏輯性。雖然目前圖片生成還未完全對接,但語音轉文本和文本轉語音的功能已非常完善,提供了兩種方式(本地文件和 URL)來處理音頻數據。

      posted @ 2025-09-18 09:18  努力的小雨  閱讀(189)  評論(0)    收藏  舉報
      主站蜘蛛池模板: 国产精品多p对白交换绿帽| 天美麻花果冻视频大全英文版| 中文字幕色av一区二区三区| 精品午夜福利短视频一区| 国产成人精品久久综合| 亚洲一区二区三区在线播放无码| 蜜桃av无码免费看永久| 亚洲人成网站观看在线观看| 日韩精品中文字幕人妻| 欧美激情一区二区久久久| 亚洲熟妇自偷自拍另欧美| 人与禽交av在线播放| 国产一区二区三区我不卡| 亚洲综合另类小说色区色噜噜| 国产精一品亚洲二区在线播放| 欧洲中文字幕国产精品| 国产 精品 自在 线免费| 激情综合网五月婷婷| 日韩伦人妻无码| 亚洲av永久无码天堂影院| 日韩高清亚洲日韩精品一区二区| 三都| 亚洲熟妇丰满多毛xxxx| 亚洲精品漫画一二三区| 镇雄县| 一区二区三区四区五区自拍| 欧美成年性h版影视中文字幕| 国产91丝袜在线观看| 99精品视频在线观看婷婷| 中文字幕久久久久人妻中出| 亚洲午夜香蕉久久精品| 国内极度色诱视频网站| 亚洲一区二区三区啪啪| 亚洲五月丁香综合视频| 日韩深夜免费在线观看| 国产成人精品视频不卡| 午夜福利国产精品小视频| AV最新高清无码专区| 日韩精品亚洲精品第一页| 亚洲中文字幕无码不卡电影| 肉大捧一进一出免费视频|