找回密码
 立即注册
首页 业界区 业界 Spring AI 增加混元 embedding 向量功能

Spring AI 增加混元 embedding 向量功能

姚望舒 6 天前
上次我们讨论了如何将自己的开源项目发布到 Maven 中央仓库,确保其能够方便地被其他开发者使用和集成。而我们的项目 spring-ai-hunyuan 已经具备了正常的聊天对话功能,包括文本聊天和图片理解等基础功能。今天,我们进一步优化和扩展了该项目,新增了一个向量化功能。如图所示:
1.png

好的,首先就是对接API接口。我们开始。
向量功能

接口调用

腾讯的所有接口共享同一个域名,并且接口之间并没有按照请求路径进行细分。主要依赖请求头中的action字段来区分不同的接口调用。通过这种方式,接口能够在同一个域名下通过不同的请求头信息进行区分和处理,如下图所示:
2.png

所以,我们以前写的HunYuanAPI类就需要改一下,否则他默认走的全是聊天接口。修改如下:
  1. ResponseEntity<EmbeddingResponse> embeddingResponseResponseEntity = this.restClient.post().uri("/")
  2.         .header("X-TC-Action", HunYuanConstants.DEFAULT_EMBED_ACTION).body(embeddingRequest).retrieve().toEntity(EmbeddingResponse.class);
复制代码
在正常调用过程中,header字段用于区分不同的接口请求。这是因为在我使用的restClient加密方式中,采用了拦截器的形式。通过这种方式,每次请求发起时,拦截器都会被触发,从而使我能够轻松地读取到请求头中的相关信息。
这样一来,我可以在请求的整个生命周期内获取和处理这些信息。具体实现细节如下所示:
  1. @Override
  2. public ClientHttpResponse intercept(HttpRequest request, byte[] body, ClientHttpRequestExecution execution) throws IOException {
  3.     String action = request.getHeaders().getFirst("X-TC-Action");
  4.     MultiValueMap<String, String> httpHeadersConsumer = hunYuanAuthApi.getHttpHeadersConsumer(action, body);
  5.     .......
  6. }
复制代码
通过这种方式,我们不再依赖于写死的固定值来传递参数,而是能够动态地处理每次请求时的不同值。完成接口调用的处理后,接下来需要关注的是输入参数的管理与传递。
输入参数

这里的输入参数有两个可选值,如图所示:
3.png

为了简化对接过程,我们选择直接使用数组类型的输入形式。这种方式不仅使得数据传递更加直观和高效,而且与Spring AI的内部处理机制高度契合。Spring AI在处理数据时,本身也会将输入数据自动转化为数组形式进行处理,具体的实现方式如下所示:
  1. default float[] embed(String text) {
  2.     Assert.notNull(text, "Text must not be null");
  3.     List<float[]> response = this.embed(List.of(text));
  4.     return response.iterator().next();
  5. }
复制代码
输出参数

处理完了输入参数,那么紧接着就是输出参数了。如图所示:
4.png

但是,腾讯接口有一个共同特点,就是所有输出参数都被Response字段包围着。所以我们还需要单独处理一下,如下所示:
  1. ResponseEntity<EmbeddingResponse> embeddingResponseResponseEntity = this.restClient.post().uri("/")
  2.         .header("X-TC-Action", HunYuanConstants.DEFAULT_EMBED_ACTION).body(embeddingRequest).retrieve().toEntity(EmbeddingResponse.class);return embeddingResponseResponseEntity.getBody().response();
复制代码
EmbeddingResponse的结构如下:
  1. @JsonInclude(Include.NON_NULL)
  2. public record EmbeddingResponse(
  3.         // @formatter:off
  4.         @JsonProperty("Response") EmbeddingList response
  5. ) {
  6.     // @formatter:on
  7. }
  8. @JsonInclude(Include.NON_NULL)
  9. public record EmbeddingList(// @formatter:off
  10.                                @JsonProperty("RequestId") String object,
  11.                                @JsonProperty("Data") List<Embedding> data,
  12.                                @JsonProperty("Usage") Usage usage) { // @formatter:on
  13. }
