diff --git a/frontend/src/api/vector-store.ts b/frontend/src/api/vector-store.ts new file mode 100644 index 000000000..f9aeafe23 --- /dev/null +++ b/frontend/src/api/vector-store.ts @@ -0,0 +1,64 @@ +import { get, post, put, del } from '@/utils/request' + +// ===== Types ===== + +export interface VectorStoreEntity { + id?: string + name: string + engine_type: string + connection_config: Record + index_config: Record + source: 'env' | 'user' + readonly: boolean + tenant_id?: number + created_at?: string + updated_at?: string +} + +export interface VectorStoreTypeInfo { + type: string + display_name: string + connection_fields: FieldSchema[] + index_fields: FieldSchema[] +} + +export interface FieldSchema { + name: string + type: 'string' | 'number' | 'boolean' + required: boolean + sensitive?: boolean + description?: string + default?: any +} + +// ===== API Functions ===== + +export function listVectorStoreTypes(): Promise { + return get('/api/v1/vector-stores/types').then((res: any) => { + return res.success && res.data ? res.data : [] + }) +} + +export function listVectorStores(): Promise<{ success: boolean; data: VectorStoreEntity[] }> { + return get('/api/v1/vector-stores') +} + +export function createVectorStore(data: Partial) { + return post('/api/v1/vector-stores', data) +} + +export function updateVectorStore(id: string, data: Partial) { + return put(`/api/v1/vector-stores/${id}`, data) +} + +export function deleteVectorStore(id: string) { + return del(`/api/v1/vector-stores/${id}`) +} + +export function testVectorStoreRaw(data: { engine_type: string; connection_config: any }): Promise { + return post('/api/v1/vector-stores/test', data) +} + +export function testVectorStoreById(id: string): Promise { + return post(`/api/v1/vector-stores/${id}/test`, {}) +} diff --git a/frontend/src/i18n/locales/en-US.ts b/frontend/src/i18n/locales/en-US.ts index 4bed7b8f2..b6c1bcb99 100755 --- a/frontend/src/i18n/locales/en-US.ts +++ b/frontend/src/i18n/locales/en-US.ts @@ -573,6 +573,7 @@ export default { autoCheckUpdateDesc: 'When enabled, automatically check and download the latest version in the background.', memoryRequiresNeo4j: 'Memory feature requires Neo4j graph database. Please configure and enable Neo4j (set NEO4J_ENABLE=true) before enabling this feature.', memoryHowToEnable: 'View Neo4j Configuration Guide', + vectorStoreEngine: 'Vector DB Engine', parserEngine: 'Parser Engine', storageEngine: 'Storage Engine', mcpService: 'MCP Service', @@ -807,6 +808,61 @@ export default { testFailed: 'Connection test failed', } }, + vectorStoreSettings: { + title: 'Vector Database Engine', + description: 'Register and manage vector database instances for knowledge base search.', + storesTitle: 'Vector Databases', + addStore: 'Add Database', + editStore: 'Edit Database', + deleteConfirm: 'Are you sure you want to delete this vector database?', + emptyDesc: 'No vector databases configured. Click "Add Database" to get started.', + engineTypeLabel: 'Engine Type', + nameLabel: 'Name', + namePlaceholder: 'e.g., my-vector-store', + connectionInfo: 'Connection Info', + advancedIndexConfig: 'Advanced Settings', + fields: { + addr: 'URL', + host: 'Host', + port: 'Port', + username: 'Username', + password: 'Password', + api_key: 'API Key', + use_tls: 'Use TLS', + scheme: 'Scheme', + grpc_address: 'gRPC Address', + use_default_connection: 'Use Default Connection', + index_name: 'Index Name', + number_of_shards: 'Shards', + number_of_replicas: 'Replicas', + collection_prefix: 'Collection Prefix', + collection_name: 'Collection Name', + shard_number: 'Shard Number', + replication_factor: 'Replication Factor', + shards_num: 'Shards', + replica_number: 'In-memory Replicas', + desired_shard_count: 'Shard Count', + }, + envTag: 'DEFAULT', + testConnection: 'Test Connection', + testing: 'Testing...', + immutableNotice: 'Engine type, connection, and index settings cannot be changed after creation.\nTo change these, delete and recreate.', + validation: { + nameRequired: 'Name is required', + engineTypeRequired: 'Engine type is required', + fieldRequired: '{field} is required', + indexNamePattern: 'Must start with a letter. Only letters, numbers, underscore, and hyphen allowed (max 128)', + }, + toasts: { + storeCreated: 'Vector database created', + storeUpdated: 'Vector database updated', + storeDeleted: 'Vector database deleted', + testSuccess: 'Connection test succeeded', + testFailed: 'Connection test failed', + duplicateName: 'A vector database with this name already exists', + errorGeneric: 'An error occurred. Please try again.', + }, + }, chatHistorySettings: { title: 'Message Management', description: 'Configure chat history knowledge base to automatically index conversation messages for semantic search', diff --git a/frontend/src/i18n/locales/ko-KR.ts b/frontend/src/i18n/locales/ko-KR.ts index 7071150c8..3d56ad798 100755 --- a/frontend/src/i18n/locales/ko-KR.ts +++ b/frontend/src/i18n/locales/ko-KR.ts @@ -435,6 +435,7 @@ export default { autoCheckUpdateDesc: '활성화하면 시작 시 최신 버전을 자동으로 확인하고 백그라운드에서 다운로드합니다.', memoryRequiresNeo4j: "기억 기능은 Neo4j 그래프 데이터베이스가 필요합니다. 이 기능을 활성화하기 전에 Neo4j를 구성하고 활성화해 주세요 (NEO4J_ENABLE=true 설정).", memoryHowToEnable: "Neo4j 구성 가이드 보기", + vectorStoreEngine: "벡터 DB 엔진", parserEngine: "파싱 엔진", storageEngine: "스토리지 엔진", mcpService: "MCP 서비스", @@ -666,6 +667,61 @@ export default { providerDeleted: "검색 엔진 프로바이더가 삭제되었습니다", }, }, + vectorStoreSettings: { + title: "벡터 데이터베이스 엔진", + description: "지식 베이스 검색을 위한 벡터 데이터베이스 인스턴스를 등록하고 관리합니다.", + storesTitle: "벡터 데이터베이스", + addStore: "데이터베이스 추가", + editStore: "데이터베이스 수정", + deleteConfirm: "이 벡터 데이터베이스를 삭제하시겠습니까?", + emptyDesc: "구성된 벡터 데이터베이스가 없습니다. '데이터베이스 추가'를 클릭하여 시작하세요.", + engineTypeLabel: "엔진 타입", + nameLabel: "이름", + namePlaceholder: "예: my-vector-store", + connectionInfo: "연결 정보", + advancedIndexConfig: "고급 설정", + fields: { + addr: "URL", + host: "호스트", + port: "포트", + username: "사용자명", + password: "비밀번호", + api_key: "API 키", + use_tls: "TLS 사용", + scheme: "프로토콜", + grpc_address: "gRPC 주소", + use_default_connection: "기본 연결 사용", + index_name: "인덱스 이름", + number_of_shards: "샤드 수", + number_of_replicas: "레플리카 수", + collection_prefix: "컬렉션 접두사", + collection_name: "컬렉션 이름", + shard_number: "샤드 수", + replication_factor: "레플리카 팩터", + shards_num: "샤드 수", + replica_number: "인메모리 레플리카", + desired_shard_count: "샤드 수", + }, + envTag: "DEFAULT", + testConnection: "연결 테스트", + testing: "테스트 중...", + immutableNotice: "엔진 타입, 연결 정보, 인덱스 설정은 생성 후 변경할 수 없습니다.\n변경이 필요하면 삭제 후 다시 생성하세요.", + validation: { + nameRequired: "이름은 필수입니다", + engineTypeRequired: "엔진 타입은 필수입니다", + fieldRequired: "{field}은(는) 필수입니다", + indexNamePattern: "영문자로 시작해야 합니다. 영문, 숫자, 밑줄, 하이픈만 허용 (최대 128자)", + }, + toasts: { + storeCreated: "벡터 데이터베이스가 생성되었습니다", + storeUpdated: "벡터 데이터베이스가 수정되었습니다", + storeDeleted: "벡터 데이터베이스가 삭제되었습니다", + testSuccess: "연결 테스트 성공", + testFailed: "연결 테스트 실패", + duplicateName: "동일한 이름의 벡터 데이터베이스가 이미 존재합니다", + errorGeneric: "오류가 발생했습니다. 다시 시도해 주세요.", + }, + }, chatHistorySettings: { title: "메시지 관리", description: "채팅 기록 지식베이스를 구성하여 대화 메시지를 자동으로 벡터화 인덱싱하여 시맨틱 검색을 지원합니다", diff --git a/frontend/src/i18n/locales/ru-RU.ts b/frontend/src/i18n/locales/ru-RU.ts index 022f76e9a..dbe1cd548 100755 --- a/frontend/src/i18n/locales/ru-RU.ts +++ b/frontend/src/i18n/locales/ru-RU.ts @@ -552,6 +552,7 @@ export default { autoCheckUpdateDesc: 'При включении автоматически проверять и скачивать последнюю версию в фоновом режиме при запуске.', memoryRequiresNeo4j: 'Функция памяти требует графовую базу данных Neo4j. Пожалуйста, настройте и включите Neo4j (установите NEO4J_ENABLE=true) перед активацией этой функции.', memoryHowToEnable: 'Руководство по настройке Neo4j', + vectorStoreEngine: 'Движок векторной БД', parserEngine: 'Движок парсинга', storageEngine: 'Движок хранения', mcpService: 'Сервис MCP', @@ -785,6 +786,61 @@ export default { providerDeleted: 'Поисковый провайдер удалён', } }, + vectorStoreSettings: { + title: 'Движок векторной базы данных', + description: 'Регистрация и управление экземплярами векторных баз данных для поиска по базе знаний.', + storesTitle: 'Векторные базы данных', + addStore: 'Добавить базу данных', + editStore: 'Редактировать базу данных', + deleteConfirm: 'Вы уверены, что хотите удалить эту векторную базу данных?', + emptyDesc: 'Векторные базы данных не настроены. Нажмите "Добавить базу данных", чтобы начать.', + engineTypeLabel: 'Тип движка', + nameLabel: 'Название', + namePlaceholder: 'например, my-vector-store', + connectionInfo: 'Информация о подключении', + advancedIndexConfig: 'Расширенные настройки', + fields: { + addr: 'URL', + host: 'Хост', + port: 'Порт', + username: 'Имя пользователя', + password: 'Пароль', + api_key: 'API ключ', + use_tls: 'Использовать TLS', + scheme: 'Схема', + grpc_address: 'gRPC адрес', + use_default_connection: 'Использовать подключение по умолчанию', + index_name: 'Имя индекса', + number_of_shards: 'Шарды', + number_of_replicas: 'Реплики', + collection_prefix: 'Префикс коллекции', + collection_name: 'Имя коллекции', + shard_number: 'Количество шардов', + replication_factor: 'Фактор репликации', + shards_num: 'Шарды', + replica_number: 'Реплики в памяти', + desired_shard_count: 'Количество шардов', + }, + envTag: 'DEFAULT', + testConnection: 'Тест подключения', + testing: 'Тестирование...', + immutableNotice: 'Тип движка, подключение и настройки индекса нельзя изменить после создания.\nДля изменения удалите и создайте заново.', + validation: { + nameRequired: 'Название обязательно', + engineTypeRequired: 'Тип движка обязателен', + fieldRequired: '{field} обязательно', + indexNamePattern: 'Должно начинаться с буквы. Допускаются только буквы, цифры, подчёркивание и дефис (макс. 128)', + }, + toasts: { + storeCreated: 'Векторная база данных создана', + storeUpdated: 'Векторная база данных обновлена', + storeDeleted: 'Векторная база данных удалена', + testSuccess: 'Тест подключения успешен', + testFailed: 'Тест подключения не удался', + duplicateName: 'Векторная база данных с таким именем уже существует', + errorGeneric: 'Произошла ошибка. Попробуйте снова.', + }, + }, chatHistorySettings: { title: 'Управление сообщениями', description: 'Настройте базу знаний истории чата для автоматической индексации сообщений и семантического поиска', diff --git a/frontend/src/i18n/locales/zh-CN.ts b/frontend/src/i18n/locales/zh-CN.ts index 8a3180d18..34e7379f0 100755 --- a/frontend/src/i18n/locales/zh-CN.ts +++ b/frontend/src/i18n/locales/zh-CN.ts @@ -432,6 +432,7 @@ export default { autoCheckUpdateDesc: '开启后自动检查并在后台下载最新版本安装包。', memoryRequiresNeo4j: "记忆功能依赖 Neo4j 图数据库,请先配置并启用 Neo4j(设置环境变量 NEO4J_ENABLE=true)后再开启此功能。", memoryHowToEnable: "查看 Neo4j 配置指南", + vectorStoreEngine: "向量数据库引擎", parserEngine: "解析引擎", storageEngine: "存储引擎", mcpService: "MCP服务", @@ -668,6 +669,61 @@ export default { testFailed: "连接测试失败", }, }, + vectorStoreSettings: { + title: "向量数据库引擎", + description: "注册和管理用于知识库搜索的向量数据库实例。", + storesTitle: "向量数据库", + addStore: "添加数据库", + editStore: "编辑数据库", + deleteConfirm: "确定要删除此向量数据库吗?", + emptyDesc: '尚未配置向量数据库。点击"添加数据库"开始设置。', + engineTypeLabel: "引擎类型", + nameLabel: "名称", + namePlaceholder: "例如:my-vector-store", + connectionInfo: "连接信息", + advancedIndexConfig: "高级设置", + fields: { + addr: "URL", + host: "主机", + port: "端口", + username: "用户名", + password: "密码", + api_key: "API 密钥", + use_tls: "使用 TLS", + scheme: "协议", + grpc_address: "gRPC 地址", + use_default_connection: "使用默认连接", + index_name: "索引名称", + number_of_shards: "分片数", + number_of_replicas: "副本数", + collection_prefix: "集合前缀", + collection_name: "集合名称", + shard_number: "分片数", + replication_factor: "副本因子", + shards_num: "分片数", + replica_number: "内存副本数", + desired_shard_count: "分片数", + }, + envTag: "DEFAULT", + testConnection: "测试连接", + testing: "测试中...", + immutableNotice: "创建后无法更改引擎类型、连接和索引设置。\n如需更改,请删除后重新创建。", + validation: { + nameRequired: "名称为必填项", + engineTypeRequired: "引擎类型为必填项", + fieldRequired: "{field}为必填项", + indexNamePattern: "必须以字母开头,仅允许字母、数字、下划线和连字符(最多128个字符)", + }, + toasts: { + storeCreated: "向量数据库已创建", + storeUpdated: "向量数据库已更新", + storeDeleted: "向量数据库已删除", + testSuccess: "连接测试成功", + testFailed: "连接测试失败", + duplicateName: "同名向量数据库已存在", + errorGeneric: "发生错误,请重试。", + }, + }, chatHistorySettings: { title: "消息管理", description: "配置聊天历史知识库,将对话消息自动向量化索引,实现语义搜索", diff --git a/frontend/src/views/settings/Settings.vue b/frontend/src/views/settings/Settings.vue index 958f7c0aa..d42d786dd 100644 --- a/frontend/src/views/settings/Settings.vue +++ b/frontend/src/views/settings/Settings.vue @@ -117,6 +117,11 @@ + +
+ +
+
@@ -169,6 +174,7 @@ import OllamaSettings from './OllamaSettings.vue' import McpSettings from './McpSettings.vue' import WebSearchSettings from './WebSearchSettings.vue' import ChatHistorySettings from './ChatHistorySettings.vue' +import VectorStoreSettings from './VectorStoreSettings.vue' import ParserEngineSettings from './ParserEngineSettings.vue' import StorageEngineSettings from './StorageEngineSettings.vue' import WeKnoraCloudSettings from './WeKnoraCloudSettings.vue' @@ -189,6 +195,7 @@ const navItems = computed(() => [ { key: 'models', icon: 'control-platform', label: t('settings.modelManagement') }, { key: 'websearch', icon: 'search', label: t('settings.webSearchConfig') }, { key: 'chathistory', icon: 'chat', label: t('chatHistorySettings.title') }, + { key: 'vectorstore', icon: 'data-base', label: t('settings.vectorStoreEngine') }, { key: 'parser', icon: 'file-search', label: t('settings.parserEngine') }, { key: 'storage', icon: 'cloud', label: t('settings.storageEngine') }, { key: 'mcp', icon: 'tools', label: t('settings.mcpService') }, diff --git a/frontend/src/views/settings/VectorStoreSettings.vue b/frontend/src/views/settings/VectorStoreSettings.vue new file mode 100644 index 000000000..3b8baae72 --- /dev/null +++ b/frontend/src/views/settings/VectorStoreSettings.vue @@ -0,0 +1,812 @@ + + + + + diff --git a/internal/types/vectorstore.go b/internal/types/vectorstore.go index e15b50456..f8f76bc6a 100644 --- a/internal/types/vectorstore.go +++ b/internal/types/vectorstore.go @@ -484,79 +484,65 @@ func GetVectorStoreTypes() []VectorStoreTypeInfo { return []VectorStoreTypeInfo{ { Type: "elasticsearch", - DisplayName: "Elasticsearch (Keywords + Vector)", + DisplayName: "Elasticsearch", ConnectionFields: []VectorStoreFieldInfo{ - {Name: "addr", Type: "string", Required: true, Description: "Elasticsearch URL (e.g., http://localhost:9200)"}, - {Name: "username", Type: "string", Required: false}, - {Name: "password", Type: "string", Required: false, Sensitive: true}, + {Name: "addr", Type: "string", Required: true, Description: "URL", Default: "http://localhost:9200"}, + {Name: "username", Type: "string", Required: false, Description: "Username", Default: "elastic"}, + {Name: "password", Type: "string", Required: false, Sensitive: true, Description: "Password"}, }, IndexFields: []VectorStoreFieldInfo{ - {Name: "index_name", Type: "string", Required: false, Default: "xwrag_default"}, - {Name: "number_of_shards", Type: "number", Required: false}, - {Name: "number_of_replicas", Type: "number", Required: false}, - }, - }, - { - Type: "postgres", - DisplayName: "PostgreSQL (Keywords + Vector)", - ConnectionFields: []VectorStoreFieldInfo{ - {Name: "use_default_connection", Type: "boolean", Required: false, Default: true, - Description: "Use the application's default database connection"}, - {Name: "addr", Type: "string", Required: false, - Description: "PostgreSQL connection string (required if use_default_connection is false)"}, - {Name: "username", Type: "string", Required: false}, - {Name: "password", Type: "string", Required: false, Sensitive: true}, + {Name: "index_name", Type: "string", Required: false, Description: "Index Name", Default: "weknora"}, + {Name: "number_of_shards", Type: "number", Required: false, Description: "Shards", Default: 4}, + {Name: "number_of_replicas", Type: "number", Required: false, Description: "Replicas", Default: 1}, }, }, + // PostgreSQL and SQLite are excluded from the type list because they only support + // the app's default DB connection (UseDefaultConnection=true). They appear as + // env stores when configured via RETRIEVE_DRIVER but cannot be added as DB stores. { Type: "qdrant", - DisplayName: "Qdrant (Keywords + Vector)", + DisplayName: "Qdrant", ConnectionFields: []VectorStoreFieldInfo{ - {Name: "host", Type: "string", Required: true, Description: "Qdrant host"}, - {Name: "port", Type: "number", Required: false, Default: 6334}, - {Name: "api_key", Type: "string", Required: false, Sensitive: true}, - {Name: "use_tls", Type: "boolean", Required: false, Default: false}, + {Name: "host", Type: "string", Required: true, Description: "Host", Default: "localhost"}, + {Name: "port", Type: "number", Required: false, Description: "Port", Default: 6334}, + {Name: "api_key", Type: "string", Required: false, Sensitive: true, Description: "API Key"}, + {Name: "use_tls", Type: "boolean", Required: false, Description: "Use TLS", Default: false}, }, IndexFields: []VectorStoreFieldInfo{ - {Name: "collection_prefix", Type: "string", Required: false, Default: "weknora_embeddings", Description: "Collection Prefix"}, - {Name: "shard_number", Type: "number", Required: false, Default: 1, Description: "Shard Number"}, - {Name: "replication_factor", Type: "number", Required: false, Default: 1, Description: "Replication Factor"}, + {Name: "collection_prefix", Type: "string", Required: false, Description: "Collection Prefix", Default: "weknora_embeddings"}, + {Name: "shard_number", Type: "number", Required: false, Description: "Shard Number", Default: 1}, + {Name: "replication_factor", Type: "number", Required: false, Description: "Replication Factor", Default: 1}, }, }, { Type: "milvus", - DisplayName: "Milvus (Keywords + Vector)", + DisplayName: "Milvus", ConnectionFields: []VectorStoreFieldInfo{ - {Name: "addr", Type: "string", Required: true, Description: "Milvus address (e.g., localhost:19530)"}, - {Name: "username", Type: "string", Required: false}, - {Name: "password", Type: "string", Required: false, Sensitive: true}, + {Name: "addr", Type: "string", Required: true, Description: "Address", Default: "localhost:19530"}, + {Name: "username", Type: "string", Required: false, Description: "Username", Default: "root"}, + {Name: "password", Type: "string", Required: false, Sensitive: true, Description: "Password"}, }, IndexFields: []VectorStoreFieldInfo{ - {Name: "collection_name", Type: "string", Required: false, Default: "weknora_embeddings", Description: "Collection Name"}, - {Name: "shards_num", Type: "number", Required: false, Default: 1, Description: "Shards (write parallelism)"}, - {Name: "replica_number", Type: "number", Required: false, Default: 1, Description: "In-memory Replicas (read HA)"}, + {Name: "collection_name", Type: "string", Required: false, Description: "Collection Name", Default: "weknora_embeddings"}, + {Name: "shards_num", Type: "number", Required: false, Description: "Shards (write parallelism)", Default: 1}, + {Name: "replica_number", Type: "number", Required: false, Description: "In-memory Replicas (read HA)", Default: 1}, }, }, { Type: "weaviate", - DisplayName: "Weaviate (Keywords + Vector)", + DisplayName: "Weaviate", ConnectionFields: []VectorStoreFieldInfo{ - {Name: "host", Type: "string", Required: true, Description: "Weaviate host (e.g., weaviate:8080)"}, - {Name: "grpc_address", Type: "string", Required: false, Default: "weaviate:50051"}, - {Name: "scheme", Type: "string", Required: false, Default: "http"}, - {Name: "api_key", Type: "string", Required: false, Sensitive: true}, + {Name: "host", Type: "string", Required: true, Description: "Host", Default: "weaviate:8080"}, + {Name: "grpc_address", Type: "string", Required: false, Description: "gRPC Address", Default: "weaviate:50051"}, + {Name: "scheme", Type: "string", Required: false, Description: "Scheme", Default: "http"}, + {Name: "api_key", Type: "string", Required: false, Sensitive: true, Description: "API Key"}, }, IndexFields: []VectorStoreFieldInfo{ - {Name: "collection_prefix", Type: "string", Required: false, Default: "Weknora_embeddings", Description: "Collection Prefix"}, - {Name: "desired_shard_count", Type: "number", Required: false, Default: 1, Description: "Shard Count"}, - {Name: "replication_factor", Type: "number", Required: false, Default: 1, Description: "Replication Factor"}, + {Name: "collection_prefix", Type: "string", Required: false, Description: "Collection Prefix", Default: "Weknora_embeddings"}, + {Name: "desired_shard_count", Type: "number", Required: false, Description: "Shard Count", Default: 1}, + {Name: "replication_factor", Type: "number", Required: false, Description: "Replication Factor", Default: 1}, }, }, - { - Type: "sqlite", - DisplayName: "SQLite (Keywords + Vector)", - ConnectionFields: []VectorStoreFieldInfo{}, - }, } } @@ -611,7 +597,7 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "postgres": return &VectorStore{ ID: "__env_postgres__", - Name: "postgres (env)", + Name: "PostgreSQL", EngineType: PostgresRetrieverEngineType, ConnectionConfig: ConnectionConfig{ UseDefaultConnection: true, @@ -620,13 +606,13 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "sqlite": return &VectorStore{ ID: "__env_sqlite__", - Name: "sqlite (env)", + Name: "SQLite", EngineType: SQLiteRetrieverEngineType, } case "elasticsearch_v8": return &VectorStore{ ID: "__env_elasticsearch_v8__", - Name: "elasticsearch v8 (env)", + Name: "Elasticsearch v8", EngineType: ElasticsearchRetrieverEngineType, ConnectionConfig: ConnectionConfig{ Addr: envLookup("ELASTICSEARCH_ADDR"), @@ -640,7 +626,7 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "elasticsearch_v7": return &VectorStore{ ID: "__env_elasticsearch_v7__", - Name: "elasticsearch v7 (env)", + Name: "Elasticsearch v7", EngineType: ElasticsearchRetrieverEngineType, ConnectionConfig: ConnectionConfig{ Addr: envLookup("ELASTICSEARCH_ADDR"), @@ -654,7 +640,7 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "qdrant": return &VectorStore{ ID: "__env_qdrant__", - Name: "qdrant (env)", + Name: "Qdrant", EngineType: QdrantRetrieverEngineType, ConnectionConfig: ConnectionConfig{ Host: envLookup("QDRANT_HOST"), @@ -664,7 +650,7 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "milvus": return &VectorStore{ ID: "__env_milvus__", - Name: "milvus (env)", + Name: "Milvus", EngineType: MilvusRetrieverEngineType, ConnectionConfig: ConnectionConfig{ Addr: envLookup("MILVUS_ADDRESS"), @@ -675,7 +661,7 @@ func buildEnvStoreForDriver(driver string, envLookup EnvLookupFunc) *VectorStore case "weaviate": return &VectorStore{ ID: "__env_weaviate__", - Name: "weaviate (env)", + Name: "Weaviate", EngineType: WeaviateRetrieverEngineType, ConnectionConfig: ConnectionConfig{ Host: envLookup("WEAVIATE_HOST"), diff --git a/internal/types/vectorstore_test.go b/internal/types/vectorstore_test.go index e4481dd5d..f957f0378 100644 --- a/internal/types/vectorstore_test.go +++ b/internal/types/vectorstore_test.go @@ -63,7 +63,7 @@ func TestBuildEnvVectorStores(t *testing.T) { stores := BuildEnvVectorStores("postgres", lookup) require.Len(t, stores, 1) assert.Equal(t, "__env_postgres__", stores[0].ID) - assert.Equal(t, "postgres (env)", stores[0].Name) + assert.Equal(t, "PostgreSQL", stores[0].Name) assert.Equal(t, PostgresRetrieverEngineType, stores[0].EngineType) assert.True(t, stores[0].ConnectionConfig.UseDefaultConnection) }) @@ -198,8 +198,8 @@ func TestNewVectorStoreResponse(t *testing.T) { func TestGetVectorStoreTypes(t *testing.T) { types := GetVectorStoreTypes() - t.Run("returns 6 engine types", func(t *testing.T) { - assert.Len(t, types, 6) + t.Run("returns 4 engine types (excludes postgres and sqlite)", func(t *testing.T) { + assert.Len(t, types, 4) }) t.Run("type names match engine constants", func(t *testing.T) { @@ -208,11 +208,11 @@ func TestGetVectorStoreTypes(t *testing.T) { typeNames[i] = typ.Type } assert.Contains(t, typeNames, "elasticsearch") - assert.Contains(t, typeNames, "postgres") assert.Contains(t, typeNames, "qdrant") assert.Contains(t, typeNames, "milvus") assert.Contains(t, typeNames, "weaviate") - assert.Contains(t, typeNames, "sqlite") + assert.NotContains(t, typeNames, "postgres") + assert.NotContains(t, typeNames, "sqlite") }) t.Run("elasticsearch has connection and index fields", func(t *testing.T) { @@ -237,15 +237,10 @@ func TestGetVectorStoreTypes(t *testing.T) { assert.True(t, passwordField.Sensitive) }) - t.Run("sqlite has no connection fields", func(t *testing.T) { - var sqliteType VectorStoreTypeInfo + t.Run("display names have no parenthetical suffix", func(t *testing.T) { for _, typ := range types { - if typ.Type == "sqlite" { - sqliteType = typ - break - } + assert.NotContains(t, typ.DisplayName, "(", "display_name should not contain parenthetical suffix: %s", typ.DisplayName) } - assert.Empty(t, sqliteType.ConnectionFields) }) } diff --git a/scripts/dev.sh b/scripts/dev.sh index 79599a90e..c4fcba5ca 100755 --- a/scripts/dev.sh +++ b/scripts/dev.sh @@ -295,7 +295,7 @@ start_app() { log_warning "提示: 安装 Air 可以实现代码修改后自动重启" log_info "安装命令: go install github.com/air-verse/air@latest" LDFLAGS="$(./scripts/get_version.sh ldflags) -X 'google.golang.org/protobuf/reflect/protoregistry.conflictPolicy=warn'" - go run -ldflags="$LDFLAGS" cmd/server/main.go + go run -ldflags="$LDFLAGS" ./cmd/server/ fi }