1.9.0后端

fix(AI):完成AI向量数据库连接机制
master
xs 6 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.AiChatMessageVo;
import org.dromara.ai.domain.vo.AiModelVo; import org.dromara.ai.domain.vo.AiModelVo;
import org.dromara.ai.process.dto.AIFillFormRequest; 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.AIMessage;
import org.dromara.ai.process.dto.AIRequest; import org.dromara.ai.process.dto.AIRequest;
import org.dromara.ai.process.dto.AIResponse; 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.AIRequest;
import org.dromara.ai.process.dto.AIResponse; import org.dromara.ai.process.dto.AIResponse;
import org.dromara.ai.process.dto.TokenUsage; 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.process.provider.processor.IUnifiedAIProviderProcessor;
import org.dromara.ai.test.ChatRequest;
import org.dromara.common.constant.HwMomAiConstants; import org.dromara.common.constant.HwMomAiConstants;
import org.dromara.common.encrypt.utils.EncryptUtils; import org.dromara.common.encrypt.utils.EncryptUtils;
import org.dromara.common.satoken.utils.LoginHelper;
import org.dromara.system.api.model.LoginUser; import org.dromara.system.api.model.LoginUser;
import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.HttpHeaders; import org.springframework.http.HttpHeaders;

@ -11,12 +11,11 @@ import com.tencentcloudapi.lkeap.v20240522.models.GetEmbeddingResponse;
import com.tencentcloudapi.lkeap.v20240522.models.Usage; import com.tencentcloudapi.lkeap.v20240522.models.Usage;
import lombok.extern.slf4j.Slf4j; import lombok.extern.slf4j.Slf4j;
import org.dromara.ai.domain.dto.StreamResult; 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.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.AIRequest;
import org.dromara.ai.process.dto.AIResponse; import org.dromara.ai.process.dto.AIResponse;
import org.dromara.ai.process.enums.AIProviderEnum; 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.common.encrypt.utils.EncryptUtils;
import org.dromara.system.api.model.LoginUser; import org.dromara.system.api.model.LoginUser;
import org.springframework.stereotype.Component; import org.springframework.stereotype.Component;

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

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

Loading…
Cancel
Save