复制代码
自动配置

在正常完成接口调用的编写之后,接下来我们需要着手进行Spring Boot的自动配置编写。
HunYuanEmbeddingProperties

首先一个配置类解析,将配置文件中的配置信息读取到类中,如下所示:
  1. @ConfigurationProperties(HunYuanEmbeddingProperties.CONFIG_PREFIX)
  2. public class HunYuanEmbeddingProperties extends HunYuanParentProperties {
  3.   
  4.     public static final String CONFIG_PREFIX = "spring.ai.hunyuan.embedding";
  5.     public static final String DEFAULT_EMBEDDING_MODEL = "hunyuan-embedding";
  6.     .......
  7. }
复制代码
HunYuanAutoConfiguration

这里就是单独配置一下我们需要的embedding模型的接口配置了。如图所示,先将配置类添加到注解中。
5.png

然后我们需要注入一下HunYuanEmbeddingModel模型。代码如下:
  1. @Bean
  2. @ConditionalOnMissingBean
  3. @ConditionalOnProperty(prefix = HunYuanEmbeddingProperties.CONFIG_PREFIX, name = "enabled", havingValue = "true",
  4.         matchIfMissing = true)
  5. public HunYuanEmbeddingModel hunYuanEmbeddingModel(HunYuanCommonProperties commonProperties,
  6.                                                   HunYuanEmbeddingProperties embeddingProperties, ObjectProvider<RestClient.Builder> restClientBuilderProvider,
  7.                                                   ObjectProvider<WebClient.Builder> webClientBuilderProvider, RetryTemplate retryTemplate,
  8.                                                   ResponseErrorHandler responseErrorHandler, ObjectProvider<ObservationRegistry> observationRegistry,
  9.                                                   ObjectProvider<EmbeddingModelObservationConvention> observationConvention) {
  10.     var hunyuanApi = hunyuanApi(embeddingProperties.getSecretId(), commonProperties.getSecretId(),
  11.             embeddingProperties.getSecretKey(), commonProperties.getSecretKey(), embeddingProperties.getBaseUrl(),
  12.             commonProperties.getBaseUrl(),
  13.             restClientBuilderProvider.getIfAvailable(RestClient::builder),responseErrorHandler);
  14.     var embeddingModel = new HunYuanEmbeddingModel(embeddingProperties.getOptions(), retryTemplate,hunyuanApi, embeddingProperties.getMetadataMode(),
  15.             observationRegistry.getIfUnique(() -> ObservationRegistry.NOOP));
  16.     observationConvention.ifAvailable(embeddingModel::setObservationConvention);
  17.     return embeddingModel;
  18. }
复制代码
这样一来,我们基本上已经完成了Spring-AI-Hunyuan中向量化功能的集成和配置工作,确保了系统能够顺利进行向量化处理,并与其他模块良好协作。接下来的步骤便是编写单元测试,由于单元测试的编写较为标准且常见,这部分内容就不再详细赘述。
小结

在本次更新中,我们进一步优化了spring-ai-hunyuan项目,新增了向量化功能。首先,我们对接了腾讯API,通过修改HunYuanAPI类来支持不同接口的调用,确保请求头能够正确区分接口类型。接着,我们处理了输入输出参数的管理,将数据以数组形式传递,并适应Spring AI的处理机制。同时,完成了Spring Boot自动配置,确保向量化功能能够顺利运行并与其他模块协同工作。
我是努力的小雨,一个正经的 Java 东北服务端开发,整天琢磨着 AI 技术这块儿的奥秘。特爱跟人交流技术,喜欢把自己的心得和大家分享。还当上了腾讯云创作之星,阿里云专家博主,华为云云享专家,掘金优秀作者。各种征文、开源比赛的牌子也拿了。


来源:程序园用户自行投稿发布,如果侵权,请联系站长删除
免责声明:如果侵犯了您的权益,请联系站长,我们会及时删除侵权内容,谢谢合作!
您需要登录后才可以回帖 登录 | 立即注册