init embedding

This commit is contained in:
Chuck1sn
2025-05-25 16:20:00 +08:00
parent 6e2cf11ec3
commit b6f72942ad
15 changed files with 1818 additions and 1674 deletions

View File

@@ -14,17 +14,17 @@ import org.springframework.context.annotation.DependsOn;
@Configuration @Configuration
@RequiredArgsConstructor @RequiredArgsConstructor
public class ChatModelConfig { public class ChatModelInitializer {
private final LlmService llmService; private final LlmService llmService;
private final PromptConfiguration promptConfiguration; private final PromptConfiguration promptConfiguration;
@Bean @Bean
@DependsOn("flywayInitializer") @DependsOn("flywayInitializer")
public ZhipuAiStreamingChatModel zhipuChatModel(ZhiPuConfiguration zhiPuConfiguration) { public ZhipuAiStreamingChatModel zhipuChatModel(ZhiPuChatModelConfig zhiPuChatModelConfig) {
return ZhipuAiStreamingChatModel.builder() return ZhipuAiStreamingChatModel.builder()
.model(zhiPuConfiguration.getModelName()) .model(zhiPuChatModelConfig.getModelName())
.apiKey(zhiPuConfiguration.getApiKey()) .apiKey(zhiPuChatModelConfig.getApiKey())
.logRequests(true) .logRequests(true)
.logResponses(true) .logResponses(true)
.build(); .build();
@@ -32,11 +32,12 @@ public class ChatModelConfig {
@Bean @Bean
@DependsOn("flywayInitializer") @DependsOn("flywayInitializer")
public OpenAiStreamingChatModel deepSeekChatModel(DeepSeekConfiguration deepSeekConfiguration) { public OpenAiStreamingChatModel deepSeekChatModel(
DeepSeekChatModelConfig deepSeekChatModelConfig) {
return OpenAiStreamingChatModel.builder() return OpenAiStreamingChatModel.builder()
.baseUrl(deepSeekConfiguration.getBaseUrl()) .baseUrl(deepSeekChatModelConfig.getBaseUrl())
.apiKey(deepSeekConfiguration.getApiKey()) .apiKey(deepSeekChatModelConfig.getApiKey())
.modelName(deepSeekConfiguration.getModelName()) .modelName(deepSeekChatModelConfig.getModelName())
.build(); .build();
} }
@@ -62,19 +63,19 @@ public class ChatModelConfig {
@Bean @Bean
@DependsOn("flywayInitializer") @DependsOn("flywayInitializer")
public DeepSeekConfiguration deepSeekConfiguration() { public DeepSeekChatModelConfig deepSeekConfiguration() {
DeepSeekConfiguration deepSeekConfiguration = new DeepSeekConfiguration(); DeepSeekChatModelConfig deepSeekChatModelConfig = new DeepSeekChatModelConfig();
AiLlmConfig deepSeek = llmService.loadConfig(LlmCodeEnum.DEEP_SEEK); AiLlmConfig deepSeek = llmService.loadConfig(LlmCodeEnum.DEEP_SEEK);
deepSeekConfiguration.init(deepSeek); deepSeekChatModelConfig.init(deepSeek);
return deepSeekConfiguration; return deepSeekChatModelConfig;
} }
@Bean @Bean
@DependsOn("flywayInitializer") @DependsOn("flywayInitializer")
public ZhiPuConfiguration zhiPuConfiguration() { public ZhiPuChatModelConfig zhiPuConfiguration() {
ZhiPuConfiguration zhiPuConfiguration = new ZhiPuConfiguration(); ZhiPuChatModelConfig zhiPuChatModelConfig = new ZhiPuChatModelConfig();
AiLlmConfig aiLlmConfig = llmService.loadConfig(LlmCodeEnum.ZHI_PU); AiLlmConfig aiLlmConfig = llmService.loadConfig(LlmCodeEnum.ZHI_PU);
zhiPuConfiguration.init(aiLlmConfig); zhiPuChatModelConfig.init(aiLlmConfig);
return zhiPuConfiguration; return zhiPuChatModelConfig;
} }
} }

View File

@@ -2,21 +2,17 @@ package com.zl.mjga.config.ai;
import lombok.Data; import lombok.Data;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig; import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
import org.springframework.stereotype.Component;
@Data @Data
@Component public class DeepSeekChatModelConfig {
public class ZhiPuConfiguration {
private String baseUrl; private String baseUrl;
private String apiKey; private String apiKey;
private String modelName; private String modelName;
private String embeddingModel;
public void init(AiLlmConfig config) { public void init(AiLlmConfig config) {
this.baseUrl = config.getUrl(); this.baseUrl = config.getUrl();
this.apiKey = config.getApiKey(); this.apiKey = config.getApiKey();
this.modelName = config.getModelName(); this.modelName = config.getModelName();
this.embeddingModel = config.getEmbeddingModel();
} }
} }

View File

@@ -1,5 +1,6 @@
package com.zl.mjga.config.ai; package com.zl.mjga.config.ai;
import com.zl.mjga.service.LlmService;
import dev.langchain4j.community.model.zhipu.ZhipuAiEmbeddingModel; import dev.langchain4j.community.model.zhipu.ZhipuAiEmbeddingModel;
import dev.langchain4j.data.segment.TextSegment; import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel; import dev.langchain4j.model.embedding.EmbeddingModel;
@@ -7,6 +8,8 @@ import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore; import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore;
import jakarta.annotation.Resource; import jakarta.annotation.Resource;
import lombok.RequiredArgsConstructor; import lombok.RequiredArgsConstructor;
import org.jooq.generated.mjga.enums.LlmCodeEnum;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration; import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.DependsOn; import org.springframework.context.annotation.DependsOn;
@@ -14,16 +17,26 @@ import org.springframework.core.env.Environment;
@Configuration @Configuration
@RequiredArgsConstructor @RequiredArgsConstructor
public class EmbeddingConfig { public class EmbeddingInitializer {
@Resource private Environment env; @Resource private Environment env;
private final LlmService llmService;
@Bean @Bean
@DependsOn("flywayInitializer") @DependsOn("flywayInitializer")
public EmbeddingModel zhipuEmbeddingModel(ZhiPuConfiguration zhiPuConfiguration) { public ZhiPuEmbeddingModelConfig zhiPuEmbeddingModelConfig() {
ZhiPuEmbeddingModelConfig zhiPuEmbeddingModelConfig = new ZhiPuEmbeddingModelConfig();
AiLlmConfig aiLlmConfig = llmService.loadConfig(LlmCodeEnum.ZHI_PU_EMBEDDING);
zhiPuEmbeddingModelConfig.init(aiLlmConfig);
return zhiPuEmbeddingModelConfig;
}
@Bean
@DependsOn("flywayInitializer")
public EmbeddingModel zhipuEmbeddingModel(ZhiPuEmbeddingModelConfig zhiPuEmbeddingModelConfig) {
return ZhipuAiEmbeddingModel.builder() return ZhipuAiEmbeddingModel.builder()
.apiKey(zhiPuConfiguration.getApiKey()) .apiKey(zhiPuEmbeddingModelConfig.getApiKey())
.model(zhiPuConfiguration.getEmbeddingModel()) .model(zhiPuEmbeddingModelConfig.getModelName())
.dimensions(2048) .dimensions(2048)
.build(); .build();
} }

View File

@@ -4,7 +4,7 @@ import lombok.Data;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig; import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
@Data @Data
public class DeepSeekConfiguration { public class ZhiPuChatModelConfig {
private String baseUrl; private String baseUrl;
private String apiKey; private String apiKey;

View File

@@ -0,0 +1,20 @@
package com.zl.mjga.config.ai;
import lombok.Data;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
@Data
public class ZhiPuEmbeddingModelConfig {
private String baseUrl;
private String apiKey;
private String modelName;
private Boolean enable;
public void init(AiLlmConfig config) {
this.baseUrl = config.getUrl();
this.apiKey = config.getApiKey();
this.modelName = config.getModelName();
this.enable = config.getEnable();
}
}

View File

@@ -1,3 +1,3 @@
package com.zl.mjga.dto.ai; package com.zl.mjga.dto.ai;
public record LlmQueryDto(String name) {} public record LlmQueryDto(String name, String type) {}

View File

@@ -9,6 +9,7 @@ import org.apache.commons.lang3.StringUtils;
import org.jooq.Configuration; import org.jooq.Configuration;
import org.jooq.Record; import org.jooq.Record;
import org.jooq.Result; import org.jooq.Result;
import org.jooq.generated.default_schema.enums.LlmTypeEnum;
import org.jooq.generated.mjga.tables.daos.AiLlmConfigDao; import org.jooq.generated.mjga.tables.daos.AiLlmConfigDao;
import org.jooq.impl.DSL; import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +32,10 @@ public class LlmRepository extends AiLlmConfigDao {
StringUtils.isNotEmpty(llmQueryDto.name()) StringUtils.isNotEmpty(llmQueryDto.name())
? AI_LLM_CONFIG.NAME.eq(llmQueryDto.name()) ? AI_LLM_CONFIG.NAME.eq(llmQueryDto.name())
: noCondition()) : noCondition())
.and(
StringUtils.isNotEmpty(llmQueryDto.type())
? AI_LLM_CONFIG.TYPE.eq(LlmTypeEnum.lookupLiteral(llmQueryDto.type()))
: noCondition())
.orderBy(pageRequestDto.getSortFields()) .orderBy(pageRequestDto.getSortFields())
.limit(pageRequestDto.getSize()) .limit(pageRequestDto.getSize())
.offset(pageRequestDto.getOffset()) .offset(pageRequestDto.getOffset())

View File

@@ -28,12 +28,13 @@ public class AiChatService {
} }
public TokenStream chatPrecedenceLlmWith(String sessionIdentifier, String userMessage) { public TokenStream chatPrecedenceLlmWith(String sessionIdentifier, String userMessage) {
Optional<AiLlmConfig> precedenceLlmBy = llmService.getPrecedenceLlmBy(true); Optional<AiLlmConfig> precedenceLlmBy = llmService.getPrecedenceChatLlmBy(true);
AiLlmConfig aiLlmConfig = precedenceLlmBy.orElseThrow(() -> new BusinessException("没有开启的大模型")); AiLlmConfig aiLlmConfig = precedenceLlmBy.orElseThrow(() -> new BusinessException("没有开启的大模型"));
LlmCodeEnum code = aiLlmConfig.getCode(); LlmCodeEnum code = aiLlmConfig.getCode();
return switch (code) { return switch (code) {
case ZHI_PU -> zhiPuChatAssistant.chat(sessionIdentifier, userMessage); case ZHI_PU -> zhiPuChatAssistant.chat(sessionIdentifier, userMessage);
case DEEP_SEEK -> deepSeekChatAssistant.chat(sessionIdentifier, userMessage); case DEEP_SEEK -> deepSeekChatAssistant.chat(sessionIdentifier, userMessage);
default -> throw new BusinessException(String.format("无效的模型代码 %s", code));
}; };
} }
} }

View File

@@ -2,6 +2,7 @@ package com.zl.mjga.service;
import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey; import static dev.langchain4j.store.embedding.filter.MetadataFilterBuilder.metadataKey;
import com.zl.mjga.config.ai.ZhiPuEmbeddingModelConfig;
import com.zl.mjga.model.urp.Actions; import com.zl.mjga.model.urp.Actions;
import dev.langchain4j.data.document.Metadata; import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.embedding.Embedding; import dev.langchain4j.data.embedding.Embedding;
@@ -27,6 +28,8 @@ public class EmbeddingService {
private final EmbeddingStore<TextSegment> zhiPuEmbeddingStore; private final EmbeddingStore<TextSegment> zhiPuEmbeddingStore;
private final ZhiPuEmbeddingModelConfig zhiPuEmbeddingModelConfig;
public Map<String, Object> searchAction(String message) { public Map<String, Object> searchAction(String message) {
Map<String, Object> result = new HashMap<>(); Map<String, Object> result = new HashMap<>();
EmbeddingSearchRequest embeddingSearchRequest = EmbeddingSearchRequest embeddingSearchRequest =
@@ -43,6 +46,9 @@ public class EmbeddingService {
@PostConstruct @PostConstruct
public void initActionIndex() { public void initActionIndex() {
if (!zhiPuEmbeddingModelConfig.getEnable()) {
return;
}
for (Actions action : Actions.values()) { for (Actions action : Actions.values()) {
Embedding queryEmbedding = zhipuEmbeddingModel.embed(action.getContent()).content(); Embedding queryEmbedding = zhipuEmbeddingModel.embed(action.getContent()).content();
Filter createUserFilter = metadataKey(Actions.INDEX_KEY).isEqualTo(action.getCode()); Filter createUserFilter = metadataKey(Actions.INDEX_KEY).isEqualTo(action.getCode());

View File

@@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.jooq.Record; import org.jooq.Record;
import org.jooq.Result; import org.jooq.Result;
import org.jooq.generated.default_schema.enums.LlmTypeEnum;
import org.jooq.generated.mjga.enums.LlmCodeEnum; import org.jooq.generated.mjga.enums.LlmCodeEnum;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig; import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
import org.springframework.beans.BeanUtils; import org.springframework.beans.BeanUtils;
@@ -28,9 +29,11 @@ public class LlmService {
return llmRepository.fetchOneByCode(llmCodeEnum); return llmRepository.fetchOneByCode(llmCodeEnum);
} }
public Optional<AiLlmConfig> getPrecedenceLlmBy(Boolean enable) { public Optional<AiLlmConfig> getPrecedenceChatLlmBy(Boolean enable) {
List<AiLlmConfig> aiLlmConfigs = llmRepository.fetchByEnable(enable); List<AiLlmConfig> aiLlmConfigs = llmRepository.fetchByEnable(enable);
return aiLlmConfigs.stream().max((o1, o2) -> o2.getPriority().compareTo(o1.getPriority())); return aiLlmConfigs.stream()
.filter(aiLlmConfig -> LlmTypeEnum.CHAT.equals(aiLlmConfig.getType()))
.max((o1, o2) -> o2.getPriority().compareTo(o1.getPriority()));
} }
public PageResponseDto<List<LlmVm>> pageQueryLlm( public PageResponseDto<List<LlmVm>> pageQueryLlm(

View File

@@ -68,16 +68,21 @@ CREATE TABLE mjga.user_position_map (
CREATE TYPE mjga.llm_code_enum AS ENUM ( CREATE TYPE mjga.llm_code_enum AS ENUM (
'DEEP_SEEK', 'DEEP_SEEK',
'ZHI_PU' 'ZHI_PU',
'ZHI_PU_EMBEDDING'
); );
CREATE TYPE "llm_type_enum" AS ENUM (
'CHAT',
'EMBEDDING'
);
CREATE TABLE mjga.ai_llm_config ( CREATE TABLE mjga.ai_llm_config (
id BIGSERIAL NOT NULL UNIQUE, id BIGSERIAL NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL UNIQUE,
code mjga.llm_code_enum NOT NULL UNIQUE, code mjga.llm_code_enum NOT NULL UNIQUE,
model_name VARCHAR(255) NOT NULL, model_name VARCHAR(255) NOT NULL,
embedding_model VARCHAR(255) NOT NULL, type LLM_TYPE_ENUM NOT NULL,
api_key VARCHAR(255) NOT NULL, api_key VARCHAR(255) NOT NULL,
url VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL,
enable BOOLEAN NOT NULL DEFAULT true, enable BOOLEAN NOT NULL DEFAULT true,

View File

@@ -33,7 +33,8 @@ VALUES (1, 1),
(1, 9), (1, 9),
(1, 10); (1, 10);
INSERT INTO mjga.ai_llm_config (name,code,model_name,embedding_model, api_key, url, enable, priority) INSERT INTO mjga.ai_llm_config (name,code,model_name, type, api_key, url, enable, priority)
VALUES VALUES
('DeepSeek','DEEP_SEEK','deepseek-chat','embedding-model-name','your_api_key', 'https://api.deepseek.com', false, 0), ('DeepSeek','DEEP_SEEK','deepseek-chat','CHAT','your_api_key', 'https://api.deepseek.com', false, 0),
('智谱清言','ZHI_PU','glm-4-flash','embedding-model-name', 'your_api_key', 'https://open.bigmodel.cn/', false, 1); ('智谱清言','ZHI_PU','glm-4-flash','CHAT', 'your_api_key', 'https://open.bigmodel.cn/', false, 1),
('智谱清言向量','ZHI_PU_EMBEDDING','Embeddings-3','EMBEDDING', 'your_api_key', 'https://open.bigmodel.cn/', false, 0);

View File

@@ -66,9 +66,23 @@ CREATE TABLE mjga.user_position_map (
FOREIGN KEY (position_id) REFERENCES mjga.position(id) ON UPDATE NO ACTION ON DELETE RESTRICT FOREIGN KEY (position_id) REFERENCES mjga.position(id) ON UPDATE NO ACTION ON DELETE RESTRICT
); );
CREATE TYPE mjga.llm_code_enum AS ENUM (
'DEEP_SEEK',
'ZHI_PU',
'ZHI_PU_EMBEDDING'
);
CREATE TYPE "llm_type_enum" AS ENUM (
'CHAT',
'EMBEDDING'
);
CREATE TABLE mjga.ai_llm_config ( CREATE TABLE mjga.ai_llm_config (
id BIGSERIAL NOT NULL UNIQUE, id BIGSERIAL NOT NULL UNIQUE,
name VARCHAR(255) NOT NULL UNIQUE, name VARCHAR(255) NOT NULL UNIQUE,
code mjga.llm_code_enum NOT NULL UNIQUE,
model_name VARCHAR(255) NOT NULL,
type LLM_TYPE_ENUM NOT NULL,
api_key VARCHAR(255) NOT NULL, api_key VARCHAR(255) NOT NULL,
url VARCHAR(255) NOT NULL, url VARCHAR(255) NOT NULL,
enable BOOLEAN NOT NULL DEFAULT true, enable BOOLEAN NOT NULL DEFAULT true,

View File

@@ -747,6 +747,39 @@
} }
} }
}, },
"/ai/action/chat": {
"post": {
"tags": [
"ai-controller"
],
"operationId": "actionChat",
"requestBody": {
"content": {
"application/json": {
"schema": {
"type": "string"
}
}
},
"required": true
},
"responses": {
"200": {
"description": "OK",
"content": {
"*/*": {
"schema": {
"type": "object",
"additionalProperties": {
"type": "object"
}
}
}
}
}
}
}
},
"/scheduler/page-query": { "/scheduler/page-query": {
"get": { "get": {
"tags": [ "tags": [
@@ -1788,6 +1821,9 @@
"properties": { "properties": {
"name": { "name": {
"type": "string" "type": "string"
},
"type": {
"type": "string"
} }
} }
}, },

File diff suppressed because it is too large Load Diff