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

View File

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

View File

@@ -1,5 +1,6 @@
package com.zl.mjga.config.ai;
import com.zl.mjga.service.LlmService;
import dev.langchain4j.community.model.zhipu.ZhipuAiEmbeddingModel;
import dev.langchain4j.data.segment.TextSegment;
import dev.langchain4j.model.embedding.EmbeddingModel;
@@ -7,6 +8,8 @@ import dev.langchain4j.store.embedding.EmbeddingStore;
import dev.langchain4j.store.embedding.pgvector.PgVectorEmbeddingStore;
import jakarta.annotation.Resource;
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.Configuration;
import org.springframework.context.annotation.DependsOn;
@@ -14,16 +17,26 @@ import org.springframework.core.env.Environment;
@Configuration
@RequiredArgsConstructor
public class EmbeddingConfig {
public class EmbeddingInitializer {
@Resource private Environment env;
private final LlmService llmService;
@Bean
@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()
.apiKey(zhiPuConfiguration.getApiKey())
.model(zhiPuConfiguration.getEmbeddingModel())
.apiKey(zhiPuEmbeddingModelConfig.getApiKey())
.model(zhiPuEmbeddingModelConfig.getModelName())
.dimensions(2048)
.build();
}

View File

@@ -4,7 +4,7 @@ import lombok.Data;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
@Data
public class DeepSeekConfiguration {
public class ZhiPuChatModelConfig {
private String baseUrl;
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;
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.Record;
import org.jooq.Result;
import org.jooq.generated.default_schema.enums.LlmTypeEnum;
import org.jooq.generated.mjga.tables.daos.AiLlmConfigDao;
import org.jooq.impl.DSL;
import org.springframework.beans.factory.annotation.Autowired;
@@ -31,6 +32,10 @@ public class LlmRepository extends AiLlmConfigDao {
StringUtils.isNotEmpty(llmQueryDto.name())
? AI_LLM_CONFIG.NAME.eq(llmQueryDto.name())
: noCondition())
.and(
StringUtils.isNotEmpty(llmQueryDto.type())
? AI_LLM_CONFIG.TYPE.eq(LlmTypeEnum.lookupLiteral(llmQueryDto.type()))
: noCondition())
.orderBy(pageRequestDto.getSortFields())
.limit(pageRequestDto.getSize())
.offset(pageRequestDto.getOffset())

View File

@@ -28,12 +28,13 @@ public class AiChatService {
}
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("没有开启的大模型"));
LlmCodeEnum code = aiLlmConfig.getCode();
return switch (code) {
case ZHI_PU -> zhiPuChatAssistant.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 com.zl.mjga.config.ai.ZhiPuEmbeddingModelConfig;
import com.zl.mjga.model.urp.Actions;
import dev.langchain4j.data.document.Metadata;
import dev.langchain4j.data.embedding.Embedding;
@@ -27,6 +28,8 @@ public class EmbeddingService {
private final EmbeddingStore<TextSegment> zhiPuEmbeddingStore;
private final ZhiPuEmbeddingModelConfig zhiPuEmbeddingModelConfig;
public Map<String, Object> searchAction(String message) {
Map<String, Object> result = new HashMap<>();
EmbeddingSearchRequest embeddingSearchRequest =
@@ -43,6 +46,9 @@ public class EmbeddingService {
@PostConstruct
public void initActionIndex() {
if (!zhiPuEmbeddingModelConfig.getEnable()) {
return;
}
for (Actions action : Actions.values()) {
Embedding queryEmbedding = zhipuEmbeddingModel.embed(action.getContent()).content();
Filter createUserFilter = metadataKey(Actions.INDEX_KEY).isEqualTo(action.getCode());

View File

@@ -12,6 +12,7 @@ import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.jooq.Record;
import org.jooq.Result;
import org.jooq.generated.default_schema.enums.LlmTypeEnum;
import org.jooq.generated.mjga.enums.LlmCodeEnum;
import org.jooq.generated.mjga.tables.pojos.AiLlmConfig;
import org.springframework.beans.BeanUtils;
@@ -28,9 +29,11 @@ public class LlmService {
return llmRepository.fetchOneByCode(llmCodeEnum);
}
public Optional<AiLlmConfig> getPrecedenceLlmBy(Boolean enable) {
public Optional<AiLlmConfig> getPrecedenceChatLlmBy(Boolean 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(

View File

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

View File

@@ -33,7 +33,8 @@ VALUES (1, 1),
(1, 9),
(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
('DeepSeek','DEEP_SEEK','deepseek-chat','embedding-model-name','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);
('DeepSeek','DEEP_SEEK','deepseek-chat','CHAT','your_api_key', 'https://api.deepseek.com', false, 0),
('智谱清言','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
);
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 (
id BIGSERIAL 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,
url VARCHAR(255) NOT NULL,
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": {
"get": {
"tags": [
@@ -1788,6 +1821,9 @@
"properties": {
"name": {
"type": "string"
},
"type": {
"type": "string"
}
}
},

File diff suppressed because it is too large Load Diff