1.9.0后端

fix(AI):完成AI向量数据库连接机制
master
xs 4 days ago
parent dbc5242fa3
commit 651c9b4d0a

@ -16,8 +16,6 @@ import org.dromara.ai.domain.bo.AiModelBo;
import org.dromara.ai.domain.vo.AiChatMessageVo;
import org.dromara.ai.domain.vo.AiModelVo;
import org.dromara.ai.process.dto.AIFillFormRequest;
import org.dromara.ai.test.vectorization.factory.EmbeddingServiceFactory;
import org.dromara.ai.test.vectorization.process.IEmbeddingProcessor;
import org.dromara.ai.process.dto.AIMessage;
import org.dromara.ai.process.dto.AIRequest;
import org.dromara.ai.process.dto.AIResponse;

@ -0,0 +1,111 @@
package org.dromara.ai.process.config;
import lombok.Data;
import org.dromara.ai.process.enums.EmbeddingProviderEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;
/**
* @author xins
* @description
* @date 2025/8/5 16:30
*/
@Data
@Configuration
@ConfigurationProperties(prefix = "embedding")
public class EmbeddingConfig {
/**
*
*/
private EmbeddingProviderEnum defaultProvider = EmbeddingProviderEnum.TENCENTLKE;
/**
*
*/
private TencentLKE tencentLke = new TencentLKE();
/**
* OpenAI
*/
private Openai openai = new Openai();
/**
*
*/
private Local local = new Local();
/**
*
*/
@Data
public static class TencentLKE {
/**
* APIID
*/
private String secretId;
/**
* APIKey
*/
private String secretKey;
/**
* ap-guangzhou
*/
private String region = "ap-guangzhou";
/**
* 使lke-text-embedding-v1
*/
private String model = "lke-text-embedding-v1";
}
/**
* OpenAI
*/
@Data
public static class Openai {
/**
* OpenAI API
*/
private String apiKey;
/**
* 使text-embedding-ada-002
*/
private String model = "text-embedding-ada-002";
/**
* ID
*/
private String organization;
/**
*
*/
private String proxyHost;
/**
*
*/
private Integer proxyPort;
}
/**
*
*/
@Data
public static class Local {
private String baseUrl = "http://localhost:11434";
/**
* llama2
*/
private String model = "llama2";
/**
* 30
*/
private Integer timeout = 30;
}
}

@ -0,0 +1,37 @@
package org.dromara.ai.process.enums;
/**
* @Author xins
* @Date 2025/8/5 14:28
* @Description:
*/
public enum EmbeddingProviderEnum {
TENCENTLKE("tencentlke", "Tencent LKE"),
OPENAI("openai", "OpenAI"),
OLLAMA("ollma", "Local Model");
private final String code;
private final String name;
EmbeddingProviderEnum(String code, String name) {
this.code = code;
this.name = name;
}
public String getCode() {
return code;
}
public String getName() {
return name;
}
public static EmbeddingProviderEnum fromString(String code) {
for (EmbeddingProviderEnum provider : values()) {
if (provider.code.equalsIgnoreCase(code)) {
return provider;
}
}
throw new IllegalArgumentException("Unknown provider code: " + code);
}
}

@ -19,12 +19,9 @@ import org.dromara.ai.process.dto.AIMessage;
import org.dromara.ai.process.dto.AIRequest;
import org.dromara.ai.process.dto.AIResponse;
import org.dromara.ai.process.dto.TokenUsage;
import org.dromara.ai.process.enums.AIChatMessageTypeEnum;
import org.dromara.ai.process.provider.processor.IUnifiedAIProviderProcessor;
import org.dromara.ai.test.ChatRequest;
import org.dromara.common.constant.HwMomAiConstants;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders;

@ -11,12 +11,11 @@ import com.tencentcloudapi.lkeap.v20240522.models.GetEmbeddingResponse;
import com.tencentcloudapi.lkeap.v20240522.models.Usage;
import lombok.extern.slf4j.Slf4j;
import org.dromara.ai.domain.dto.StreamResult;
import org.dromara.ai.process.config.EmbeddingConfig;
import org.dromara.ai.process.provider.processor.utils.ProcessorUtils;
import org.dromara.ai.test.vectorization.config.EmbeddingConfig;
import org.dromara.ai.process.dto.AIRequest;
import org.dromara.ai.process.dto.AIResponse;
import org.dromara.ai.process.enums.AIProviderEnum;
import org.dromara.ai.process.provider.processor.IUnifiedAIProviderProcessor;
import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.system.api.model.LoginUser;
import org.springframework.stereotype.Component;

@ -1,145 +1,145 @@
package org.dromara.ai.service.impl;
import org.dromara.ai.mapper.SQLServerDatabaseMetaMapper;
import org.dromara.ai.test.ChatRequest;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;
/**
* @Author xins
* @Date 2025/7/8 9:25
* @Description:
*/
@Service
public class DatabaseMetaServiceImpl {
@Autowired
private SQLServerDatabaseMetaMapper databaseMetaMapper;
/**
*
*/
public String getFormattedSchema() {
List<Map<String, Object>> allColumns = databaseMetaMapper.getAllTablesStructure();
Map<String, List<Map<String, Object>>> tables = allColumns.stream()
.collect(Collectors.groupingBy(
col -> (String) col.get("tableName"),
LinkedHashMap::new,
Collectors.toList()
));
StringBuilder sb = new StringBuilder("SQL Server 数据库结构:\n\n");
for (Map.Entry<String, List<Map<String, Object>>> entry : tables.entrySet()) {
String tableName = entry.getKey();
List<String> primaryKeys = databaseMetaMapper.getPrimaryKeys(tableName);
sb.append("- 表名: ").append(tableName).append("\n");
sb.append(" 主键: ").append(String.join(", ", primaryKeys)).append("\n");
sb.append(" 字段:\n");
for (Map<String, Object> column : entry.getValue()) {
sb.append(" * ")
.append(column.get("columnName"))
.append(" (").append(column.get("dataType"));
if (column.get("maxLength") != null && (short)column.get("maxLength") > 0) {
sb.append(", 长度: ").append(column.get("maxLength"));
}
if (column.get("precision") != null && (short)column.get("precision") > 0) {
sb.append(", 精度: ").append(column.get("precision"));
}
if (column.get("scale") != null && (short)column.get("scale") > 0) {
sb.append(", 小数位: ").append(column.get("scale"));
}
sb.append(column.get("nullable").equals(1) ? ", 可空" : ", 非空");
if (!((String)column.get("defaultValue")).isEmpty()) {
sb.append(", 默认值: ").append(column.get("defaultValue"));
}
if (!((String)column.get("description")).isEmpty()) {
sb.append(", 描述: ").append(column.get("description"));
}
sb.append(")\n");
}
sb.append("\n");
}
return sb.toString();
}
public String generateSQL(String naturalLanguageQuery) {
// 1. 获取数据库结构
String schemaDescription = this.getFormattedSchema();
// 2. 构建 AI 提示
String prompt = String.format(
"你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
"请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
"---\n%s\n---\n\n" +
"要求:\n" +
"1. 只返回 SQL 语句,不要包含解释\n" +
"2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT\n" +
"3. 考虑性能优化\n" +
"4. 使用合适的索引提示(如果需要)\n" +
"5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
"6. 使用 ANSI 标准的 JOIN 语法",
schemaDescription, naturalLanguageQuery
);
ChatRequest chatRequest = new ChatRequest();
chatRequest.setPrompt(prompt);
return prompt;
}
/**
*
*/
public Map<String, Object> getTableDetail(String tableName) {
Map<String, Object> result = new LinkedHashMap<>();
result.put("tableName", tableName);
result.put("primaryKeys", databaseMetaMapper.getPrimaryKeys(tableName));
result.put("columns", databaseMetaMapper.getTableStructure(tableName));
return result;
}
public String generateSQL1(String naturalLanguageQuery) {
// 1. 获取数据库结构
String schemaDescription = this.getFormattedSchema();
// 2. 构建 AI 提示
String prompt = String.format(
"你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
"请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
"---\n%s\n---\n\n" +
"要求:\n" +
"1. 只返回 SQL 语句,不要包含解释\n" +
"2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT\n" +
"3. 考虑性能优化\n" +
"4. 使用合适的索引提示(如果需要)\n" +
"5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
"6. 使用 ANSI 标准的 JOIN 语法",
schemaDescription, naturalLanguageQuery
);
return prompt;
}
}
//package org.dromara.ai.service.impl;
//
//import org.dromara.ai.mapper.SQLServerDatabaseMetaMapper;
//import org.dromara.ai.test.ChatRequest;
//import org.springframework.beans.factory.annotation.Autowired;
//import org.springframework.stereotype.Service;
//
//import java.util.LinkedHashMap;
//import java.util.List;
//import java.util.Map;
//import java.util.stream.Collectors;
//
///**
// * @Author xins
// * @Date 2025/7/8 9:25
// * @Description:
// */
//@Service
//public class DatabaseMetaServiceImpl {
//
// @Autowired
// private SQLServerDatabaseMetaMapper databaseMetaMapper;
//
// /**
// * 获取格式化的数据库结构描述
// */
// public String getFormattedSchema() {
// List<Map<String, Object>> allColumns = databaseMetaMapper.getAllTablesStructure();
//
// Map<String, List<Map<String, Object>>> tables = allColumns.stream()
// .collect(Collectors.groupingBy(
// col -> (String) col.get("tableName"),
// LinkedHashMap::new,
// Collectors.toList()
// ));
//
// StringBuilder sb = new StringBuilder("SQL Server 数据库结构:\n\n");
//
// for (Map.Entry<String, List<Map<String, Object>>> entry : tables.entrySet()) {
// String tableName = entry.getKey();
// List<String> primaryKeys = databaseMetaMapper.getPrimaryKeys(tableName);
//
// sb.append("- 表名: ").append(tableName).append("\n");
// sb.append(" 主键: ").append(String.join(", ", primaryKeys)).append("\n");
// sb.append(" 字段:\n");
//
// for (Map<String, Object> column : entry.getValue()) {
// sb.append(" * ")
// .append(column.get("columnName"))
// .append(" (").append(column.get("dataType"));
//
// if (column.get("maxLength") != null && (short)column.get("maxLength") > 0) {
// sb.append(", 长度: ").append(column.get("maxLength"));
// }
// if (column.get("precision") != null && (short)column.get("precision") > 0) {
// sb.append(", 精度: ").append(column.get("precision"));
// }
// if (column.get("scale") != null && (short)column.get("scale") > 0) {
// sb.append(", 小数位: ").append(column.get("scale"));
// }
//
// sb.append(column.get("nullable").equals(1) ? ", 可空" : ", 非空");
//
// if (!((String)column.get("defaultValue")).isEmpty()) {
// sb.append(", 默认值: ").append(column.get("defaultValue"));
// }
//
// if (!((String)column.get("description")).isEmpty()) {
// sb.append(", 描述: ").append(column.get("description"));
// }
//
// sb.append(")\n");
// }
// sb.append("\n");
// }
//
// return sb.toString();
// }
//
//
// public String generateSQL(String naturalLanguageQuery) {
// // 1. 获取数据库结构
// String schemaDescription = this.getFormattedSchema();
//
// // 2. 构建 AI 提示
// String prompt = String.format(
// "你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
// "请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
// "---\n%s\n---\n\n" +
// "要求:\n" +
// "1. 只返回 SQL 语句,不要包含解释\n" +
// "2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT\n" +
// "3. 考虑性能优化\n" +
// "4. 使用合适的索引提示(如果需要)\n" +
// "5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
// "6. 使用 ANSI 标准的 JOIN 语法",
// schemaDescription, naturalLanguageQuery
// );
//
// ChatRequest chatRequest = new ChatRequest();
// chatRequest.setPrompt(prompt);
//
// return prompt;
//
// }
//
//
// /**
// * 获取表的结构信息
// */
// public Map<String, Object> getTableDetail(String tableName) {
// Map<String, Object> result = new LinkedHashMap<>();
// result.put("tableName", tableName);
// result.put("primaryKeys", databaseMetaMapper.getPrimaryKeys(tableName));
// result.put("columns", databaseMetaMapper.getTableStructure(tableName));
// return result;
// }
//
//
//
//
//
// public String generateSQL1(String naturalLanguageQuery) {
// // 1. 获取数据库结构
// String schemaDescription = this.getFormattedSchema();
//
// // 2. 构建 AI 提示
// String prompt = String.format(
// "你是一个专业的 SQL Server 数据库专家。根据以下数据库结构:\n\n%s\n\n" +
// "请将以下自然语言查询转换为优化的 SQL Server T-SQL 语句:\n" +
// "---\n%s\n---\n\n" +
// "要求:\n" +
// "1. 只返回 SQL 语句,不要包含解释\n" +
// "2. 使用 SQL Server 特有的语法(如 TOP 而不是 LIMIT\n" +
// "3. 考虑性能优化\n" +
// "4. 使用合适的索引提示(如果需要)\n" +
// "5. 包含必要的 WITH(NOLOCK) 提示(适用于高并发环境)\n" +
// "6. 使用 ANSI 标准的 JOIN 语法",
// schemaDescription, naturalLanguageQuery
// );
//
// return prompt;
// }
//
//}

@ -1,7 +1,6 @@
package org.dromara.ai.vectordb.config;
import lombok.Data;
import org.dromara.ai.test.vectorization.enums.EmbeddingProviderEnum;
import org.dromara.ai.vectordb.enums.VectorDBTypeEnum;
import org.springframework.boot.context.properties.ConfigurationProperties;
import org.springframework.context.annotation.Configuration;

Loading…
Cancel
Save