diff --git a/COMMIT_DAY1.txt b/COMMIT_DAY1.txt index 9ac23cce..f868ad6b 100644 --- a/COMMIT_DAY1.txt +++ b/COMMIT_DAY1.txt @@ -51,5 +51,6 @@ Status: Day 1 complete (11/11 tasks), ready for Day 2 + diff --git a/DC模块代码恢复指南.md b/DC模块代码恢复指南.md index 25c25499..3a2348c0 100644 --- a/DC模块代码恢复指南.md +++ b/DC模块代码恢复指南.md @@ -281,5 +281,6 @@ + diff --git a/Dockerfile.postgres-pgvector b/Dockerfile.postgres-pgvector new file mode 100644 index 00000000..f620f10a --- /dev/null +++ b/Dockerfile.postgres-pgvector @@ -0,0 +1,23 @@ +# 基于已有的 postgres:15-alpine 镜像构建 pgvector 版本 +# pgvector 版本:0.8.0(与阿里云 RDS PostgreSQL 15 保持一致) +FROM postgres:15-alpine + +# 使用阿里云镜像源加速 Alpine 包下载 +RUN sed -i 's/dl-cdn.alpinelinux.org/mirrors.aliyun.com/g' /etc/apk/repositories + +# 复制本地下载的 pgvector 源码包 +COPY pgvector-0.8.0.tar.gz /tmp/pgvector-0.8.0.tar.gz + +# 安装编译依赖并编译 pgvector(禁用 LLVM bitcode 编译) +RUN apk add --no-cache --virtual .build-deps \ + build-base \ + && cd /tmp \ + && tar -xzf pgvector-0.8.0.tar.gz \ + && cd pgvector-0.8.0 \ + && sed -i 's/^with_llvm.*/with_llvm = no/' /usr/local/lib/postgresql/pgxs/src/Makefile.global \ + && make USE_PGXS=1 PG_CONFIG=/usr/local/bin/pg_config \ + && make USE_PGXS=1 PG_CONFIG=/usr/local/bin/pg_config install \ + && cd / \ + && rm -rf /tmp/pgvector-0.8.0 /tmp/pgvector-0.8.0.tar.gz \ + && apk del .build-deps + diff --git a/SAE_WECHAT_MP_DEPLOY_STEPS.md b/SAE_WECHAT_MP_DEPLOY_STEPS.md index c1545e99..e3425c6d 100644 --- a/SAE_WECHAT_MP_DEPLOY_STEPS.md +++ b/SAE_WECHAT_MP_DEPLOY_STEPS.md @@ -227,5 +227,6 @@ https://iit.xunzhengyixue.com/api/v1/iit/health + diff --git a/backend/DEPLOY_TO_SAE_FOR_WECHAT_MP.md b/backend/DEPLOY_TO_SAE_FOR_WECHAT_MP.md index cdfe4bec..5adca17b 100644 --- a/backend/DEPLOY_TO_SAE_FOR_WECHAT_MP.md +++ b/backend/DEPLOY_TO_SAE_FOR_WECHAT_MP.md @@ -156,5 +156,6 @@ https://iit.xunzhengyixue.com/api/v1/iit/health + diff --git a/backend/RESTART_SERVER_NOW.md b/backend/RESTART_SERVER_NOW.md index c60606e6..b1b312af 100644 --- a/backend/RESTART_SERVER_NOW.md +++ b/backend/RESTART_SERVER_NOW.md @@ -57,5 +57,6 @@ + diff --git a/backend/WECHAT_MP_CONFIG_READY.md b/backend/WECHAT_MP_CONFIG_READY.md index ec9b47ed..0382aded 100644 --- a/backend/WECHAT_MP_CONFIG_READY.md +++ b/backend/WECHAT_MP_CONFIG_READY.md @@ -317,5 +317,6 @@ npx tsx src/modules/iit-manager/test-patient-wechat-url-verify.ts + diff --git a/backend/WECHAT_MP_QUICK_FIX.md b/backend/WECHAT_MP_QUICK_FIX.md index f52d32bd..2b60390c 100644 --- a/backend/WECHAT_MP_QUICK_FIX.md +++ b/backend/WECHAT_MP_QUICK_FIX.md @@ -179,5 +179,6 @@ npm run dev + diff --git a/backend/check_db.ts b/backend/check_db.ts index 8210d00e..65a28f6e 100644 --- a/backend/check_db.ts +++ b/backend/check_db.ts @@ -58,3 +58,4 @@ main() + diff --git a/backend/check_db_data.ts b/backend/check_db_data.ts index 26e7b72e..05f85b39 100644 --- a/backend/check_db_data.ts +++ b/backend/check_db_data.ts @@ -52,3 +52,4 @@ main() + diff --git a/backend/check_iit.ts b/backend/check_iit.ts index 8a9c175a..a9992873 100644 --- a/backend/check_iit.ts +++ b/backend/check_iit.ts @@ -47,3 +47,4 @@ main() + diff --git a/backend/check_iit_asl_data.ts b/backend/check_iit_asl_data.ts index d5e48d6b..0282b2a7 100644 --- a/backend/check_iit_asl_data.ts +++ b/backend/check_iit_asl_data.ts @@ -79,3 +79,4 @@ main() + diff --git a/backend/check_queue_table.ts b/backend/check_queue_table.ts index 81bdf59d..a4c4fd74 100644 --- a/backend/check_queue_table.ts +++ b/backend/check_queue_table.ts @@ -42,3 +42,4 @@ main() + diff --git a/backend/check_rvw_issue.ts b/backend/check_rvw_issue.ts index f379a351..7affea67 100644 --- a/backend/check_rvw_issue.ts +++ b/backend/check_rvw_issue.ts @@ -83,3 +83,4 @@ main() + diff --git a/backend/check_tables.ts b/backend/check_tables.ts index deb45c6d..08f02ed0 100644 --- a/backend/check_tables.ts +++ b/backend/check_tables.ts @@ -30,3 +30,4 @@ main() + diff --git a/backend/compare_db.ts b/backend/compare_db.ts index 146963de..d1edede9 100644 --- a/backend/compare_db.ts +++ b/backend/compare_db.ts @@ -118,3 +118,4 @@ main() + diff --git a/backend/compare_dc_asl.ts b/backend/compare_dc_asl.ts index e0c56681..29c98e6f 100644 --- a/backend/compare_dc_asl.ts +++ b/backend/compare_dc_asl.ts @@ -89,3 +89,4 @@ main() + diff --git a/backend/compare_pkb_aia_rvw.ts b/backend/compare_pkb_aia_rvw.ts index e996e368..cfde4751 100644 --- a/backend/compare_pkb_aia_rvw.ts +++ b/backend/compare_pkb_aia_rvw.ts @@ -75,3 +75,4 @@ main() + diff --git a/backend/compare_schema_db.ts b/backend/compare_schema_db.ts index 645aff30..6359ec3a 100644 --- a/backend/compare_schema_db.ts +++ b/backend/compare_schema_db.ts @@ -117,3 +117,4 @@ main() + diff --git a/backend/create_mock_user.sql b/backend/create_mock_user.sql index 25e2e9ab..26e175ba 100644 --- a/backend/create_mock_user.sql +++ b/backend/create_mock_user.sql @@ -28,3 +28,4 @@ ON CONFLICT (id) DO NOTHING; + diff --git a/backend/create_mock_user_platform.sql b/backend/create_mock_user_platform.sql index ab55bff6..350a55f3 100644 --- a/backend/create_mock_user_platform.sql +++ b/backend/create_mock_user_platform.sql @@ -60,3 +60,4 @@ ON CONFLICT (id) DO NOTHING; + diff --git a/backend/migrations/add_data_stats_to_tool_c_session.sql b/backend/migrations/add_data_stats_to_tool_c_session.sql index 5ac42dec..99c22db5 100644 --- a/backend/migrations/add_data_stats_to_tool_c_session.sql +++ b/backend/migrations/add_data_stats_to_tool_c_session.sql @@ -76,5 +76,6 @@ WHERE table_schema = 'dc_schema' + diff --git a/backend/prisma/manual-migrations/001_add_postgres_cache_and_checkpoint.sql b/backend/prisma/manual-migrations/001_add_postgres_cache_and_checkpoint.sql index 6d0656b0..8064d001 100644 --- a/backend/prisma/manual-migrations/001_add_postgres_cache_and_checkpoint.sql +++ b/backend/prisma/manual-migrations/001_add_postgres_cache_and_checkpoint.sql @@ -114,5 +114,6 @@ ORDER BY ordinal_position; + diff --git a/backend/prisma/manual-migrations/run-migration-002.ts b/backend/prisma/manual-migrations/run-migration-002.ts index 6c79b751..beeb64c1 100644 --- a/backend/prisma/manual-migrations/run-migration-002.ts +++ b/backend/prisma/manual-migrations/run-migration-002.ts @@ -127,5 +127,6 @@ runMigration() + diff --git a/backend/prisma/migrations/20251208_add_column_mapping/migration.sql b/backend/prisma/migrations/20251208_add_column_mapping/migration.sql index f7a97409..b5d09a60 100644 --- a/backend/prisma/migrations/20251208_add_column_mapping/migration.sql +++ b/backend/prisma/migrations/20251208_add_column_mapping/migration.sql @@ -61,5 +61,6 @@ COMMENT ON COLUMN "dc_schema"."dc_tool_c_sessions"."column_mapping" IS '列名 + diff --git a/backend/prisma/migrations/create_tool_c_session.sql b/backend/prisma/migrations/create_tool_c_session.sql index c83bbb23..2b694d36 100644 --- a/backend/prisma/migrations/create_tool_c_session.sql +++ b/backend/prisma/migrations/create_tool_c_session.sql @@ -88,5 +88,6 @@ COMMENT ON COLUMN dc_schema.dc_tool_c_sessions.expires_at IS '过期时间(创 + diff --git a/backend/rebuild-and-push.ps1 b/backend/rebuild-and-push.ps1 index 5cd5fca9..62e12718 100644 --- a/backend/rebuild-and-push.ps1 +++ b/backend/rebuild-and-push.ps1 @@ -128,5 +128,6 @@ Write-Host "" + diff --git a/backend/recover-code-from-cursor-db.js b/backend/recover-code-from-cursor-db.js index fced7c95..b51f0251 100644 --- a/backend/recover-code-from-cursor-db.js +++ b/backend/recover-code-from-cursor-db.js @@ -238,5 +238,6 @@ function extractCodeBlocks(obj, blocks = []) { + diff --git a/backend/restore_job_common.sql b/backend/restore_job_common.sql index 19ed7b4d..a46c4a79 100644 --- a/backend/restore_job_common.sql +++ b/backend/restore_job_common.sql @@ -37,3 +37,4 @@ CREATE TABLE IF NOT EXISTS platform_schema.job_common ( + diff --git a/backend/restore_pgboss_functions.sql b/backend/restore_pgboss_functions.sql index ac404dcb..80cb98a1 100644 --- a/backend/restore_pgboss_functions.sql +++ b/backend/restore_pgboss_functions.sql @@ -111,3 +111,4 @@ CREATE OR REPLACE FUNCTION platform_schema.delete_queue(queue_name text) RETURNS + diff --git a/backend/scripts/check-dc-tables.mjs b/backend/scripts/check-dc-tables.mjs index d8ae0a26..641bec75 100644 --- a/backend/scripts/check-dc-tables.mjs +++ b/backend/scripts/check-dc-tables.mjs @@ -257,5 +257,6 @@ checkDCTables(); + diff --git a/backend/scripts/create-capability-schema.sql b/backend/scripts/create-capability-schema.sql index 2f7daf53..b25b93f7 100644 --- a/backend/scripts/create-capability-schema.sql +++ b/backend/scripts/create-capability-schema.sql @@ -12,3 +12,4 @@ CREATE SCHEMA IF NOT EXISTS capability_schema; + diff --git a/backend/scripts/create-tool-c-ai-history-table.mjs b/backend/scripts/create-tool-c-ai-history-table.mjs index b8079153..c0cd2c79 100644 --- a/backend/scripts/create-tool-c-ai-history-table.mjs +++ b/backend/scripts/create-tool-c-ai-history-table.mjs @@ -209,5 +209,6 @@ createAiHistoryTable() + diff --git a/backend/scripts/create-tool-c-table.js b/backend/scripts/create-tool-c-table.js index d00e20eb..871b5178 100644 --- a/backend/scripts/create-tool-c-table.js +++ b/backend/scripts/create-tool-c-table.js @@ -196,5 +196,6 @@ createToolCTable() + diff --git a/backend/scripts/create-tool-c-table.mjs b/backend/scripts/create-tool-c-table.mjs index cd3db92b..9fce371c 100644 --- a/backend/scripts/create-tool-c-table.mjs +++ b/backend/scripts/create-tool-c-table.mjs @@ -193,5 +193,6 @@ createToolCTable() + diff --git a/backend/scripts/migrate-aia-prompts.ts b/backend/scripts/migrate-aia-prompts.ts index be8b61d6..9be3bbef 100644 --- a/backend/scripts/migrate-aia-prompts.ts +++ b/backend/scripts/migrate-aia-prompts.ts @@ -315,3 +315,4 @@ main() }) .finally(() => prisma.$disconnect()); + diff --git a/backend/scripts/setup-prompt-system.ts b/backend/scripts/setup-prompt-system.ts index 9091d8b6..d827de40 100644 --- a/backend/scripts/setup-prompt-system.ts +++ b/backend/scripts/setup-prompt-system.ts @@ -122,3 +122,4 @@ main() + diff --git a/backend/scripts/test-pkb-apis-simple.ts b/backend/scripts/test-pkb-apis-simple.ts index e14863a0..cef5ab32 100644 --- a/backend/scripts/test-pkb-apis-simple.ts +++ b/backend/scripts/test-pkb-apis-simple.ts @@ -342,3 +342,4 @@ runTests().catch(error => { + diff --git a/backend/scripts/test-prompt-api.ts b/backend/scripts/test-prompt-api.ts index 9f048eec..5f896120 100644 --- a/backend/scripts/test-prompt-api.ts +++ b/backend/scripts/test-prompt-api.ts @@ -88,3 +88,4 @@ testAPI().catch(console.error); + diff --git a/backend/scripts/test-unifuncs-deepsearch.ts b/backend/scripts/test-unifuncs-deepsearch.ts index b72771a5..e93ab67c 100644 --- a/backend/scripts/test-unifuncs-deepsearch.ts +++ b/backend/scripts/test-unifuncs-deepsearch.ts @@ -118,3 +118,4 @@ async function testDeepSearch() { // ========== 运行 ========== testDeepSearch().catch(console.error); + diff --git a/backend/scripts/verify-pkb-rvw-schema.ts b/backend/scripts/verify-pkb-rvw-schema.ts index 273a9257..cd436266 100644 --- a/backend/scripts/verify-pkb-rvw-schema.ts +++ b/backend/scripts/verify-pkb-rvw-schema.ts @@ -307,3 +307,4 @@ verifySchemas() + diff --git a/backend/src/common/auth/jwt.service.ts b/backend/src/common/auth/jwt.service.ts index 98fd15e2..dc6a60e5 100644 --- a/backend/src/common/auth/jwt.service.ts +++ b/backend/src/common/auth/jwt.service.ts @@ -195,3 +195,4 @@ export const jwtService = new JWTService(); + diff --git a/backend/src/common/jobs/utils.ts b/backend/src/common/jobs/utils.ts index 248b7de7..e7ea5a88 100644 --- a/backend/src/common/jobs/utils.ts +++ b/backend/src/common/jobs/utils.ts @@ -325,5 +325,6 @@ export function getBatchItems( + diff --git a/backend/src/common/prompt/prompt.types.ts b/backend/src/common/prompt/prompt.types.ts index 22c77c73..62439447 100644 --- a/backend/src/common/prompt/prompt.types.ts +++ b/backend/src/common/prompt/prompt.types.ts @@ -78,3 +78,4 @@ export interface VariableValidation { + diff --git a/backend/src/common/streaming/OpenAIStreamAdapter.ts b/backend/src/common/streaming/OpenAIStreamAdapter.ts index 7165cc34..2d2edddd 100644 --- a/backend/src/common/streaming/OpenAIStreamAdapter.ts +++ b/backend/src/common/streaming/OpenAIStreamAdapter.ts @@ -199,3 +199,4 @@ export function createOpenAIStreamAdapter( + diff --git a/backend/src/common/streaming/StreamingService.ts b/backend/src/common/streaming/StreamingService.ts index a92b8798..5210235c 100644 --- a/backend/src/common/streaming/StreamingService.ts +++ b/backend/src/common/streaming/StreamingService.ts @@ -205,3 +205,4 @@ export async function streamChat( + diff --git a/backend/src/common/streaming/index.ts b/backend/src/common/streaming/index.ts index 44d27568..918d56c2 100644 --- a/backend/src/common/streaming/index.ts +++ b/backend/src/common/streaming/index.ts @@ -23,3 +23,4 @@ export { THINKING_TAGS } from './types'; + diff --git a/backend/src/common/streaming/types.ts b/backend/src/common/streaming/types.ts index 57ed5c4d..17406ac7 100644 --- a/backend/src/common/streaming/types.ts +++ b/backend/src/common/streaming/types.ts @@ -98,3 +98,4 @@ export type SSEEventType = + diff --git a/backend/src/modules/admin/routes/tenantRoutes.ts b/backend/src/modules/admin/routes/tenantRoutes.ts index 72e5f837..241f6892 100644 --- a/backend/src/modules/admin/routes/tenantRoutes.ts +++ b/backend/src/modules/admin/routes/tenantRoutes.ts @@ -84,3 +84,4 @@ export async function moduleRoutes(fastify: FastifyInstance) { + diff --git a/backend/src/modules/admin/types/tenant.types.ts b/backend/src/modules/admin/types/tenant.types.ts index 63929110..de3484b1 100644 --- a/backend/src/modules/admin/types/tenant.types.ts +++ b/backend/src/modules/admin/types/tenant.types.ts @@ -114,3 +114,4 @@ export interface PaginatedResponse { + diff --git a/backend/src/modules/admin/types/user.types.ts b/backend/src/modules/admin/types/user.types.ts index 195809c8..1adee826 100644 --- a/backend/src/modules/admin/types/user.types.ts +++ b/backend/src/modules/admin/types/user.types.ts @@ -161,3 +161,4 @@ export const ROLE_DISPLAY_NAMES: Record = { + diff --git a/backend/src/modules/aia/controllers/agentController.ts b/backend/src/modules/aia/controllers/agentController.ts index 69046476..2a9eaa97 100644 --- a/backend/src/modules/aia/controllers/agentController.ts +++ b/backend/src/modules/aia/controllers/agentController.ts @@ -236,3 +236,4 @@ async function matchIntent(query: string): Promise<{ + diff --git a/backend/src/modules/aia/controllers/attachmentController.ts b/backend/src/modules/aia/controllers/attachmentController.ts index f2a545f0..3df36a43 100644 --- a/backend/src/modules/aia/controllers/attachmentController.ts +++ b/backend/src/modules/aia/controllers/attachmentController.ts @@ -90,3 +90,4 @@ export async function uploadAttachment( } + diff --git a/backend/src/modules/aia/index.ts b/backend/src/modules/aia/index.ts index fb5c8207..85ed343c 100644 --- a/backend/src/modules/aia/index.ts +++ b/backend/src/modules/aia/index.ts @@ -19,3 +19,4 @@ export { aiaRoutes }; + diff --git a/backend/src/modules/asl/fulltext-screening/__tests__/api-integration-test.ts b/backend/src/modules/asl/fulltext-screening/__tests__/api-integration-test.ts index 90717db2..deb11b4b 100644 --- a/backend/src/modules/asl/fulltext-screening/__tests__/api-integration-test.ts +++ b/backend/src/modules/asl/fulltext-screening/__tests__/api-integration-test.ts @@ -361,5 +361,6 @@ runTests().catch((error) => { + diff --git a/backend/src/modules/asl/fulltext-screening/__tests__/e2e-real-test-v2.ts b/backend/src/modules/asl/fulltext-screening/__tests__/e2e-real-test-v2.ts index eea67868..f3ad5d0c 100644 --- a/backend/src/modules/asl/fulltext-screening/__tests__/e2e-real-test-v2.ts +++ b/backend/src/modules/asl/fulltext-screening/__tests__/e2e-real-test-v2.ts @@ -302,5 +302,6 @@ runTest() + diff --git a/backend/src/modules/asl/fulltext-screening/__tests__/fulltext-screening-api.http b/backend/src/modules/asl/fulltext-screening/__tests__/fulltext-screening-api.http index e0795416..211ab1a6 100644 --- a/backend/src/modules/asl/fulltext-screening/__tests__/fulltext-screening-api.http +++ b/backend/src/modules/asl/fulltext-screening/__tests__/fulltext-screening-api.http @@ -340,5 +340,6 @@ Content-Type: application/json + diff --git a/backend/src/modules/dc/tool-b/services/ConflictDetectionService.ts b/backend/src/modules/dc/tool-b/services/ConflictDetectionService.ts index 6a24a32b..3e8d91af 100644 --- a/backend/src/modules/dc/tool-b/services/ConflictDetectionService.ts +++ b/backend/src/modules/dc/tool-b/services/ConflictDetectionService.ts @@ -276,5 +276,6 @@ export const conflictDetectionService = new ConflictDetectionService(); + diff --git a/backend/src/modules/dc/tool-c/README.md b/backend/src/modules/dc/tool-c/README.md index 68f16244..ba377728 100644 --- a/backend/src/modules/dc/tool-c/README.md +++ b/backend/src/modules/dc/tool-c/README.md @@ -226,5 +226,6 @@ curl -X POST http://localhost:3000/api/v1/dc/tool-c/test/execute \ + diff --git a/backend/src/modules/dc/tool-c/controllers/StreamAIController.ts b/backend/src/modules/dc/tool-c/controllers/StreamAIController.ts index de7f72f2..67d555f2 100644 --- a/backend/src/modules/dc/tool-c/controllers/StreamAIController.ts +++ b/backend/src/modules/dc/tool-c/controllers/StreamAIController.ts @@ -280,5 +280,6 @@ export const streamAIController = new StreamAIController(); + diff --git a/backend/src/modules/iit-manager/agents/SessionMemory.ts b/backend/src/modules/iit-manager/agents/SessionMemory.ts index 0fc867c0..c2266f22 100644 --- a/backend/src/modules/iit-manager/agents/SessionMemory.ts +++ b/backend/src/modules/iit-manager/agents/SessionMemory.ts @@ -189,5 +189,6 @@ logger.info('[SessionMemory] 会话记忆管理器已启动', { + diff --git a/backend/src/modules/iit-manager/check-iit-table-structure.ts b/backend/src/modules/iit-manager/check-iit-table-structure.ts index 456433fa..8669d8e1 100644 --- a/backend/src/modules/iit-manager/check-iit-table-structure.ts +++ b/backend/src/modules/iit-manager/check-iit-table-structure.ts @@ -123,5 +123,6 @@ checkTableStructure(); + diff --git a/backend/src/modules/iit-manager/check-project-config.ts b/backend/src/modules/iit-manager/check-project-config.ts index d1a5ffe7..41fa58d6 100644 --- a/backend/src/modules/iit-manager/check-project-config.ts +++ b/backend/src/modules/iit-manager/check-project-config.ts @@ -110,5 +110,6 @@ checkProjectConfig().catch(console.error); + diff --git a/backend/src/modules/iit-manager/check-test-project-in-db.ts b/backend/src/modules/iit-manager/check-test-project-in-db.ts index 14c2120d..bd156f26 100644 --- a/backend/src/modules/iit-manager/check-test-project-in-db.ts +++ b/backend/src/modules/iit-manager/check-test-project-in-db.ts @@ -92,5 +92,6 @@ main(); + diff --git a/backend/src/modules/iit-manager/docs/微信服务号接入指南.md b/backend/src/modules/iit-manager/docs/微信服务号接入指南.md index 670135f6..ca2d2560 100644 --- a/backend/src/modules/iit-manager/docs/微信服务号接入指南.md +++ b/backend/src/modules/iit-manager/docs/微信服务号接入指南.md @@ -549,5 +549,6 @@ URL: https://iit.xunzhengyixue.com/api/v1/iit/patient-wechat/callback + diff --git a/backend/src/modules/iit-manager/generate-wechat-tokens.ts b/backend/src/modules/iit-manager/generate-wechat-tokens.ts index bb3a9ca5..676057cb 100644 --- a/backend/src/modules/iit-manager/generate-wechat-tokens.ts +++ b/backend/src/modules/iit-manager/generate-wechat-tokens.ts @@ -184,5 +184,6 @@ console.log(''); + diff --git a/backend/src/modules/iit-manager/services/PatientWechatService.ts b/backend/src/modules/iit-manager/services/PatientWechatService.ts index 552d32c3..e3fa0ebc 100644 --- a/backend/src/modules/iit-manager/services/PatientWechatService.ts +++ b/backend/src/modules/iit-manager/services/PatientWechatService.ts @@ -501,5 +501,6 @@ export const patientWechatService = new PatientWechatService(); + diff --git a/backend/src/modules/iit-manager/test-chatservice-dify.ts b/backend/src/modules/iit-manager/test-chatservice-dify.ts index 1e01583f..93639a8b 100644 --- a/backend/src/modules/iit-manager/test-chatservice-dify.ts +++ b/backend/src/modules/iit-manager/test-chatservice-dify.ts @@ -146,5 +146,6 @@ testDifyIntegration().catch(error => { + diff --git a/backend/src/modules/iit-manager/test-iit-database.ts b/backend/src/modules/iit-manager/test-iit-database.ts index a35fe2f1..e61d42db 100644 --- a/backend/src/modules/iit-manager/test-iit-database.ts +++ b/backend/src/modules/iit-manager/test-iit-database.ts @@ -175,5 +175,6 @@ testIitDatabase() + diff --git a/backend/src/modules/iit-manager/test-patient-wechat-config.ts b/backend/src/modules/iit-manager/test-patient-wechat-config.ts index 10a99a37..0538ef53 100644 --- a/backend/src/modules/iit-manager/test-patient-wechat-config.ts +++ b/backend/src/modules/iit-manager/test-patient-wechat-config.ts @@ -161,5 +161,6 @@ if (hasError) { + diff --git a/backend/src/modules/iit-manager/test-patient-wechat-url-verify.ts b/backend/src/modules/iit-manager/test-patient-wechat-url-verify.ts index 8c05fc6d..d6720806 100644 --- a/backend/src/modules/iit-manager/test-patient-wechat-url-verify.ts +++ b/backend/src/modules/iit-manager/test-patient-wechat-url-verify.ts @@ -187,5 +187,6 @@ async function testUrlVerification() { + diff --git a/backend/src/modules/iit-manager/test-redcap-query-from-db.ts b/backend/src/modules/iit-manager/test-redcap-query-from-db.ts index 022566d6..02d60bb7 100644 --- a/backend/src/modules/iit-manager/test-redcap-query-from-db.ts +++ b/backend/src/modules/iit-manager/test-redcap-query-from-db.ts @@ -268,5 +268,6 @@ main().catch((error) => { + diff --git a/backend/src/modules/iit-manager/test-wechat-mp-local.ps1 b/backend/src/modules/iit-manager/test-wechat-mp-local.ps1 index cb16ac39..da4f456b 100644 --- a/backend/src/modules/iit-manager/test-wechat-mp-local.ps1 +++ b/backend/src/modules/iit-manager/test-wechat-mp-local.ps1 @@ -152,5 +152,6 @@ Write-Host "" + diff --git a/backend/src/modules/iit-manager/types/index.ts b/backend/src/modules/iit-manager/types/index.ts index 0fabbd09..e84ef10d 100644 --- a/backend/src/modules/iit-manager/types/index.ts +++ b/backend/src/modules/iit-manager/types/index.ts @@ -245,5 +245,6 @@ export interface CachedProtocolRules { + diff --git a/backend/src/modules/pkb/routes/health.ts b/backend/src/modules/pkb/routes/health.ts index 30b40c26..f15c18a1 100644 --- a/backend/src/modules/pkb/routes/health.ts +++ b/backend/src/modules/pkb/routes/health.ts @@ -60,3 +60,4 @@ export default async function healthRoutes(fastify: FastifyInstance) { + diff --git a/backend/src/modules/rvw/__tests__/api.http b/backend/src/modules/rvw/__tests__/api.http index 10f38870..d0815d2f 100644 --- a/backend/src/modules/rvw/__tests__/api.http +++ b/backend/src/modules/rvw/__tests__/api.http @@ -138,3 +138,4 @@ Content-Type: application/json + diff --git a/backend/src/modules/rvw/__tests__/test-api.ps1 b/backend/src/modules/rvw/__tests__/test-api.ps1 index 0d96fb34..0de09cf7 100644 --- a/backend/src/modules/rvw/__tests__/test-api.ps1 +++ b/backend/src/modules/rvw/__tests__/test-api.ps1 @@ -123,3 +123,4 @@ Write-Host " - 删除任务: DELETE $BaseUrl/api/v1/rvw/tasks/{taskId}" -Foregr + diff --git a/backend/src/modules/rvw/index.ts b/backend/src/modules/rvw/index.ts index 7fb64c41..fbb4d252 100644 --- a/backend/src/modules/rvw/index.ts +++ b/backend/src/modules/rvw/index.ts @@ -37,3 +37,4 @@ export * from './services/utils.js'; + diff --git a/backend/src/modules/rvw/services/utils.ts b/backend/src/modules/rvw/services/utils.ts index 5e1831c7..8d0eb394 100644 --- a/backend/src/modules/rvw/services/utils.ts +++ b/backend/src/modules/rvw/services/utils.ts @@ -128,3 +128,4 @@ export function validateAgentSelection(agents: string[]): void { + diff --git a/backend/src/tests/README.md b/backend/src/tests/README.md index 21dcdfad..de1877c7 100644 --- a/backend/src/tests/README.md +++ b/backend/src/tests/README.md @@ -426,5 +426,6 @@ SET session_replication_role = 'origin'; + diff --git a/backend/src/tests/verify-test1-database.sql b/backend/src/tests/verify-test1-database.sql index 72fb5058..b946984e 100644 --- a/backend/src/tests/verify-test1-database.sql +++ b/backend/src/tests/verify-test1-database.sql @@ -128,5 +128,6 @@ WHERE key = 'verify_test'; + diff --git a/backend/src/tests/verify-test1-database.ts b/backend/src/tests/verify-test1-database.ts index fee15303..15dfc96c 100644 --- a/backend/src/tests/verify-test1-database.ts +++ b/backend/src/tests/verify-test1-database.ts @@ -271,5 +271,6 @@ verifyDatabase() + diff --git a/backend/src/types/global.d.ts b/backend/src/types/global.d.ts index d10be8ac..a5281c64 100644 --- a/backend/src/types/global.d.ts +++ b/backend/src/types/global.d.ts @@ -61,5 +61,6 @@ export {} + diff --git a/backend/sync-dc-database.ps1 b/backend/sync-dc-database.ps1 index c3fadeb4..1422989d 100644 --- a/backend/sync-dc-database.ps1 +++ b/backend/sync-dc-database.ps1 @@ -84,5 +84,6 @@ Write-Host "✅ 完成!" -ForegroundColor Green + diff --git a/backend/temp_check.sql b/backend/temp_check.sql index 4fff8ca1..0d8ff9be 100644 --- a/backend/temp_check.sql +++ b/backend/temp_check.sql @@ -11,3 +11,4 @@ SELECT schema_name FROM information_schema.schemata WHERE schema_name NOT IN ('p + diff --git a/backend/test-pkb-migration.http b/backend/test-pkb-migration.http index b022d164..8344ecf6 100644 --- a/backend/test-pkb-migration.http +++ b/backend/test-pkb-migration.http @@ -174,3 +174,4 @@ DELETE {{baseUrl}}/api/v1/pkb/knowledge/knowledge-bases/{{testKbId}} + diff --git a/backend/test-tool-c-advanced-scenarios.mjs b/backend/test-tool-c-advanced-scenarios.mjs index 97623885..c6e87731 100644 --- a/backend/test-tool-c-advanced-scenarios.mjs +++ b/backend/test-tool-c-advanced-scenarios.mjs @@ -371,5 +371,6 @@ runAdvancedTests().catch(error => { + diff --git a/backend/test-tool-c-day2.mjs b/backend/test-tool-c-day2.mjs index e9b3dd07..37a84860 100644 --- a/backend/test-tool-c-day2.mjs +++ b/backend/test-tool-c-day2.mjs @@ -437,5 +437,6 @@ runAllTests() + diff --git a/backend/test-tool-c-day3.mjs b/backend/test-tool-c-day3.mjs index 537fbeda..061e881e 100644 --- a/backend/test-tool-c-day3.mjs +++ b/backend/test-tool-c-day3.mjs @@ -395,5 +395,6 @@ runAllTests() + diff --git a/backend/verify_all_users.ts b/backend/verify_all_users.ts index 090896e5..c371210e 100644 --- a/backend/verify_all_users.ts +++ b/backend/verify_all_users.ts @@ -31,3 +31,4 @@ main() + diff --git a/backend/verify_functions.ts b/backend/verify_functions.ts index 39a0fe72..08603512 100644 --- a/backend/verify_functions.ts +++ b/backend/verify_functions.ts @@ -29,3 +29,4 @@ main() + diff --git a/backend/verify_job_common.ts b/backend/verify_job_common.ts index c4ebeb37..efd0762a 100644 --- a/backend/verify_job_common.ts +++ b/backend/verify_job_common.ts @@ -41,3 +41,4 @@ main() + diff --git a/backend/verify_mock_user.ts b/backend/verify_mock_user.ts index 78e113b3..b8ea77f1 100644 --- a/backend/verify_mock_user.ts +++ b/backend/verify_mock_user.ts @@ -30,3 +30,4 @@ main() + diff --git a/backend/verify_system.ts b/backend/verify_system.ts index 9a76638c..295f7b56 100644 --- a/backend/verify_system.ts +++ b/backend/verify_system.ts @@ -170,3 +170,4 @@ main() + diff --git a/backup_before_pgvector_20260119.sql b/backup_before_pgvector_20260119.sql new file mode 100644 index 00000000..39470b21 Binary files /dev/null and b/backup_before_pgvector_20260119.sql differ diff --git a/deploy-to-sae.ps1 b/deploy-to-sae.ps1 index 0ca82b42..9d0bdca1 100644 --- a/deploy-to-sae.ps1 +++ b/deploy-to-sae.ps1 @@ -179,5 +179,6 @@ Set-Location .. + diff --git a/docker-compose.yml b/docker-compose.yml index 999d984d..22c79764 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -1,9 +1,9 @@ version: '3.8' services: - # PostgreSQL 数据库 + # PostgreSQL 数据库 (with pgvector extension) postgres: - image: postgres:15-alpine + image: pgvector/pgvector:pg15 container_name: ai-clinical-postgres environment: POSTGRES_DB: ai_clinical_research diff --git a/docs/00-系统总体设计/00-系统当前状态与开发指南.md b/docs/00-系统总体设计/00-系统当前状态与开发指南.md index 155121b2..d3ea51bc 100644 --- a/docs/00-系统总体设计/00-系统当前状态与开发指南.md +++ b/docs/00-系统总体设计/00-系统当前状态与开发指南.md @@ -1,13 +1,13 @@ # AIclinicalresearch 系统当前状态与开发指南 -> **文档版本:** v3.7 +> **文档版本:** v3.8 > **创建日期:** 2025-11-28 > **维护者:** 开发团队 -> **最后更新:** 2026-01-18 -> **重大进展:** 🎉 **ASL 智能文献检索(DeepSearch)MVP 完成!** -> - 🆕 集成 unifuncs DeepSearch API,AI 驱动的 PubMed 自动检索 -> - ✅ SSE 实时流式显示 AI 思考过程 -> - ✅ 自然语言输入,自动生成检索策略 +> **最后更新:** 2026-01-19 +> **重大进展:** 🎉 **pgvector 向量数据库集成完成!PKB RAG 基础设施就绪!** +> - 🆕 pgvector 0.8.1 已安装,支持 HNSW/IVFFlat 索引 +> - ✅ 与阿里云 RDS pgvector 0.8.0 完全兼容 +> - ✅ PKB 模块 RAG 检索功能基础设施已就绪 > **部署状态:** ✅ 生产环境运行中 | 公网地址:http://8.140.53.236/ > **文档目的:** 快速了解系统当前状态,为新AI助手提供上下文 @@ -100,7 +100,8 @@ - 架构:增量演进(legacy + common + modules) **数据库**: -- PostgreSQL 15 (Docker: postgres:15-alpine) +- PostgreSQL 15 (Docker: pgvector/pgvector:pg15) +- **pgvector 0.8.1** ✅ 2026-01-19 新增(向量数据库扩展,支持 RAG) - 12个Schema隔离(platform/aia/pkb/asl/dc/iit/ssa/st/rvw/admin/common/capability ✅新增) **云原生部署**: @@ -120,9 +121,52 @@ --- -## 🚀 当前开发状态(2026-01-18) +## 🚀 当前开发状态(2026-01-19) -### 🏆 最新进展:AIA V2.1 Prompt管理集成(2026-01-18) +### 🏆 最新进展:pgvector 向量数据库集成(2026-01-19) + +#### ✅ pgvector 0.8.1 安装成功 + +**背景**: +- PKB 模块需要实现 RAG 检索功能 +- 原计划依赖 Dify 知识库,现改为 PostgreSQL 原生 pgvector 方案 +- 与 Postgres-Only 架构理念一致,减少外部依赖 + +**完成工作**: +- ✅ Docker 镜像迁移:`postgres:15-alpine` → `pgvector/pgvector:pg15` +- ✅ pgvector 扩展安装:版本 0.8.1 +- ✅ 数据安全:执行双重备份(SQL dump + Volume tarball) +- ✅ 功能验证:前后端服务重启后功能全部正常 +- ✅ 数据完整性:用户数据、pg-boss 队列函数全部正常 + +**技术细节**: +| 项目 | 说明 | +|------|------| +| Docker 镜像 | `pgvector/pgvector:pg15` | +| pgvector 版本 | 0.8.1 | +| 支持索引类型 | HNSW、IVFFlat | +| 最大向量维度 | 16000 维 | +| 阿里云 RDS 兼容性 | ✅ 完全兼容(RDS 为 0.8.0) | + +**版本兼容性说明**: +- 开发环境:pgvector 0.8.1 +- 生产环境(阿里云 RDS):pgvector 0.8.0 +- 兼容性:0.8.x 系列向后兼容,数据格式和 API 一致 + +**文件变更**: +- `docker-compose.yml`:更新 postgres 服务镜像 +- `Dockerfile.postgres-pgvector`:自定义构建文件(备用) +- `backup_before_pgvector_20260119.sql`:迁移前备份 +- `postgres_volume_backup_20260119.tar`:Volume 备份 + +**下一步**: +- 设计 `pkb_schema.document_embeddings` 向量表 +- 集成 Embedding 服务(OpenAI/智谱) +- 实现 RAG 检索 API + +--- + +### 🏆 历史进展:AIA V2.1 Prompt管理集成(2026-01-18) #### ✅ AIA 模块 Prompt 管理系统集成 @@ -378,7 +422,7 @@ data: [DONE]\n\n **详细文档:** [AIA模块状态与开发指南](../../03-业务模块/AIA-AI智能问答/00-模块当前状态与开发指南.md) -#### 3. PKB模块 - 个人知识库 🎉 **前端V3设计完成!** +#### 3. PKB模块 - 个人知识库 🎉 **pgvector RAG基础设施就绪!** **开发进度**: - ✅ **后端API**:100%完成(v1 + v2双路由运行) @@ -387,7 +431,7 @@ data: [DONE]\n\n - ✅ **全文阅读模式**:90%完成(Chat组件集成) - ✅ **逐篇精读模式**:85%完成(文档选择+对话) - 🔧 **批处理模式**:70%完成(UI完成,API待调试) -- ❌ **RAG检索模式**:0%(后端待实现) +- 🟡 **RAG检索模式**:基础设施就绪(pgvector 0.8.1 已安装),业务逻辑待实现 **核心功能**: - 知识库CRUD + 文档管理 @@ -400,11 +444,12 @@ data: [DONE]\n\n - ✅ Zustand状态管理 - ✅ 复用shared/components/Chat通用组件 - ✅ 单层Header + 紧凑工作模式栏设计 +- ✅ **pgvector 0.8.1 已集成**(2026-01-19) **待解决问题**: - 🔧 批处理API执行待调试 - 🔧 知识资产页面导航条待完善 -- 🔧 UI与原型图精细化对比 +- 🔧 RAG 检索业务逻辑待实现(向量表设计、Embedding服务) **详细文档**:[PKB模块当前状态](../03-业务模块/PKB-个人知识库/00-模块当前状态与开发指南.md) @@ -896,7 +941,8 @@ AIclinicalresearch/ | **2026-01-02** | **REDCap对接方案** 🏆 | ✅ REDCap环境部署 + DET+REST API方案确定 | | **2026-01-07 上午** | **PKB前端V3** 🎉 | ✅ PKB模块前端V3设计实现完成(Dashboard+Workspace+3种工作模式) | | **2026-01-07 下午** | **PKB批处理完善** 🏆 | ✅ 批处理完整流程调试通过(执行+进度+结果导出)+ 文档上传功能 + UI优化 | -| **当前** | **PKB模块生产可用** | ✅ 核心功能全部实现(90%),具备生产环境部署条件 | +| **2026-01-19** | **pgvector集成** 🎉 | ✅ pgvector 0.8.1 安装成功,PKB RAG基础设施就绪 | +| **当前** | **PKB模块生产可用** | ✅ 核心功能全部实现(90%),pgvector已集成,RAG业务逻辑待开发 | | **2026-01-07 晚** | **RVW模块开发完成** 🎉 | ✅ Phase 1-3完成(后端迁移+数据库扩展+前端重构) | --- @@ -1001,7 +1047,8 @@ AIclinicalresearch/ ### 环境要求 ``` Node.js: v22.18.0+ -PostgreSQL: 15+(当前使用15.14) +PostgreSQL: 15+(当前使用15.14,Docker镜像: pgvector/pgvector:pg15) +pgvector: 0.8.1(向量数据库扩展) npm: 10+ ``` @@ -1194,14 +1241,15 @@ if (items.length >= 50) { ## 🌟 技术亮点 -1. ✅ **Platform-Only 架构**:统一任务管理,零代码重复 🏆 **新!** -2. ✅ **智能双模式处理**:小任务快速响应,大任务可靠执行 🏆 **新!** -3. ✅ **适配器模式**:存储/缓存/日志支持本地↔云端零代码切换 -4. ✅ **10个Schema一次性完成**:架构一次到位 -5. ✅ **Prisma自动路由**:Schema迁移后,代码无需修改 -6. ✅ **4个LLM集成**:DeepSeek、Qwen、GPT、Claude -7. ✅ **增量演进**:新旧并存,降低风险 -8. ✅ **云原生就绪**:为SAE部署做好准备 +1. ✅ **Platform-Only 架构**:统一任务管理,零代码重复 🏆 +2. ✅ **智能双模式处理**:小任务快速响应,大任务可靠执行 🏆 +3. ✅ **pgvector 向量数据库**:PostgreSQL 原生 RAG 支持 🏆 **2026-01-19 新增!** +4. ✅ **适配器模式**:存储/缓存/日志支持本地↔云端零代码切换 +5. ✅ **12个Schema隔离**:架构一次到位 +6. ✅ **Prisma自动路由**:Schema迁移后,代码无需修改 +7. ✅ **4个LLM集成**:DeepSeek、Qwen、GPT、Claude +8. ✅ **增量演进**:新旧并存,降低风险 +9. ✅ **云原生就绪**:为SAE部署做好准备 --- @@ -1213,9 +1261,9 @@ if (items.length >= 50) { --- -**文档版本**:v3.1 -**最后更新**:2026-01-10 -**下次更新**:RVW生产环境部署 或 ASL智能文献筛选模块启动 +**文档版本**:v3.8 +**最后更新**:2026-01-19 +**下次更新**:PKB RAG检索功能实现 或 生产环境pgvector部署 --- diff --git a/docs/02-通用能力层/Postgres-Only异步任务处理指南.md b/docs/02-通用能力层/Postgres-Only异步任务处理指南.md index bf44b222..cfdb8644 100644 --- a/docs/02-通用能力层/Postgres-Only异步任务处理指南.md +++ b/docs/02-通用能力层/Postgres-Only异步任务处理指南.md @@ -618,5 +618,6 @@ async saveProcessedData(recordId, newData) { + diff --git a/docs/02-通用能力层/快速引用卡片.md b/docs/02-通用能力层/快速引用卡片.md index 6ad4f6b7..79d0d3e7 100644 --- a/docs/02-通用能力层/快速引用卡片.md +++ b/docs/02-通用能力层/快速引用卡片.md @@ -231,3 +231,4 @@ const userId = 'test'; // ❌ 应该用 getUserId(request) + diff --git a/docs/02-通用能力层/通用能力层技术债务清单.md b/docs/02-通用能力层/通用能力层技术债务清单.md index 7c0d8397..ac0a32a1 100644 --- a/docs/02-通用能力层/通用能力层技术债务清单.md +++ b/docs/02-通用能力层/通用能力层技术债务清单.md @@ -805,5 +805,6 @@ export const AsyncProgressBar: React.FC = ({ + diff --git a/docs/03-业务模块/ADMIN-运营管理端/00-Phase3.5完成总结.md b/docs/03-业务模块/ADMIN-运营管理端/00-Phase3.5完成总结.md index 462789e6..999796c6 100644 --- a/docs/03-业务模块/ADMIN-运营管理端/00-Phase3.5完成总结.md +++ b/docs/03-业务模块/ADMIN-运营管理端/00-Phase3.5完成总结.md @@ -300,3 +300,4 @@ Level 3: 兜底Prompt(缓存也失效) + diff --git a/docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-16_用户管理功能与模块权限系统完成.md b/docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-16_用户管理功能与模块权限系统完成.md index d214e529..88715787 100644 --- a/docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-16_用户管理功能与模块权限系统完成.md +++ b/docs/03-业务模块/ADMIN-运营管理端/06-开发记录/2026-01-16_用户管理功能与模块权限系统完成.md @@ -486,3 +486,4 @@ const pageSize = Number(query.pageSize) || 20; + diff --git a/docs/03-业务模块/ADMIN-运营管理端/README.md b/docs/03-业务模块/ADMIN-运营管理端/README.md index fff9685c..eabf2d9f 100644 --- a/docs/03-业务模块/ADMIN-运营管理端/README.md +++ b/docs/03-业务模块/ADMIN-运营管理端/README.md @@ -220,3 +220,4 @@ ADMIN-运营管理端/ + diff --git a/docs/03-业务模块/ADMIN运营与INST机构管理端-文档体系建立完成.md b/docs/03-业务模块/ADMIN运营与INST机构管理端-文档体系建立完成.md index c47fc08c..11a5a6c3 100644 --- a/docs/03-业务模块/ADMIN运营与INST机构管理端-文档体系建立完成.md +++ b/docs/03-业务模块/ADMIN运营与INST机构管理端-文档体系建立完成.md @@ -319,3 +319,4 @@ INST-机构管理端/ + diff --git a/docs/03-业务模块/AIA-AI智能问答/04-开发计划/03-前端组件设计.md b/docs/03-业务模块/AIA-AI智能问答/04-开发计划/03-前端组件设计.md index 6f745aa2..d8e5fc4c 100644 --- a/docs/03-业务模块/AIA-AI智能问答/04-开发计划/03-前端组件设计.md +++ b/docs/03-业务模块/AIA-AI智能问答/04-开发计划/03-前端组件设计.md @@ -886,3 +886,4 @@ export interface SlashCommand { + diff --git a/docs/03-业务模块/AIA-AI智能问答/06-开发记录/2026-01-18-Prompt管理系统集成.md b/docs/03-业务模块/AIA-AI智能问答/06-开发记录/2026-01-18-Prompt管理系统集成.md index 03633721..d1b9ae28 100644 --- a/docs/03-业务模块/AIA-AI智能问答/06-开发记录/2026-01-18-Prompt管理系统集成.md +++ b/docs/03-业务模块/AIA-AI智能问答/06-开发记录/2026-01-18-Prompt管理系统集成.md @@ -191,3 +191,4 @@ export type AgentStage = 'topic' | 'design' | 'review' | 'data' | 'writing'; 本次开发遵循了现有 PromptService 的设计模式,与 RVW 模块集成方式保持一致。 + diff --git a/docs/03-业务模块/ASL-AI智能文献/04-开发计划/05-全文复筛前端开发计划.md b/docs/03-业务模块/ASL-AI智能文献/04-开发计划/05-全文复筛前端开发计划.md index 753435d8..0d39d676 100644 --- a/docs/03-业务模块/ASL-AI智能文献/04-开发计划/05-全文复筛前端开发计划.md +++ b/docs/03-业务模块/ASL-AI智能文献/04-开发计划/05-全文复筛前端开发计划.md @@ -1298,5 +1298,6 @@ interface FulltextScreeningResult { + diff --git a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端开发完成.md b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端开发完成.md index 07e91c73..64470068 100644 --- a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端开发完成.md +++ b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端开发完成.md @@ -412,5 +412,6 @@ GET /api/v1/asl/fulltext-screening/tasks/:taskId/export + diff --git a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端逻辑调整.md b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端逻辑调整.md index 179c1eef..82fef801 100644 --- a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端逻辑调整.md +++ b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-01-23_全文复筛前端逻辑调整.md @@ -355,5 +355,6 @@ Linter错误:0个 + diff --git a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-23_Day5_全文复筛API开发.md b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-23_Day5_全文复筛API开发.md index 63c09b97..792b547e 100644 --- a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-23_Day5_全文复筛API开发.md +++ b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2025-11-23_Day5_全文复筛API开发.md @@ -514,5 +514,6 @@ Failed to open file '\\tmp\\extraction_service\\temp_10000_test.pdf' + diff --git a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2026-01-18_智能文献检索DeepSearch集成.md b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2026-01-18_智能文献检索DeepSearch集成.md index b1cf3aea..c97acb55 100644 --- a/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2026-01-18_智能文献检索DeepSearch集成.md +++ b/docs/03-业务模块/ASL-AI智能文献/05-开发记录/2026-01-18_智能文献检索DeepSearch集成.md @@ -172,3 +172,4 @@ UNIFUNCS_API_KEY=sk-xxxx - [Postgres-Only 异步任务处理指南](../../02-通用能力层/Postgres-Only异步任务处理指南.md) - [数据库开发规范](../../04-开发规范/09-数据库开发规范.md) + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_AI_Few-shot示例库.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_AI_Few-shot示例库.md index 1efd0d53..32280b02 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_AI_Few-shot示例库.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_AI_Few-shot示例库.md @@ -580,5 +580,6 @@ df['creatinine'] = pd.to_numeric(df['creatinine'], errors='coerce') + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Bug修复总结_2025-12-08.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Bug修复总结_2025-12-08.md index b9e91dac..2e315a89 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Bug修复总结_2025-12-08.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Bug修复总结_2025-12-08.md @@ -418,5 +418,6 @@ npm run dev + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day3开发计划.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day3开发计划.md index 11982531..d9cd50f4 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day3开发计划.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day3开发计划.md @@ -995,5 +995,6 @@ export const aiController = new AIController(); + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day4-5前端开发计划.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day4-5前端开发计划.md index c2c0a11c..c2f48681 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day4-5前端开发计划.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Day4-5前端开发计划.md @@ -1329,5 +1329,6 @@ npm install react-markdown + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Pivot列顺序优化总结.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Pivot列顺序优化总结.md index bc5f196b..5deafb4c 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Pivot列顺序优化总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_Pivot列顺序优化总结.md @@ -237,5 +237,6 @@ FMA___基线 | FMA___1个月 | FMA___2个月 + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_方案B实施总结_2025-12-09.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_方案B实施总结_2025-12-09.md index 9f57414b..f44d638d 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_方案B实施总结_2025-12-09.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_方案B实施总结_2025-12-09.md @@ -395,5 +395,6 @@ formula = "FMA总分(0-100) / 100" + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理_开发进度_2025-12-10.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理_开发进度_2025-12-10.md index f79a1302..211e0db8 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理_开发进度_2025-12-10.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理_开发进度_2025-12-10.md @@ -229,5 +229,6 @@ async handleFillnaMice(request, reply) { + diff --git a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理功能_更新说明.md b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理功能_更新说明.md index d98aeeca..f753a756 100644 --- a/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理功能_更新说明.md +++ b/docs/03-业务模块/DC-数据清洗整理/04-开发计划/工具C_缺失值处理功能_更新说明.md @@ -201,5 +201,6 @@ method: 'mean' | 'median' | 'mode' | 'constant' | 'ffill' | 'bfill' + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-02_工作总结.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-02_工作总结.md index c8d4755c..bb489398 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-02_工作总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-02_工作总结.md @@ -351,5 +351,6 @@ Changes: + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day1开发完成总结.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day1开发完成总结.md index 94f768a6..03ccac27 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day1开发完成总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day1开发完成总结.md @@ -423,5 +423,6 @@ cd path; command + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day2开发完成总结.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day2开发完成总结.md index 6b9af4b5..e091b24d 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day2开发完成总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-06_工具C_Day2开发完成总结.md @@ -652,5 +652,6 @@ import { logger } from '../../../../common/logging/index.js'; + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_AI对话核心功能增强总结.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_AI对话核心功能增强总结.md index b148be36..94457185 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_AI对话核心功能增强总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_AI对话核心功能增强总结.md @@ -656,5 +656,6 @@ Content-Length: 45234 + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Bug修复_DataGrid空数据防御.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Bug修复_DataGrid空数据防御.md index 38516ccf..2e929808 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Bug修复_DataGrid空数据防御.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Bug修复_DataGrid空数据防御.md @@ -308,5 +308,6 @@ Response: + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5_Ant-Design-X重构完成.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5_Ant-Design-X重构完成.md index b5fcbcab..dcd18d0b 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5_Ant-Design-X重构完成.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5_Ant-Design-X重构完成.md @@ -461,5 +461,6 @@ Response: + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5最终总结.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5最终总结.md index 38407823..a4a605b3 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5最终总结.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_Day5最终总结.md @@ -455,5 +455,6 @@ import { ChatContainer } from '@/shared/components/Chat'; + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_UI优化与Bug修复.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_UI优化与Bug修复.md index 7c794548..f43f9c6e 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_UI优化与Bug修复.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_UI优化与Bug修复.md @@ -365,5 +365,6 @@ const initialMessages = defaultMessages.length > 0 ? defaultMessages : [{ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_后端API完整对接完成.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_后端API完整对接完成.md index dffff1da..e0f6cfb3 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_后端API完整对接完成.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_后端API完整对接完成.md @@ -405,5 +405,6 @@ python main.py + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_完整UI优化与功能增强.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_完整UI优化与功能增强.md index a4c0cbee..7e279914 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_完整UI优化与功能增强.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_完整UI优化与功能增强.md @@ -653,5 +653,6 @@ http://localhost:5173/data-cleaning/tool-c + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_工具C_Day4前端基础完成.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_工具C_Day4前端基础完成.md index dba9548c..33a35327 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_工具C_Day4前端基础完成.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/2025-12-07_工具C_Day4前端基础完成.md @@ -263,5 +263,6 @@ Day 5 (6-8小时): + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建完成总结-Day1.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建完成总结-Day1.md index fc6169e7..a4a82676 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建完成总结-Day1.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建完成总结-Day1.md @@ -441,5 +441,6 @@ Docs: docs/03-业务模块/DC-数据清洗整理/06-开发记录/DC模块重建 + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase1-Portal页面开发完成-2025-12-02.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase1-Portal页面开发完成-2025-12-02.md index 939ec648..944e158e 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase1-Portal页面开发完成-2025-12-02.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase1-Portal页面开发完成-2025-12-02.md @@ -416,5 +416,6 @@ const mockAssets: Asset[] = [ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase2-ToolB-Step1-2开发完成-2025-12-03.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase2-ToolB-Step1-2开发完成-2025-12-03.md index 45796159..c909229b 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase2-ToolB-Step1-2开发完成-2025-12-03.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Phase2-ToolB-Step1-2开发完成-2025-12-03.md @@ -400,5 +400,6 @@ frontend-v2/src/modules/dc/ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Portal页面UI优化-2025-12-02.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Portal页面UI优化-2025-12-02.md index 34238806..ad9da518 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Portal页面UI优化-2025-12-02.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Portal页面UI优化-2025-12-02.md @@ -360,5 +360,6 @@ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Tool-B-MVP完成总结-2025-12-03.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Tool-B-MVP完成总结-2025-12-03.md index 24517ffa..b4669e51 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Tool-B-MVP完成总结-2025-12-03.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/Tool-B-MVP完成总结-2025-12-03.md @@ -314,5 +314,6 @@ ConflictDetectionService // 冲突检测(字段级对比) + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-2025-12-03.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-2025-12-03.md index 01a80baa..752bf080 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-2025-12-03.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-2025-12-03.md @@ -363,5 +363,6 @@ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-Round2-2025-12-03.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-Round2-2025-12-03.md index 3954c378..440aaf53 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-Round2-2025-12-03.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB-UI优化-Round2-2025-12-03.md @@ -326,5 +326,6 @@ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB浏览器测试计划-2025-12-03.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB浏览器测试计划-2025-12-03.md index c0df8b0a..af3f66dd 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB浏览器测试计划-2025-12-03.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/ToolB浏览器测试计划-2025-12-03.md @@ -390,5 +390,6 @@ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/后端API测试报告-2025-12-02.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/后端API测试报告-2025-12-02.md index 2097bf61..1fc3812a 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/后端API测试报告-2025-12-02.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/后端API测试报告-2025-12-02.md @@ -478,5 +478,6 @@ Tool B后端代码**100%复用**了平台通用能力层,无任何重复开发 + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/待办事项-下一步工作.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/待办事项-下一步工作.md index 9f5e6e94..80e37478 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/待办事项-下一步工作.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/待办事项-下一步工作.md @@ -324,5 +324,6 @@ + diff --git a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/数据库验证报告-2025-12-02.md b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/数据库验证报告-2025-12-02.md index a0830a7d..0f7a6d42 100644 --- a/docs/03-业务模块/DC-数据清洗整理/06-开发记录/数据库验证报告-2025-12-02.md +++ b/docs/03-业务模块/DC-数据清洗整理/06-开发记录/数据库验证报告-2025-12-02.md @@ -255,5 +255,6 @@ $ node scripts/check-dc-tables.mjs + diff --git a/docs/03-业务模块/DC-数据清洗整理/07-技术债务/Tool-B技术债务清单.md b/docs/03-业务模块/DC-数据清洗整理/07-技术债务/Tool-B技术债务清单.md index 9b97a4d6..10337f28 100644 --- a/docs/03-业务模块/DC-数据清洗整理/07-技术债务/Tool-B技术债务清单.md +++ b/docs/03-业务模块/DC-数据清洗整理/07-技术债务/Tool-B技术债务清单.md @@ -488,5 +488,6 @@ ${fields.map((f, i) => `${i + 1}. ${f.name}:${f.desc}`).join('\n')} + diff --git a/docs/03-业务模块/IIT Manager Agent/02-技术设计/IIT Manager Agent 技术路径与架构设计.md b/docs/03-业务模块/IIT Manager Agent/02-技术设计/IIT Manager Agent 技术路径与架构设计.md index dd4adf63..e1adbf26 100644 --- a/docs/03-业务模块/IIT Manager Agent/02-技术设计/IIT Manager Agent 技术路径与架构设计.md +++ b/docs/03-业务模块/IIT Manager Agent/02-技术设计/IIT Manager Agent 技术路径与架构设计.md @@ -694,4 +694,5 @@ private async processMessageAsync(xmlData: any) { + diff --git a/docs/03-业务模块/IIT Manager Agent/04-开发计划/REDCap对接技术方案与实施指南.md b/docs/03-业务模块/IIT Manager Agent/04-开发计划/REDCap对接技术方案与实施指南.md index de72c225..15ad37c3 100644 --- a/docs/03-业务模块/IIT Manager Agent/04-开发计划/REDCap对接技术方案与实施指南.md +++ b/docs/03-业务模块/IIT Manager Agent/04-开发计划/REDCap对接技术方案与实施指南.md @@ -1087,5 +1087,6 @@ async function testIntegration() { + diff --git a/docs/03-业务模块/IIT Manager Agent/04-开发计划/企业微信注册指南.md b/docs/03-业务模块/IIT Manager Agent/04-开发计划/企业微信注册指南.md index ac89cd69..28bead5c 100644 --- a/docs/03-业务模块/IIT Manager Agent/04-开发计划/企业微信注册指南.md +++ b/docs/03-业务模块/IIT Manager Agent/04-开发计划/企业微信注册指南.md @@ -228,5 +228,6 @@ Content-Type: application/json + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/2026-01-04-Dify知识库集成开发记录.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/2026-01-04-Dify知识库集成开发记录.md index 3f280aa8..bd59412f 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/2026-01-04-Dify知识库集成开发记录.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/2026-01-04-Dify知识库集成开发记录.md @@ -649,4 +649,5 @@ REDCap API: exportRecords success { recordCount: 1 } + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day2-REDCap实时集成开发完成记录.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day2-REDCap实时集成开发完成记录.md index 2e5ea4b6..6a5f7b12 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day2-REDCap实时集成开发完成记录.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day2-REDCap实时集成开发完成记录.md @@ -654,5 +654,6 @@ backend/src/modules/iit-manager/ + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成与端到端测试完成记录.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成与端到端测试完成记录.md index 18688b44..e4d41bec 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成与端到端测试完成记录.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成与端到端测试完成记录.md @@ -804,5 +804,6 @@ CREATE TABLE iit_schema.wechat_tokens ( + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成开发完成记录.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成开发完成记录.md index 64f353a4..48f54bc4 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成开发完成记录.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Day3-企业微信集成开发完成记录.md @@ -561,5 +561,6 @@ Day 3 的开发工作虽然遇到了多个技术问题,但最终成功完成 + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Phase1.5-AI对话集成REDCap完成记录.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Phase1.5-AI对话集成REDCap完成记录.md index e91455de..dc291ff3 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/Phase1.5-AI对话集成REDCap完成记录.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/Phase1.5-AI对话集成REDCap完成记录.md @@ -328,5 +328,6 @@ AI: "出生日期:2017-01-04 + diff --git a/docs/03-业务模块/IIT Manager Agent/06-开发记录/V1.1更新完成报告.md b/docs/03-业务模块/IIT Manager Agent/06-开发记录/V1.1更新完成报告.md index 56128af8..b572bc41 100644 --- a/docs/03-业务模块/IIT Manager Agent/06-开发记录/V1.1更新完成报告.md +++ b/docs/03-业务模块/IIT Manager Agent/06-开发记录/V1.1更新完成报告.md @@ -272,5 +272,6 @@ Day 4: REDCap EM(Webhook推送)← 作为增强,而非核心 + diff --git a/docs/03-业务模块/IIT Manager Agent/07-技术债务/IIT Manager Agent 技术债务清单.md b/docs/03-业务模块/IIT Manager Agent/07-技术债务/IIT Manager Agent 技术债务清单.md index cc5a8b4e..6fa47f96 100644 --- a/docs/03-业务模块/IIT Manager Agent/07-技术债务/IIT Manager Agent 技术债务清单.md +++ b/docs/03-业务模块/IIT Manager Agent/07-技术债务/IIT Manager Agent 技术债务清单.md @@ -687,4 +687,5 @@ const answer = `根据研究方案[1]和CRF表格[2],纳入标准包括: + diff --git a/docs/03-业务模块/INST-机构管理端/00-模块当前状态与开发指南.md b/docs/03-业务模块/INST-机构管理端/00-模块当前状态与开发指南.md index 165e904b..3962f9ab 100644 --- a/docs/03-业务模块/INST-机构管理端/00-模块当前状态与开发指南.md +++ b/docs/03-业务模块/INST-机构管理端/00-模块当前状态与开发指南.md @@ -445,3 +445,4 @@ export const calculateAvailableQuota = async (tenantId: string) => { + diff --git a/docs/03-业务模块/INST-机构管理端/README.md b/docs/03-业务模块/INST-机构管理端/README.md index 3055d4c6..4e980d2a 100644 --- a/docs/03-业务模块/INST-机构管理端/README.md +++ b/docs/03-业务模块/INST-机构管理端/README.md @@ -318,3 +318,4 @@ https://platform.example.com/t/pharma-abc/login + diff --git a/docs/03-业务模块/PKB-个人知识库/00-模块当前状态与开发指南.md b/docs/03-业务模块/PKB-个人知识库/00-模块当前状态与开发指南.md index d9511d34..de5aa5d7 100644 --- a/docs/03-业务模块/PKB-个人知识库/00-模块当前状态与开发指南.md +++ b/docs/03-业务模块/PKB-个人知识库/00-模块当前状态与开发指南.md @@ -1,10 +1,11 @@ # PKB个人知识库模块 - 当前状态与开发指南 -> **文档版本:** v2.0 +> **文档版本:** v2.1 > **创建日期:** 2026-01-07 > **维护者:** PKB模块开发团队 -> **最后更新:** 2026-01-07 -> **重大进展:** 🎉 **PKB模块核心功能全部实现,具备生产可用性!** +> **最后更新:** 2026-01-19 +> **重大进展:** 🎉 **PKB模块核心功能全部实现,pgvector向量数据库已集成!** +> **基础设施:** ✅ pgvector 0.8.1 已安装,RAG检索模式基础设施就绪 > **文档目的:** 反映模块真实状态,记录开发历程 --- @@ -65,10 +66,11 @@ UI组件: Ant Design v6 + Ant Design X ``` 框架: Fastify v4 (Node.js 22) -数据库: PostgreSQL 15 + Prisma 6 +数据库: PostgreSQL 15 + Prisma 6 + pgvector 0.8.1 Schema: pkb_schema (独立隔离) +向量存储: pgvector (PostgreSQL原生向量扩展) ✅ 2026-01-19 已集成 LLM: DeepSeek-V3, Qwen-Max (通过LLMFactory) -RAG: Dify知识库集成 +RAG: Dify知识库集成 → 计划迁移到 pgvector 原生RAG 存储: OSS对象存储 ``` @@ -210,30 +212,41 @@ frontend-v2/src/modules/pkb/ **当前状态**:🔧 API执行待调试 -### 4. RAG检索模式(待开发) +### 4. RAG检索模式(基础设施就绪) **功能说明**: - 基于向量检索 - 精准定位相关段落 - 适合快速查找 -**当前状态**:❌ 后端待实现 +**当前状态**:🟡 基础设施已就绪(pgvector 0.8.1 已安装),后端业务逻辑待实现 + +**技术基础**(2026-01-19 完成): +- ✅ pgvector 扩展已安装(版本 0.8.1) +- ✅ 支持 HNSW 和 IVFFlat 索引 +- ✅ 与阿里云 RDS pgvector 0.8.0 兼容 +- ⏳ 向量表设计待实现 +- ⏳ Embedding 服务集成待实现 +- ⏳ 相似度检索 API 待实现 --- ## ⚠️ 已知问题 -### 1. RAG检索模式未实现 🟡 中优先级 +### 1. RAG检索模式业务逻辑未实现 🟡 中优先级 **问题描述**: -- RAG检索模式暂未实现 +- pgvector 基础设施已就绪(2026-01-19) +- RAG检索业务逻辑待实现 - 当前优先全文阅读和逐篇精读模式 **影响**:工作模式选择有限 **解决方案**: -- v2.1版本实现RAG检索 -- 集成Dify知识库检索能力 +- v2.1版本实现RAG检索(基于pgvector,不再依赖Dify) +- 设计向量表结构(pkb_schema.document_embeddings) +- 集成 Embedding 服务(OpenAI/智谱) +- 实现相似度检索 API ### 2. 批处理模板有限 🟢 低优先级 @@ -265,8 +278,11 @@ frontend-v2/src/modules/pkb/ ### v2.1 版本(短期) -1. **RAG检索模式** 🟡 - - 实现基于Dify的知识库检索 +1. **RAG检索模式** 🟡 (基础设施已就绪 ✅) + - ✅ pgvector 0.8.1 已安装 + - 设计向量表结构(pkb_schema.document_embeddings) + - 集成 Embedding 服务(文本向量化) + - 实现相似度检索 API - 添加工作模式选择器 - 测试检索准确度 @@ -394,7 +410,32 @@ frontend-v2/src/modules/pkb/ --- -**最后更新:** 2026-01-07 +--- + +## 📝 更新日志 + +### 2026-01-19 pgvector 向量数据库集成 + +**重大变更**: +- ✅ **pgvector 0.8.1 安装成功**:Docker 环境已迁移到 `pgvector/pgvector:pg15` 镜像 +- ✅ **兼容性验证**:与阿里云 RDS pgvector 0.8.0 完全兼容 +- ✅ **功能验证**:前后端服务重启后功能正常 +- ✅ **数据完整性**:用户数据、知识库数据、pg-boss 队列函数全部正常 + +**技术细节**: +- 镜像:`pgvector/pgvector:pg15` +- 扩展版本:0.8.1 +- 支持索引类型:HNSW、IVFFlat +- 向量维度:最高支持 16000 维 + +**下一步**: +- 设计 `pkb_schema.document_embeddings` 表 +- 集成 Embedding 服务 +- 实现 RAG 检索 API + +--- + +**最后更新:** 2026-01-19 **文档维护:** PKB模块开发团队 **联系方式:** 项目Issues diff --git a/docs/03-业务模块/PKB-个人知识库/00-系统设计/企业级医学知识库_综合技术解决方案 V2.md b/docs/03-业务模块/PKB-个人知识库/00-系统设计/企业级医学知识库_综合技术解决方案 V2.md new file mode 100644 index 00000000..f97f7520 --- /dev/null +++ b/docs/03-业务模块/PKB-个人知识库/00-系统设计/企业级医学知识库_综合技术解决方案 V2.md @@ -0,0 +1,191 @@ +# **企业级医学知识库 (EKB) 综合技术解决方案** + +版本: v2.0 (增强版:临床数据全要素结构化) +核心目标: 构建高精度、可追溯、基于医学证据的企业级知识库 +技术栈: Node.js, Python, PostgreSQL (pgvector), DeepSeek, pymupdf4llm +设计范式: R-C-R-G (Router \- Concurrent \- Rerank \- Generate) + +## **1\. 总体架构设计** + +本方案采用 **"Postgres-Only"** 极简架构,利用 Node.js 进行业务编排,Python 进行文档解析,外部 API 提供 AI 算力。 + +### **1.1 核心组件** + +1. **解析层 (Python Microservice)**: + * **核心工具**:pymupdf4llm + * **作用**:将 PDF(含复杂表格)转换为 **Markdown** 格式,保留结构化语义。 +2. **存储层 (PostgreSQL 15+)**: + * **三维信息架构**: + 1. **文献属性信息** (Metadata):PMID、IF分、期刊等。 + 2. **文献关键内容信息** (Clinical Data):PICO、用药方案、不良反应、入排标准、终点指标等(JSONB存储)。 + 3. **向量信息** (Vector):全文切片的语义向量。 +3. **计算层 (Node.js \+ External APIs)**: + * **Embedding**:调用 text-embedding-v4 或 BGE-M3 API。 + * **Rerank**:调用 qwen-rerank API。 + * **Reasoning**:调用 DeepSeek V3 进行全要素提取和答案生成。 +4. **文件层 (OSS)**: + * 存储原始 PDF 和生成的 Markdown 文件。 + +## **2\. 数据模型设计 (存储方案)** + +利用 PostgreSQL 的强大扩展性,我们在单库中实现多种数据类型的融合存储,构建**健壮的临床数据库**。 + +### **2.1 数据库 Schema (Prisma 描述)** + +// 1\. 文档主表:承载 "属性信息" 与 "关键内容信息" +model EkbDocument { + id String @id @default(uuid()) + projectId String // 业务隔离 + + // \--- A. 文档属性信息 (Metadata) \- 用于基础筛选 \--- + title String + abstract String? @db.Text // 原始摘要 + pmid String? @unique + doi String? + journal String? + authors String\[\] + publishYear Int // 用于 "2024年最新" 筛选 + ifScore Float? // 用于 "高分文献" 筛选 + docType String // 指南/RCT/综述/病例报告 + + // \--- B. 文档关键内容信息 (Clinical Data) \- AI 提取的结构化金矿 \--- + // 使用 JSONB 存储,支持 GIN 索引,实现 "SQL 级" 的精准查询 + + // 1\. PICO 要素 + // { "P": "晚期NSCLC", "I": "Keytruda", "C": "化疗", "O": "OS, PFS" } + pico Json? + + // 2\. 研究设计与样本 + // { "design": "Phase III RCT", "sampleSize": 500, "blinding": "Double-blind" } + studyDesign Json? + + // 3\. 药物与剂量 (Regimen) + // \[ { "drug": "Pembrolizumab", "dose": "200mg", "freq": "Q3W" } \] + regimen Json? + + // 4\. 安全性与不良反应 (Safety) + // { "ae\_all": \["Rash", "Fatigue"\], "ae\_grade34": \["Pneumonitis"\], "dropout\_rate": "5%" } + safety Json? + + // 5\. 入排标准 (Criteria) + // { "inclusion": \["Age \>= 18", "EGFR \-"\], "exclusion": \["Autoimmune disease"\] } + criteria Json? + + // 6\. 观察指标 (Endpoints) + // { "primary": \["PFS"\], "secondary": \["OS", "ORR"\], "results": {"PFS\_HR": 0.5} } + endpoints Json? + + // \--- C. 系统信息 \--- + fileKey String // PDF OSS 路径 + mdKey String? // Markdown OSS 路径 + status String // PENDING, PROCESSED, FAILED + + chunks EkbChunk\[\] + + // \--- 索引优化 \--- + @@index(\[projectId\]) + @@index(\[publishYear\]) + @@index(\[ifScore\]) + // GIN 索引:让 JSON 字段支持高速查询 (e.g. 搜特定不良反应) + @@index(\[pico\], type: Gin) + @@index(\[regimen\], type: Gin) + @@index(\[safety\], type: Gin) +} + +// 2\. 切片表:向量信息 \+ 文本内容 +model EkbChunk { + id String @id @default(uuid()) + documentId String + + // \--- D. 切片内容 \--- + content String @db.Text // Markdown 格式的切片文本 + pageNumber Int // 溯源锚点 + sectionType String? // 标记切片来源:Title, Abstract, Methods, Results, Discussion + + // \--- E. 向量信息 \--- + // 使用 Unsupported 类型支持 pgvector + embedding Unsupported("vector(1024)")? + + document EkbDocument @relation(fields: \[documentId\], references: \[id\], onDelete: Cascade) +} + +## **3\. 数据处理流水线 (Ingestion Pipeline)** + +此流程负责将非结构化的 PDF 转化为结构化的数据库记录。 + +### **步骤一:解析与转换 (Python)** + +* **工具**:pymupdf4llm +* **输入**:PDF 文件流。 +* **输出**:Markdown 文本(保留表格结构)。 + +### **步骤二:全要素智能提取 (DeepSeek)** + +这是构建健壮数据库的关键一步。 + +* **操作**:将全文 Markdown(或前 10k token)丢给 DeepSeek V3。 +* **Prompt**:"你是一个医学数据专家。请阅读这篇文献,严格按照以下 JSON 格式提取关键信息。如果文中未提及,字段留空。 + 1. **pico**: { P, I, C, O } + 2. **studyDesign**: { design (如RCT), sampleSize (数字), blinding } + 3. **regimen**: 提取主要药物名称、剂量、给药频率。 + 4. **safety**: 提取主要不良反应(Adverse Events)及严重不良反应。 + 5. **criteria**: 简要概括核心入选和排除标准。 + 6. **endpoints**: 主要和次要观察指标。 + +输出必须是纯 JSON。" + +* **存储**:解析返回的 JSON,分别填入 EkbDocument 的对应字段。 + +### **步骤三:切片与向量化 (Node.js)** + +* **切片器**:RecursiveCharacterTextSplitter。 +* **增强策略**:在切片 content 前面加上元数据头。例如:\[Design: RCT\] \[Sample: 500\] ...原文...。这能显著增加向量检索的召回率。 +* **存储**:存入 EkbChunk。 + +## **4\. 检索与问答策略 (增强版 R-C-R-G)** + +有了结构化数据,我们的检索策略从“模糊搜”升级为“精准筛 \+ 模糊搜”。 + +### **4.1 Router (意图路由)** + +用户提问后,调用 LLM 判断意图并提取**结构化参数**: + +1. **安全性查询** \-\> 提取不良反应关键词 (e.g., "Rash")。 +2. **方案对比** \-\> 提取药物名称 (e.g., "Keytruda")。 +3. **高质筛选** \-\> 提取样本量阈值 (e.g., "n \> 100")。 + +### **4.2 Concurrent Retrieval (并发混合召回)** + +Node.js 并行执行以下查询,最后取并集: + +* 路径 A (SQL 精准筛选 \- 新增杀手锏): + 利用 JSONB 字段进行逻辑过滤。 + * *Query*: SELECT id FROM EkbDocument WHERE safety-\>\>'ae\_all' ILIKE '%Pneumonitis%' (找提到肺炎副作用的) + * *Query*: SELECT id FROM EkbDocument WHERE (studyDesign-\>\>'sampleSize')::int \> 100 (找大样本研究) +* 路径 B (向量检索): + 在路径 A 圈定的 ID 范围内,执行 ORDER BY embedding \<=\> query\_vec。 +* 路径 C (关键词检索): + 使用 ts\_rank 捕捉专有名词。 + +### **4.3 Rerank (重排序)** + +* **工具**:qwen-rerank API。 +* **策略**:输入用户问题 \+ 混合召回的 Top 50 切片。 + +### **4.4 Generate (生成与溯源)** + +* **模型**:DeepSeek V3/R1。 +* **优势**:此时 LLM 拿到的 Context 不仅有文本切片,还可以注入该文档的结构化信息(如样本量、PICO),使得回答更加立体。 + +## **5\. 实施关键检查点** + +1. **JSONB 性能**:PostgreSQL 的 JSONB 查询非常快,但务必建立 GIN 索引(如 @@index(\[safety\], type: Gin)),否则全表扫描会很慢。 +2. **提取成本**:全要素提取会消耗更多 Input Token。按 1000 篇文献算,DeepSeek V3 成本约为 20-30 元人民币,完全可接受。 +3. **数据清洗**:AI 提取的 JSON 可能会有格式错误,Node.js 端需要加一层 try-catch 和简单的格式校验(如 JSON.parse 失败重试)。 + +## **6\. 总结** + +这套升级后的方案,不仅是一个**知识库**,更是一个**轻量级的 RWE (真实世界证据) 数据库**。 + +* **查询能力质变**:从只能问“文章说了什么”,升级为能问“有哪些文章是用 200mg 剂量的”或“有哪些三期临床涉及了亚洲人”。 +* **应用场景扩展**:支持自动生成 **Meta 分析草稿**、**竞品安全性对比表**、**指南用药推荐汇总** 等高级应用。 \ No newline at end of file diff --git a/docs/03-业务模块/PKB-个人知识库/00-系统设计/医疗科研AI系统架构评估报告:PostgreSQL与pgvector在RAG及知识库中的深度应用分析.md b/docs/03-业务模块/PKB-个人知识库/00-系统设计/医疗科研AI系统架构评估报告:PostgreSQL与pgvector在RAG及知识库中的深度应用分析.md new file mode 100644 index 00000000..4e4723f1 --- /dev/null +++ b/docs/03-业务模块/PKB-个人知识库/00-系统设计/医疗科研AI系统架构评估报告:PostgreSQL与pgvector在RAG及知识库中的深度应用分析.md @@ -0,0 +1,602 @@ +# **医疗科研AI系统架构评估报告:PostgreSQL与pgvector在RAG及知识库中的深度应用分析** + +## **1\. 执行摘要** + +本报告旨在为一家中国的医疗科研创业AI公司提供关于技术选型及其架构决策的深度分析,重点评估利用PostgreSQL数据库的扩展插件pgvector构建检索增强生成(RAG)系统及医疗知识库的可行性、性能表现及行业最佳实践。 + +经过对技术架构、医疗领域需求及当前中国云服务生态的详尽调研,本报告得出以下核心结论: + +1. **战略契合度极高(Reliability & Fit)**:对于一家处于创业阶段且数据规模在“数千至数百万”篇文献量级的医疗AI公司,采用PostgreSQL集成pgvector不仅是“靠谱”的方案,更是**最优的架构决策**。它避免了引入专用向量数据库带来的运维复杂性和数据一致性风险,完全契合创业团队对开发效率和系统稳定性的要求。 +2. **医疗场景的独特优势(Unique Capabilities)**:PostgreSQL最大的竞争壁垒在于其原生支持**混合检索(Hybrid Search)**。医疗科研对查准率要求极高(如区分“5mg”与“50mg”的剂量差异,或精准匹配特定药物名称),单纯的向量语义检索往往难以满足。pgvector与PostgreSQL内置的全文检索(tsvector)结合,能够通过互惠排名融合(RRF)算法,在单一ACID事务中同时实现语义理解与关键词精准匹配,这是大多数独立向量数据库难以企及的能力。 +3. **容量与扩展性(Capacity & Scalability)**:针对用户关心的“几千还是几万篇文献”的容量问题,pgvector的处理能力远超此量级。在标准硬件配置下,它可以轻松承载**数千万级**的向量数据(对应数十万篇全长医学文献的切片)。只有在数据量突破亿级(100M+ vectors)时,才需考虑分片或迁移至分布式专用向量引擎。 +4. **国产化与合规(Ecosystem)**:阿里云、腾讯云及华为云的RDS PostgreSQL服务均已全面支持pgvector(包括最新的HNSW索引),这为医疗数据的本地化部署与合规性提供了坚实的基础设施保障。 + +本报告将从技术原理、架构对比、医疗场景实战、局限性分析及落地实施指南五个维度,展开长达15,000字的深度论述。 + +## --- + +**2\. 技术背景与架构演进** + +### **2.1 医疗科研AI面临的“检索”挑战** + +在构建医疗垂直领域的RAG系统时,核心痛点并非在于大模型(LLM)的生成能力,而在于**检索(Retrieval)的精准度**。医疗数据具有以下显著特征: + +* **术语严谨性**:医学术语(如“心肌梗死”与“心绞痛”)在语义上相近,但在临床路径上截然不同。向量模型有时会因语义泛化而混淆两者。 +* **多模态信息**:科研文献中包含大量图表、剂量数值、分子式等非结构化文本,这些信息难以通过单一的文本嵌入(Embedding)完美表达。 +* **数据一致性**:临床指南或药物说明书的更新必须实时反映在系统中。如果数据库与向量库分离,极易出现“幻觉”——即LLM基于旧版本的检索结果生成错误的医疗建议。 + +### **2.2 向量数据库的“分久必合”** + +过去三年,AI技术栈经历了从“分离式架构”向“融合式架构”的演进。 + +* **第一阶段(2022-2023)**:应用通常采用“PostgreSQL(存储元数据) \+ Pinecone/Milvus(存储向量)”的双库架构。这种架构虽然性能强劲,但带来了双倍的运维成本、网络延迟及数据同步难题(Data Consistency Drift)。 +* **第二阶段(2024-2026)**:随着pgvector、pg\_embedding等插件的成熟,PostgreSQL具备了原生向量处理能力。对于95%的企业级应用(数据量在1亿向量以下),“全能型数据库”(Converged Database)成为主流选择。它允许开发者在一条SQL语句中同时完成关系型筛选(如“筛选2024年后的论文”)和语义检索(如“查找关于免疫疗法的研究”)1。 + +对于初创公司而言,选择pgvector意味着将技术栈复杂度降低了50%,这是在激烈的市场竞争中保持迭代速度的关键优势。 + +## --- + +**3\. 深度解析:PostgreSQL \+ pgvector 的核心能力(回应问题 1 & 2)** + +### **3.1 什么是 pgvector?** + +pgvector 是一个基于PostgreSQL的开源扩展插件,它赋予了PostgreSQL存储、索引和查询高维向量数据的能力。它不是一个独立的数据库,而是作为一种新的数据类型(Data Type)和索引方法(Index Access Method)嵌入在PostgreSQL内核中。 + +#### **3.1.1 核心数据结构** + +pgvector 并非简单的存储工具,它针对AI场景引入了多种专用数据类型,极大地丰富了应用场景: + +* **vector (Dense Vector)**: + * **描述**:标准的稠密向量类型,支持最高16,000维(默认编译配置通常为2,000维,可调整)。 + * **医疗应用**:完美适配**BioBERT**(768维)、**PubMedBERT**或OpenAI text-embedding-3(1536/3072维)生成的嵌入向量。这是构建医疗文献语义索引的基础 3。 +* **halfvec (Half-Precision Vector)**: + * **描述**:在pgvector 0.7.0版本中引入,使用16位浮点数(FP16)代替标准的32位浮点数(FP32)存储维度数据。 + * **价值**:这一特性对医疗初创公司至关重要。它将索引占用的内存(RAM)直接**减半**。基准测试显示,在医疗文献检索任务中,FP16相比FP32的检索精度损失(Recall Loss)通常小于1%,但能够让原本需要64GB内存的服务器承载两倍的数据量,极大地降低了云资源成本 5。 +* **sparsevec (Sparse Vector)**: + * **描述**:稀疏向量支持,仅存储非零元素。 + * **医疗应用**:这是实现**SPLADE**(Sparse Lexical and Expansion)等高级检索模型的关键。在医疗领域,许多文档特征是稀疏的(例如,在数万种药物中,一篇论文可能只提及了“阿司匹林”和“氯吡格雷”)。使用稀疏向量可以比稠密向量更精准地捕捉这些关键词特征,避免语义漂移 6。 +* **bit (Binary Vector)**: + * **描述**:支持二进制向量及海明距离(Hamming Distance)、杰卡德相似系数(Jaccard Distance)。 + * **医疗应用**:这是**化学信息学**的神器。在药物研发中,分子指纹(Molecular Fingerprints)通常表示为二进制串(如MACCS Keys)。利用pgvector的位运算索引,科研人员可以毫秒级在数百万分子库中检索结构相似的化合物,这是通用文本向量库(如OpenAI Embeddings)无法直接做到的 6。 + +### **3.2 索引机制:HNSW 与 IVFFlat 的抉择** + +PostgreSQL 的查询优化器极其强大,而pgvector为向量数据提供了两种核心索引算法。理解它们的差异对于系统调优至关重要。 + +#### **3.2.1 HNSW (Hierarchical Navigable Small World)** + +* **原理**:这是一种基于图(Graph-based)的索引算法。它构建了一个分层的“小世界”网络,搜索过程类似于在地图上从洲际公路(高层)逐级导航到街道(底层)。 +* **性能**:HNSW是目前业界的**性能金标准**(State-of-the-Art)。它提供了极高的查询速度(低延迟)和召回率(Recall)。 +* **pgvector实战**:自0.5.0版本引入HNSW以来,pgvector的查询性能已能与Milvus、Qdrant等专用库媲美。对于医疗科研系统,**强烈推荐默认使用HNSW索引**。尽管其构建速度较慢且内存占用较高,但它能保证医生在查询“罕见病治疗方案”时,不会因为索引精度问题而漏掉关键文献 9。 + +#### **3.2.2 IVFFlat (Inverted File with Flat Compression)** + +* **原理**:基于聚类(Clustering)的倒排索引。它将向量空间划分为多个区域(Lists),查询时先找到最近的区域中心,再遍历该区域内的向量。 +* **局限**:如果查询向量位于区域边界,极易漏掉相邻区域的最近邻(Recall较低)。且当新增数据导致数据分布改变时,IVFFlat索引的性能会急剧下降,需要定期重建。 +* **适用场景**:仅在内存极度受限(如在边缘设备或极低配云主机上运行)时考虑。对于追求精准的医疗AI,应尽量避免使用 12。 + +### **3.3 距离度量算法** + +pgvector 支持多种度量方式,且可以在同一列上创建不同度量的索引: + +* **余弦相似度(Cosine Similarity \<=\>)**:最适合归一化的文本嵌入(如BioBERT),衡量向量的方向一致性。 +* **欧氏距离(L2 Distance \<-\>)**:适合未归一化的数据或空间坐标数据。 +* **内积(Inner Product \<\#\>)**:常用于推荐系统中的矩阵分解场景。 + +## --- + +**4\. 核心竞争力:PostgreSQL 独有的“必杀技”(回应问题 3)** + +用户问到:“PostgreSQL的插件pgvector,与PostgreSQL 有哪些特殊的技能,或者能力,是其他向量库所不具备的?” +这是一个非常关键的问题。pgvector的真正威力不在于它作为一个向量库有多快,而在于它依然是PostgreSQL。 + +### **4.1 真正的“混合检索”(Hybrid Search)能力** + +在医疗RAG系统中,纯向量检索往往存在致命缺陷——**“精确性丢失”**。 + +* *案例*:用户查询“\*\*依鲁替尼(Ibrutinib)\*\*的副作用”。 +* *纯向量检索的问题*:向量模型可能认为“泽布替尼(Zanubrutinib)”在语义上与“依鲁替尼”极度相似(都是BTK抑制剂),因此检索结果可能混杂了大量关于泽布替尼的文献。这在临床上是不可接受的噪音。 +* PostgreSQL的解法: + 利用PostgreSQL内置的全文检索(Full-Text Search, FTS)组件tsvector,结合pgvector,可以在一条SQL语句中同时执行: + 1. **语义检索**:找到关于“BTK抑制剂副作用”的相关文献(高召回)。 + 2. **关键词检索**:强制要求文档中必须包含“Ibrutinib”这个词(高精确)。 + 3. **重排序(Reranking)**:使用\*\*互惠排名融合(Reciprocal Rank Fusion, RRF)\*\*算法,将两者的评分融合。 + +**技术实现代码(SQL):** + +SQL + +WITH semantic\_search AS ( + SELECT id, RANK() OVER (ORDER BY embedding \<=\> query\_embedding) as rank + FROM medical\_docs + ORDER BY embedding \<=\> query\_embedding LIMIT 50 +), +keyword\_search AS ( + SELECT id, RANK() OVER (ORDER BY ts\_rank\_cd(to\_tsvector('english', content), plainto\_tsquery('Ibrutinib side effects'))) as rank + FROM medical\_docs + WHERE to\_tsvector('english', content) @@ plainto\_tsquery('Ibrutinib side effects') + LIMIT 50 +) +SELECT + COALESCE(s.id, k.id) as doc\_id, + COALESCE(s.rank, 0) \+ COALESCE(k.rank, 0) as combined\_score +FROM semantic\_search s +FULL OUTER JOIN keyword\_search k ON s.id \= k.id +ORDER BY combined\_score ASC +LIMIT 10; + +这种\*\*“原生SQL级融合”\*\*是Milvus或Pinecone无法做到的。后者通常需要你在应用层(Python代码)分别请求两个系统(Elasticsearch \+ Milvus),然后在内存中极其痛苦地合并结果,不仅增加了延迟,还引入了系统复杂性 14。 + +### **4.2 ACID 事务一致性(Transactional Consistency)** + +医疗数据容不得“最终一致性”。 + +* *场景*:某篇科研论文被撤稿(Retracted),或者某位患者撤回了隐私授权。 +* *专用向量库的痛点*:你需要在MySQL中删除记录,然后异步调用API去Pinecone中删除向量。如果中间网络抖动,Pinecone删除失败,系统就会出现“幽灵数据”——AI依然能检索到这篇已被撤稿的文章并据此生成建议,引发严重的医疗伦理事故。 +* *PostgreSQL的能力*: + SQL + BEGIN; + DELETE FROM medical\_docs WHERE id \= 1001; \-- 向量数据随行记录一同物理删除 + COMMIT; + + 在PostgreSQL中,向量只是表的一列。删除操作是**原子性(Atomic)的。一旦提交,任何查询(无论是SQL还是向量搜索)都绝不会再看到这条数据。这种强一致性**是医疗级系统的刚需 2。 + +### **4.3 复杂的元数据过滤(Pre-Filtering)** + +医疗查询往往伴随着极其复杂的筛选条件。 + +* *查询*:“查找**2020年以后**发表的、由**北京协和医院**作者撰写的、关于**肺结节**的**随机对照试验(RCT)**。” +* PostgreSQL的优势: + PostgreSQL拥有几十年历史的查询优化器(Query Planner)。它能智能地分析统计信息: + * 如果“2020年以后”的数据很少,它会先利用B-Tree索引筛选出这些记录,然后对剩下的几条数据进行暴力向量计算(速度极快)。 + * 如果筛选条件很宽泛,它会先走HNSW向量索引,再过滤属性。 + 这种\*\*基于成本的优化(Cost-Based Optimization)\*\*是其核心壁垒。专用向量库在处理复杂的布尔逻辑(AND/OR/NOT嵌套)和关系型Join(如关联作者表、医院表)时,性能往往大幅下降,甚至不支持 17。 + +## --- + +**5\. 局限性与不足分析(回应问题 4)** + +尽管pgvector在架构上优势明显,但在某些维度上,它确实不如专用向量数据库。我们需要客观地认清这些差距,以判断它们是否会成为贵公司的瓶颈。 + +### **5.1 规模天花板(The Scale Wall)** + +* **现象**:PostgreSQL是单机垂直扩展(Scale-up)架构。 +* **局限**:当向量数据量达到\*\*1亿(100 Million)\*\*级别以上时,单机内存(RAM)和磁盘I/O将成为瓶颈。虽然可以通过分区表(Partitioning)缓解,但在十亿级规模下,Milvus或Weaviate这种天生分布式、支持水平分片(Sharding)的系统会更有优势。 +* **医疗场景评估**:PubMed所有文献摘要加起来约为3500万篇。即使切分成块(Chunking),总量可能在2-3亿向量。如果贵公司的目标是索引全人类所有语种的医疗文献,PostgreSQL可能会吃力(需要引入Citus分布式插件或极高配置的服务器)。但如果仅针对特定领域(如肿瘤学、心血管)或中文医疗文献,数据量通常在百万至千万级,pgvector完全在舒适区 19。 + +### **5.2 资源争抢(Resource Contention)** + +* **现象**:向量搜索是计算密集型(CPU密集)和内存密集型任务。 +* **局限**:在同一个PostgreSQL实例中,构建HNSW索引或执行高并发向量查询会占用大量CPU资源。如果数据库同时还承载着用户登录、订单支付等OLTP业务,可能会导致由于CPU飙升而拖慢常规业务的响应速度。 +* **解决方案**:架构分离。 + * **主库(Primary)**:负责写入和常规业务。 + * **只读副本(Read Replica)**:专门用于承载向量搜索流量。阿里云和腾讯云的RDS都支持创建只读实例,这是标准的规避方案。 + +### **5.3 缺乏GPU加速** + +* **局限**:目前的pgvector主要依赖CPU指令集(如AVX-512)进行加速。相比之下,Milvus和FAISS对GPU(NVIDIA CUDA)有深度优化,在大批量(Batch)查询或超大规模索引构建时,GPU的速度是CPU的几十倍。 +* **影响**:对于实时RAG系统(通常是单条查询),CPU的延迟(毫秒级)已经足够低,GPU的吞吐优势体现不明显。但如果需要离线大规模聚类分析,pgvector会慢很多 20。 + +## --- + +**6\. 医疗科研领域的RAG应用实战(回应问题 5 & 6)** + +### **6.1 典型应用场景** + +1. **循证医学问答(Evidence-Based QA)**: + * 医生提问:“针对EGFR突变的非小细胞肺癌,三代TKI耐药后的后续治疗方案有哪些?” + * 系统利用pgvector检索最新的临床指南和Case Report,结合RAG生成包含引用来源的建议。 +2. **临床试验匹配(Clinical Trial Matching)**: + * 将患者的病历(非结构化文本)转化为向量。 + * 利用向量相似度搜索,在数据库中匹配入排标准(Inclusion/Exclusion Criteria)相似的临床试验项目。 +3. **药物重定位(Drug Repurposing)**: + * 利用二进制向量(bit类型)存储药物分子指纹。 + * 通过杰卡德距离计算,发现老药与新靶点在分子结构上的潜在关联 6。 + +### **6.2 知识库容量评估** + +用户问:“能够承载多大容量?几千篇还是几万篇?” + +* **结论**:**“几千、几万篇”对PostgreSQL来说属于微量数据**。 +* **数据推算**: + * 假设一篇医疗文献平均5,000字,切分为10个Chunk。 + * **5万篇文献** \= 50万个向量。 + * **50万个768维向量**(BioBERT)的原始数据大小约为 **1.5 GB**。 + * 加上HNSW索引,总内存占用可能在 **2-3 GB** 左右。 +* **性能预期**:在任何一台现代笔记本电脑或入门级云服务器(2核 4G)上,检索50万向量的耗时都在 **5毫秒(ms)** 以内。 +* **上限**:pgvector 在单机(如阿里云 32GB 内存实例)上,可以流畅处理 **1000万至2000万** 个向量(对应约100万-200万篇全长文献)。因此,贵公司的需求完全在覆盖范围内,且留有百倍的增长空间 10。 + +### **6.3 医疗文献处理的最佳范式** + +在医疗领域,直接将整段文本向量化往往效果不佳。推荐采用\*\*分层索引(Hierarchical Indexing)\*\*策略: + +| 处理步骤 | 方法 | PostgreSQL实现 | +| :---- | :---- | :---- | +| **1\. 图表处理** | 医疗文献包含大量图表(Table 1, Figure 2)。直接丢弃会丢失关键数据。 | 将表格转化为Markdown或JSON格式,利用LLM生成“表格摘要文本”。对**摘要**进行Embedding存入vector列,原表格存入jsonb列。 | +| **2\. 切片策略** | 避免机械切分(如每500字一切)。采用语义切分。 | 建立父子文档结构。父文档(Parent)是整章“Result”,子文档(Child)是具体发现。检索时匹配子文档向量,但在Prompt中提供父文档全文上下文。PostgreSQL的JOIN查询天然支持这种操作。 | +| **3\. 引用溯源** | 医疗回答必须有据可查。 | 建立citations表。RAG生成答案后,利用SQL关联查询出对应的文献DOI、发表年份和期刊影响因子,作为可信度背书。 | + +## --- + +**7\. 实施指南与生态资源(回应问题 7)** + +### **7.1 开发教程与易用性** + +pgvector 的学习曲线极低,特别是对于熟悉SQL的开发者。 + +**极简开发流程:** + +1. **启用插件**: + SQL + CREATE EXTENSION vector; + +2. **创建表**: + SQL + CREATE TABLE papers ( + id bigserial PRIMARY KEY, + content text, + embedding vector(768) \-- BioBERT dimensions + ); + +3. **插入数据**: + SQL + INSERT INTO papers (content, embedding) VALUES ('Aspirin inhibits...', '\[0.1, \-0.2,...\]'); + +4. **查询(最近邻搜索)**: + SQL + SELECT content FROM papers ORDER BY embedding \<=\> '\[0.1, \-0.2,...\]' LIMIT 5; + +**开发框架支持**: + +* **LangChain**:Python库langchain-postgres提供了开箱即用的PGVector类,完全封装了底层SQL 21。 +* **LlamaIndex**:原生支持Postgres向量存储,并能自动将LlamaIndex的高级过滤器转换为SQL WHERE子句 23。 + +### **7.2 中国云服务商支持情况** + +由于贵公司在中国,云服务商的兼容性至关重要: + +* **阿里云(Aliyun RDS)**: + * PostgreSQL 14及以上版本全面支持pgvector。 + * **注意**:需在控制台确认插件版本。建议升级到支持HNSW的0.5.0以上版本。最新的0.7.0版本(支持稀疏向量)可能需要最新的内核小版本(20240530以后),请在购买前查看RDS发布说明 24。 +* **腾讯云(TencentDB)**: + * PostgreSQL 13/14/15 均支持pgvector。腾讯云对内核进行了深度优化,支持向量化指令加速。 + * 最新版本已支持pgvector 0.7.0,且支持在控制台管理插件升级 26。 +* **华为云(GaussDB / RDS)**: + * 华为云RDS for PostgreSQL 12+ 支持该插件。 + * GaussDB(分布式版)也有自己的向量检索引擎,但标准RDS PostgreSQL更适合初创期的轻量级部署 28。 + +## --- + +**8\. 总结与建议** + +经过全面评估,我们认为**PostgreSQL \+ pgvector 是贵公司构建医疗AI知识库的首选方案**。 + +**核心理由总结**: + +1. **架构极简**:无需维护第二套数据库,降低了创业初期的运维与人力成本。 +2. **能力全面**:独有的混合检索(Hybrid Search)能力完美解决医疗领域对“精准实体匹配”的刚需。 +3. **完全合规**:数据完全私有化,依托成熟的国产云数据库底座,规避数据出境风险。 +4. **容量充足**:轻松应对千万级文献,足以支撑公司未来3-5年的业务增长。 + +**落地建议**: + +* **模型选择**:务必使用针对生物医学微调的**BioBERT**或**PubMedBERT**作为Embedding模型,而非通用的OpenAI模型,以提升专业术语的理解能力。 +* **索引策略**:生产环境务必创建**HNSW索引**,不要使用默认的IVFFlat。 +* **硬件配置**:向量索引常驻内存。建议数据库服务器内存(RAM)配置充足(例如,每100万个768维向量预留约2-3GB内存)。 + +此方案不仅是一个技术上的“可行解”,更是一个商业上的“最优解”,它以最低的复杂度提供了最符合医疗严肃场景需求的核心能力。 + +--- + +*(以下为报告详细正文,涵盖上述章节的深度展开,包含具体SQL代码、性能调优参数及详细的架构设计图解描述。)* + +# **详细研究报告:基于PostgreSQL与pgvector构建医疗科研AI系统的深度评估** + +## **1\. 引言** + +随着大语言模型(LLM)在医疗领域的应用深化,\*\*检索增强生成(RAG)\*\*已成为解决模型幻觉、赋予模型实时专业知识的关键架构。对于一家中国的医疗科研创业公司而言,选择何种技术栈来构建底层的“知识库”与“向量检索引擎”,直接决定了产品的检索质量、响应速度以及后续数年的运维成本。 + +本报告针对用户提出的核心疑问,对利用现有的 **PostgreSQL** 数据库集成 **pgvector** 插件这一技术路线进行了全方位的可行性研究。报告将结合医疗行业的特殊需求(如高精度、多模态数据、数据隐私)及中国本土的云基础设施环境,提供客观、详实的技术分析。 + +## **2\. 技术路线评估:为什么选择 pgvector?(Reliability & Architectural Fit)** + +### **2.1 从“专用”到“通用”的范式转移** + +在RAG技术出现的早期(2022年左右),由于传统关系型数据库对向量支持的缺失,开发者往往被迫采用“多库架构”:使用MySQL/PostgreSQL存储业务数据,同时引入Milvus、Pinecone或Weaviate存储向量数据。 + +然而,对于医疗科研系统,这种分离架构带来了巨大的痛点: + +1. **数据一致性风险(Data Consistency Risk)**:医疗数据要求极高的严谨性。如果一篇临床指南被修订了,PostgreSQL中的文本更新了,但向量库中的索引未能毫秒级同步,AI就可能引用旧版指南给出错误的医疗建议。这种“同步延迟”在医疗领域是不可接受的风险。 +2. **元数据过滤的复杂性(Metadata Filtering Complexity)**:科研人员常需要进行复杂的组合查询,例如“查找2023年IF\>10的期刊中关于PD-1抑制剂的论文”。在分离架构中,这需要在两个数据库间传输大量ID进行“交集”运算,效率极低。 + +pgvector 的出现解决了这一核心矛盾。 +作为PostgreSQL的一个扩展,pgvector 让向量(Vector)成为数据库中的一种原生数据类型。这意味着: + +* **单一数据源(Single Source of Truth)**:文本、元数据、向量存储在同一张表中。 +* **ACID 事务保障**:更新文献和更新向量在同一个事务中完成,要么全成功,要么全失败,彻底消除了数据不一致的隐患。 +* **运维极简**:初创团队无需学习和维护一套全新的分布式向量数据库系统,只需维护现有的PostgreSQL即可。备份、恢复、高可用(HA)方案完全复用。 + +### **2.2 中国医疗环境下的合规性优势** + +在中国,医疗数据属于强监管范畴(如《数据安全法》)。使用SaaS类的向量数据库(如Pinecone)通常涉及数据传输到公有云API,这在合规上存在灰色地带。 +相比之下,PostgreSQL可以完全私有化部署(Self-hosted)。无论是在医院内网的物理机上,还是在阿里云/腾讯云的私有网络(VPC)中,企业都能对数据拥有100%的掌控权。各大国产数据库(如华为GaussDB、腾讯TDSQL)大多基于PostgreSQL生态,这也为未来的信创迁移留出了空间。 + +## --- + +**3\. 功能详解:pgvector 能做什么?(Capabilities & Features)** + +pgvector 的功能迭代极快,特别是0.5.0版本之后的HNSW索引支持,使其真正具备了生产级能力。 + +### **3.1 向量数据类型与存储** + +在PostgreSQL中,启用插件后,即可使用 vector 类型: + +SQL + +CREATE EXTENSION vector; +CREATE TABLE documents ( + id bigserial PRIMARY KEY, + content text, + embedding vector(768) \-- 对应BioBERT模型的维度 +); + +#### **3.1.1 维度支持** + +pgvector 支持高达16,000维的向量。对于医疗领域常用的Embedding模型: + +* **BioBERT / PubMedBERT**:输出768维向量。 +* **BGE-M3 (BAAI)**:输出1024维向量。 +* OpenAI text-embedding-3-large:输出3072维向量。 + 以上模型均能被完美支持。 + +#### **3.1.2 半精度向量(Halfvec)—— 降本增效利器** + +在pgvector 0.7.0版本中,引入了 halfvec 类型。它将维度的存储精度从32位浮点数降为16位。 + +* **原理**:深度学习模型的输出往往不需要极高的浮点精度来维持检索排序。 +* **收益**:存储空间减少50%,内存占用减少50%。 +* **实测**:对于千万级的文献库,这意味着原本需要128GB内存的服务器,现在只需64GB即可全内存加载索引,大幅节省了云服务器成本 5。 + +#### **3.1.3 稀疏向量(Sparsevec)—— 专治“关键词遗漏”** + +传统的稠密向量(Dense Vector)是将一段文本压缩成一个实数数组,这会导致信息压缩损失。例如,一篇长论文中只出现了一次“TP53基因突变”,在稠密向量中,这个特征可能被淹没。 +sparsevec 允许存储稀疏向量(如SPLADE模型的输出)。它仅记录非零维度的值,能够精准捕捉稀缺关键词。这对于医疗科研中的精准术语检索价值巨大 7。 + +### **3.2 索引算法:性能的核心** + +#### **3.2.1 HNSW(推荐)** + +pgvector 实现了完整的HNSW索引。 + +* **性能**:查询时间复杂度为 $O(\\log N)$。在百万级数据下,单次查询通常在2ms-10ms之间。 +* **参数可调**: + * m:节点最大连接数。医疗场景建议设为16-32,以保证高召回。 + * ef\_construction:构建时的搜索深度。设为64-128可提升索引质量,虽然构建变慢,但查询更准 9。 +* **构建速度**:支持并行构建(Parallel Build)。利用多核CPU,构建速度比早期版本提升了数倍。 + +#### **3.2.2 IVFFlat** + +这是早期的索引算法。除非您的服务器内存极小(例如只有2GB内存却要跑数百万数据),否则不建议使用。它的召回率不稳定,且维护成本高(需要定期Reindex)。 + +## --- + +**4\. 独家绝技:PostgreSQL \+ pgvector 的不可替代性(Unique Skills)** + +用户特别关心“有什么是别人做不到的”。除了前文提到的ACID事务,最大的杀手锏是**混合检索(Hybrid Search)**。 + +### **4.1 医疗场景下的“语义”与“符号”之争** + +在医疗RAG中,我们经常面临两难: + +* \*\*语义检索(Vector)\*\*擅长理解概念。例如搜“免疫检查点抑制剂”,它能找到“PD-1”、“CTLA-4”相关的文章。 +* \*\*符号检索(Keyword)\*\*擅长精确匹配。例如搜“NCT04826348”(临床试验号),或者搜“5mg/kg”,这需要字符级的精确匹配。 + +如果只用向量库,很难搜到具体的临床试验号,因为向量模型无法精确编码一串随机数字。 +如果只用全文检索,搜“癌症治疗”可能会漏掉“肿瘤疗法”的文章。 + +### **4.2 完美的结合:pgvector \+ tsvector** + +PostgreSQL 是世界上最强大的开源关系型数据库,它内置了企业级的全文检索引擎 tsvector(基于BM25算法)。 +利用 pgvector,我们可以在数据库内部实现\*\*“语义+关键词”的双路召回\*\*,并使用\*\*RRF(互惠排名融合)\*\*算法合并结果。 +实战案例: +假设我们要找“阿司匹林在心血管疾病中的应用,且必须提及出血风险”。 + +SQL + +WITH vector\_search AS ( + \-- 路径1:语义检索,找前50个语义最相关的 + SELECT id, RANK() OVER (ORDER BY embedding \<=\> query\_embedding) as rank + FROM papers + ORDER BY embedding \<=\> query\_embedding LIMIT 50 +), +keyword\_search AS ( + \-- 路径2:关键词检索,找前50个包含'bleeding'和'risk'的 + SELECT id, RANK() OVER (ORDER BY ts\_rank\_cd(to\_tsvector('english', content), plainto\_tsquery('bleeding risk'))) as rank + FROM papers + WHERE to\_tsvector('english', content) @@ plainto\_tsquery('bleeding risk') + LIMIT 50 +) +\-- 融合:计算RRF得分 +SELECT + COALESCE(v.id, k.id) as id, + (1.0 / (60 \+ COALESCE(v.rank, 0))) \+ (1.0 / (60 \+ COALESCE(k.rank, 0))) as rrf\_score +FROM vector\_search v +FULL OUTER JOIN keyword\_search k ON v.id \= k.id +ORDER BY rrf\_score DESC +LIMIT 10; + +这一能力是**PostgreSQL独有**的。它不需要外部的Elasticsearch,不需要复杂的ETL,不需要在应用层写代码合并列表。它极其高效、稳定,是构建高精度医疗RAG的最佳范式 14。 + +## --- + +**5\. 局限性与不足:理性看待差距(Limitations)** + +虽然pgvector对于99%的场景都足够好,但在某些极端场景下,它确实不如Milvus或Pinecone。 + +### **5.1 亿级以上规模的挑战** + +* **索引构建时间**:当数据量达到1亿(100M)以上时,PostgreSQL构建HNSW索引可能会非常慢(数小时甚至数天),因为它是基于磁盘的数据库,且主要依赖CPU计算。而Milvus支持GPU加速索引构建,速度快10倍以上 20。 +* **内存瓶颈**:HNSW索引非常吃内存。虽然PostgreSQL支持将索引存放在磁盘上(利用OS Page Cache),但如果内存不足以容纳大部分索引层,查询会出现大量磁盘IO,导致延迟从2ms飙升到200ms。专用向量库通常有更复杂的内存管理机制(如Mmap优化)来缓解这个问题。 + +### **5.2 资源隔离问题** + +* PostgreSQL是单进程多线程(或多进程)模型。如果一个巨大的向量查询占满了CPU,可能会影响到数据库中其他简单的SQL查询(如用户登录)。 +* **对策**:在生产环境中,强烈建议配置**读写分离**。主库处理写入和元数据更新,配置一个只读节点(Read Replica)专门处理向量查询请求。阿里云和腾讯云的RDS都能一键实现这个架构。 + +### **5.3 高级量化技术缺失** + +* 目前pgvector支持halfvec(FP16)和简单的二进制量化。但业界领先的向量库(如Qdrant)支持积量化(Product Quantization, PQ),能将向量压缩到原始大小的1/64。如果您的数据量极其庞大且预算极其有限,pgvector的存储成本会显得较高。 + +## --- + +**6\. 容量与性能:几千还是几万?(Capacity Analysis)** + +用户问:“能够承载多大容量的知识库?几千篇文献,还是几万篇文献?” + +### **6.1 容量评估:绰绰有余** + +对于pgvector而言,“几万篇文献”属于微型数据集。 +让我们做一下量化计算: + +* **场景**:假设您有**10万篇**医疗文献。 +* **切片(Chunking)**:每篇文献平均切分为20个段落(Chunks)。 +* **总量**:$100,000 \\times 20 \= 2,000,000$ (200万)个向量。 +* **存储需求**: + * BioBERT向量(768维)大小:$2,000,000 \\times 768 \\times 4 \\text{ bytes} \\approx 6 \\text{ GB}$。 + * HNSW索引大小:约为数据大小的50%-80%,即约 **4 GB**。 + * **总内存需求**:约 **10 GB**。 + +结论:一台标准的 16GB内存 的云服务器(如阿里云ECS g7型)就足以将这10万篇文献的索引全部加载进内存,实现毫秒级查询。 +PostgreSQL的舒适区在 1000万至5000万 向量之间。因此,贵公司的业务即使增长100倍,这套架构依然撑得住。 + +### **6.2 性能实测数据** + +根据由于Google Cloud和AWS进行的基准测试(基于10): + +* **数据集**:100万条 768维向量。 +* **索引**:HNSW (m=16, ef=64)。 +* **查询延迟(Latency)**:\< 5ms (在t3.medium这种低配机器上)。 +* **每秒查询数(QPS)**:单机可达数千QPS。对于医疗科研系统(通常是医生或研究员使用,并发不高),这性能完全溢出。 + +## --- + +**7\. 医疗科研领域的特殊应用与最佳范式(Medical Best Practices)** + +### **7.1 嵌入模型的选择** + +不要直接使用OpenAI的通用模型。在医疗领域,专有模型效果更好。 + +* **推荐**: + * 英文文献:**BioBERT** 或 **PubMedBERT**。 + * 中文文献:**Text2Vec-Base-Chinese-Paraphrase** 或针对中医/西医微调过的BERT模型。 +* **注意**:pgvector 只是存储容器,检索质量的70%取决于Embedding模型本身的质量。 + +### **7.2 表格与图表的处理** + +科研文献中的精华往往在图表(Table/Figure)里。 + +* **错误做法**:直接把表格转成文本字符串切片。这会丢失行列对应关系。 +* **最佳范式**: + 1. 使用OCR或PDF解析工具(如Unstructured.io)提取表格。 + 2. 将表格转化为Markdown格式或JSON。 + 3. 利用大模型(如GPT-4o或Qwen-Max)生成一段\*\*“表格摘要”\*\*(例如:“表1显示,实验组的生存期中位数为12个月,显著高于对照组的8个月...”)。 + 4. 对这段**摘要**进行Embedding,存入vector列。 + 5. 将原始表格Markdown存入PostgreSQL的jsonb列。 + 6. 检索时,匹配摘要,但将原始表格Markdown作为上下文喂给LLM 30。 + +### **7.3 引文溯源(Citations)** + +医疗RAG必须解决“幻觉”问题。 + +* **设计**:在documents表中增加metadata列(JSONB类型),存储DOI、作者、期刊名、发表日期。 +* **查询**:在RAG生成回答时,利用PostgreSQL查出的元数据,强制LLM在回答中标注引用来源(例如:“根据2023年JAMA的研究...”)。 + +## --- + +**8\. 实施指南与云服务支持(Implementation Guide)** + +### **8.1 云平台支持详情** + +鉴于贵公司在中国,以下是三大云厂商的具体支持情况: + +* **阿里云(Aliyun RDS PostgreSQL)**: + * **版本**:PostgreSQL 14/15/16 均支持。 + * **操作**:在RDS控制台“插件管理”页面,点击安装vector插件即可。 + * **注意**:确保内核小版本是最新的,以获取HNSW索引支持。 +* **腾讯云(TencentDB for PostgreSQL)**: + * **版本**:全面支持。腾讯云在内核层面做了向量指令加速。 + * **教程**:腾讯云官方文档中有详细的“使用pgvector构建向量检索系统”的教程 26。 +* **华为云(RDS for PostgreSQL)**: + * 支持pgvector。华为云通常用于政企项目,如果贵公司服务于公立医院,华为云的合规属性会有加分 28。 + +### **8.2 开发教程资源** + +* **教程丰富度**:pgvector 是目前GitHub上Star增长最快的PostgreSQL插件之一,社区资源极其丰富。 +* **推荐库**: + * **Python**: psycopg3 或 SQLAlchemy(配合pgvector-python库)。 + * **AI框架**: **LangChain** (langchain\_postgres) 和 **LlamaIndex** 都内置了对pgvector的完美支持。你甚至不需要写SQL,只需要几行Python代码即可完成知识库的构建和检索 21。 + +**LangChain 极简示例:** + +Python + +from langchain\_postgres import PGVector +from langchain\_huggingface import HuggingFaceEmbeddings + +\# 1\. 定义连接字符串 (阿里云RDS地址) +connection \= "postgresql+psycopg://user:pass@rm-xxx.pg.rds.aliyuncs.com:5432/med\_db" + +\# 2\. 初始化向量库 (自动使用pgvector) +vector\_store \= PGVector( + embeddings=HuggingFaceEmbeddings(model\_name="shibing624/text2vec-base-chinese"), + collection\_name="clinical\_guidelines", + connection=connection, + use\_jsonb=True, +) + +\# 3\. 添加文档 +vector\_store.add\_documents(documents) + +\# 4\. 检索 (RAG) +results \= vector\_store.similarity\_search("高血压的首选药物", k=5) + +## **9\. 结论** + +综上所述,对于贵公司——一家专注于医疗科研的AI创业公司而言,**集成PostgreSQL的pgvector插件不仅是“靠谱”的,而且是目前阶段最具性价比、最稳健的技术选型。** + +它利用PostgreSQL强大的生态,解决了医疗领域最棘手的**混合检索**和**数据一致性**问题,同时完全满足从数千篇到数千万篇文献的扩展需求。相比于盲目引入复杂的专用向量数据库,基于PostgreSQL构建“全栈式”医疗知识库,将让贵公司的技术架构更加简洁、高效且合规。 + +#### **引用的著作** + +1. Load vector embeddings up to 67x faster with pgvector and Amazon Aurora \- AWS, 访问时间为 一月 14, 2026, [https://aws.amazon.com/blogs/database/load-vector-embeddings-up-to-67x-faster-with-pgvector-and-amazon-aurora/](https://aws.amazon.com/blogs/database/load-vector-embeddings-up-to-67x-faster-with-pgvector-and-amazon-aurora/) +2. Ditch the Extra Database: Simplify Your AI Stack with Managed PostgreSQL and pgvector, 访问时间为 一月 14, 2026, [https://render.com/articles/simplify-ai-stack-managed-postgresql-pgvector](https://render.com/articles/simplify-ai-stack-managed-postgresql-pgvector) +3. Postgres Vector Search with pgvector: Benchmarks, Costs, and Reality Check \- Medium, 访问时间为 一月 14, 2026, [https://medium.com/@DataCraft-Innovations/postgres-vector-search-with-pgvector-benchmarks-costs-and-reality-check-f839a4d2b66f](https://medium.com/@DataCraft-Innovations/postgres-vector-search-with-pgvector-benchmarks-costs-and-reality-check-f839a4d2b66f) +4. Overfitter/biobert\_embedding: Token and Sentence level embeddings from BioBERT model, 访问时间为 一月 14, 2026, [https://github.com/Overfitter/biobert\_embedding](https://github.com/Overfitter/biobert_embedding) +5. What's new in pgvector v0.7.0 \- Supabase, 访问时间为 一月 14, 2026, [https://supabase.com/blog/pgvector-0-7-0](https://supabase.com/blog/pgvector-0-7-0) +6. vector 0.7.0: Open-source vector similarity search for Postgres / PostgreSQL Extension Network \- PGXN, 访问时间为 一月 14, 2026, [https://pgxn.org/dist/vector/0.7.0/](https://pgxn.org/dist/vector/0.7.0/) +7. The pgvector extension \- Neon Docs, 访问时间为 一月 14, 2026, [https://neon.com/docs/extensions/pgvector](https://neon.com/docs/extensions/pgvector) +8. pgvector 0.7.0 Released\! \- PostgreSQL, 访问时间为 一月 14, 2026, [https://www.postgresql.org/about/news/pgvector-070-released-2852/](https://www.postgresql.org/about/news/pgvector-070-released-2852/) +9. An early look at HNSW performance with pgvector | Jonathan Katz, 访问时间为 一月 14, 2026, [https://jkatz05.com/post/postgres/pgvector-hnsw-performance/](https://jkatz05.com/post/postgres/pgvector-hnsw-performance/) +10. Faster similarity search performance with pgvector indexes | Google Cloud Blog, 访问时间为 一月 14, 2026, [https://cloud.google.com/blog/products/databases/faster-similarity-search-performance-with-pgvector-indexes](https://cloud.google.com/blog/products/databases/faster-similarity-search-performance-with-pgvector-indexes) +11. How to calculate amount of RAM required for serving X N-dimensional vectors with pgvector (HNSW)? \- Stack Overflow, 访问时间为 一月 14, 2026, [https://stackoverflow.com/questions/77401874/how-to-calculate-amount-of-ram-required-for-serving-x-n-dimensional-vectors-with](https://stackoverflow.com/questions/77401874/how-to-calculate-amount-of-ram-required-for-serving-x-n-dimensional-vectors-with) +12. pgvector/pgvector: Open-source vector similarity search for Postgres \- GitHub, 访问时间为 一月 14, 2026, [https://github.com/pgvector/pgvector](https://github.com/pgvector/pgvector) +13. Optimize generative AI applications with pgvector indexing: A deep dive into IVFFlat and HNSW techniques | AWS Database Blog, 访问时间为 一月 14, 2026, [https://aws.amazon.com/blogs/database/optimize-generative-ai-applications-with-pgvector-indexing-a-deep-dive-into-ivfflat-and-hnsw-techniques/](https://aws.amazon.com/blogs/database/optimize-generative-ai-applications-with-pgvector-indexing-a-deep-dive-into-ivfflat-and-hnsw-techniques/) +14. Hybrid Search in PostgreSQL: The Missing Manual | ParadeDB, 访问时间为 一月 14, 2026, [https://www.paradedb.com/blog/hybrid-search-in-postgresql-the-missing-manual](https://www.paradedb.com/blog/hybrid-search-in-postgresql-the-missing-manual) +15. Hybrid search with PostgreSQL and pgvector \- Jonathan Katz, 访问时间为 一月 14, 2026, [https://jkatz05.com/post/postgres/hybrid-search-postgres-pgvector/](https://jkatz05.com/post/postgres/hybrid-search-postgres-pgvector/) +16. Vector Databases vs. PostgreSQL with pg\_vector for RAG Setups \- DEV Community, 访问时间为 一月 14, 2026, [https://dev.to/simplr\_sh/vector-databases-vs-postgresql-with-pgvector-for-rag-setups-1lg2](https://dev.to/simplr_sh/vector-databases-vs-postgresql-with-pgvector-for-rag-setups-1lg2) +17. The Case Against pgvector | Alex Jacobs, 访问时间为 一月 14, 2026, [https://alex-jacobs.com/posts/the-case-against-pgvector/](https://alex-jacobs.com/posts/the-case-against-pgvector/) +18. Supercharging vector search performance and relevance with pgvector 0.8.0 on Amazon Aurora PostgreSQL | AWS Database Blog, 访问时间为 一月 14, 2026, [https://aws.amazon.com/blogs/database/supercharging-vector-search-performance-and-relevance-with-pgvector-0-8-0-on-amazon-aurora-postgresql/](https://aws.amazon.com/blogs/database/supercharging-vector-search-performance-and-relevance-with-pgvector-0-8-0-on-amazon-aurora-postgresql/) +19. 访问时间为 一月 14, 2026, [https://www.instaclustr.com/education/vector-database/pgvector-key-features-tutorial-and-pros-and-cons-2026-guide/\#:\~:text=pgvector%20inherits%20PostgreSQL's%20scalability%20limits,strategies%20or%20external%20vector%20systems.](https://www.instaclustr.com/education/vector-database/pgvector-key-features-tutorial-and-pros-and-cons-2026-guide/#:~:text=pgvector%20inherits%20PostgreSQL's%20scalability%20limits,strategies%20or%20external%20vector%20systems.) +20. Beyond PGVector: When Your Vector Database Needs a Formula 1 Upgrade \- Zilliz blog, 访问时间为 一月 14, 2026, [https://zilliz.com/blog/beyond-pgvector-when-your-vectordb-need-a-formula-one-upgrade](https://zilliz.com/blog/beyond-pgvector-when-your-vectordb-need-a-formula-one-upgrade) +21. PGVector \- Docs by LangChain, 访问时间为 一月 14, 2026, [https://python.langchain.com/docs/integrations/vectorstores/pgvector/](https://python.langchain.com/docs/integrations/vectorstores/pgvector/) +22. PGVectorStore \- Docs by LangChain, 访问时间为 一月 14, 2026, [https://docs.langchain.com/oss/javascript/integrations/vectorstores/pgvector](https://docs.langchain.com/oss/javascript/integrations/vectorstores/pgvector) +23. Postgres Vector Store | LlamaIndex Python Documentation, 访问时间为 一月 14, 2026, [https://developers.llamaindex.ai/python/examples/vector\_stores/postgres/](https://developers.llamaindex.ai/python/examples/vector_stores/postgres/) +24. How do I use the pgvector extension to perform vector similarity searches? \- ApsaraDB RDS \- Alibaba Cloud Documentation Center, 访问时间为 一月 14, 2026, [https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/pgvector-use-guide](https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/pgvector-use-guide) +25. ApsaraDB RDS:AliPG minor engine version release notes (PostgreSQL 14–18) \- Alibaba Cloud, 访问时间为 一月 14, 2026, [https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/release-notes-for-alipg](https://www.alibabacloud.com/help/en/rds/apsaradb-rds-for-postgresql/release-notes-for-alipg) +26. Overview \- Tencent Cloud, 访问时间为 一月 14, 2026, [https://www.tencentcloud.com/document/product/409/47734](https://www.tencentcloud.com/document/product/409/47734) +27. Kernel Version Release Notes \- Tencent Cloud, 访问时间为 一月 14, 2026, [https://www.tencentcloud.com/document/product/409/44365](https://www.tencentcloud.com/document/product/409/44365) +28. pgvector \- Cloud Service Help Center \- Huawei, 访问时间为 一月 14, 2026, [https://doc.hcs.huawei.com/usermanual/rds/rds\_09\_0062.html](https://doc.hcs.huawei.com/usermanual/rds/rds_09_0062.html) +29. pgvector\_Extension Management\_User Guide\_Relational Database Service\_RDS for PostgreSQL-Huawei Cloud, 访问时间为 一月 14, 2026, [https://support.huaweicloud.com/intl/en-us/usermanual-rds-pg/rds\_09\_0062.html](https://support.huaweicloud.com/intl/en-us/usermanual-rds-pg/rds_09_0062.html) +30. Mastering RAG: Precision techniques for table-heavy documents \- Kx Systems, 访问时间为 一月 14, 2026, [https://kx.com/blog/mastering-rag-precision-techniques-for-table-heavy-documents/](https://kx.com/blog/mastering-rag-precision-techniques-for-table-heavy-documents/) +31. Knowledge Table — Multi-Document RAG (Extraction & Memory) | by Chia Jeng Yang, 访问时间为 一月 14, 2026, [https://medium.com/enterprise-rag/knowledge-table-multi-document-rag-extraction-memory-ec08450e858f](https://medium.com/enterprise-rag/knowledge-table-multi-document-rag-extraction-memory-ec08450e858f) +32. Accelerate HNSW indexing and searching with pgvector on Amazon Aurora PostgreSQL-compatible edition and Amazon RDS for PostgreSQL | AWS Database Blog, 访问时间为 一月 14, 2026, [https://aws.amazon.com/blogs/database/accelerate-hnsw-indexing-and-searching-with-pgvector-on-amazon-aurora-postgresql-compatible-edition-and-amazon-rds-for-postgresql/](https://aws.amazon.com/blogs/database/accelerate-hnsw-indexing-and-searching-with-pgvector-on-amazon-aurora-postgresql-compatible-edition-and-amazon-rds-for-postgresql/) \ No newline at end of file diff --git a/docs/03-业务模块/PKB-个人知识库/04-开发计划/01-Dify替换为pgvector开发计划.md b/docs/03-业务模块/PKB-个人知识库/04-开发计划/01-Dify替换为pgvector开发计划.md new file mode 100644 index 00000000..59e27595 --- /dev/null +++ b/docs/03-业务模块/PKB-个人知识库/04-开发计划/01-Dify替换为pgvector开发计划.md @@ -0,0 +1,672 @@ +# PKB 模块:Dify 替换为 pgvector 开发计划 + +> **文档版本:** v1.0 +> **创建日期:** 2026-01-19 +> **预计工期:** 2 周(10个工作日) +> **前置条件:** ✅ pgvector 0.8.1 已安装 +> **目标:** 用 PostgreSQL + pgvector 原生 RAG 替代 Dify,实现 R-C-R-G 混合检索架构 + +--- + +## 📊 整体难度评估 + +### 总体评估:⭐⭐⭐ 中等难度 + +| 评估维度 | 难度 | 说明 | +|----------|------|------| +| **数据库设计** | ⭐⭐ 低 | Prisma schema 直接写,pgvector 已就绪 | +| **Embedding 服务** | ⭐⭐ 低 | 调用阿里云 API,简单封装 | +| **文档切片** | ⭐⭐ 低 | 成熟方案,RecursiveCharacterTextSplitter | +| **全要素提取** | ⭐⭐⭐ 中 | 需要调优 Prompt,处理 JSON 异常 | +| **向量检索** | ⭐⭐⭐ 中 | pgvector SQL 语法需要学习 | +| **混合检索(RRF)** | ⭐⭐⭐ 中 | 核心算法,需要调优 | +| **服务替换** | ⭐⭐⭐⭐ 中高 | 需要保持 API 兼容,测试覆盖 | +| **数据迁移** | ⭐⭐⭐ 中 | 现有文档需重新向量化 | + +**综合评估**:技术上完全可行,主要挑战在于**服务替换的平滑过渡**和**检索效果调优**。 + +--- + +## 🔥 核心挑战分析 + +### 挑战 1:混合检索效果调优 🔴 高风险 + +**问题描述**: +- 替换 Dify 后,检索效果可能下降 +- 需要调优向量检索 + 关键词检索的权重 +- RRF 参数(k 值)需要实验确定 + +**应对策略**: +- 准备测试数据集(100+ 查询) +- 建立效果评估指标(Recall@K, MRR) +- 先用小批量数据验证,再全量迁移 + +**预留时间**:2 天专门用于调优 + +--- + +### 挑战 2:全要素提取的准确性 🟡 中风险 + +**问题描述**: +- LLM 提取的 JSON 可能格式错误 +- PICO、用药方案等字段提取不完整 +- 不同类型文献(RCT/综述/病例)提取策略不同 + +**应对策略**: +- 三层 JSON 解析容错(直接解析 → 提取代码块 → LLM修复) +- 字段级校验(必填字段、类型校验) +- 分文献类型设计 Prompt + +**预留时间**:1 天用于 Prompt 调优 + +--- + +### 挑战 3:服务替换的兼容性 🟡 中风险 + +**问题描述**: +- 需要保持 API 接口不变(前端零修改) +- `searchKnowledgeBase()` 返回格式需兼容 +- 文档上传流程需要无缝切换 + +**应对策略**: +- 定义适配层,转换返回格式 +- 新旧服务并行运行,灰度切换 +- 充分测试所有使用场景 + +**预留时间**:1 天专门用于兼容性测试 + +--- + +### 挑战 4:向量数据的批量处理 🟢 低风险 + +**问题描述**: +- 批量 Embedding 调用需要控制并发 +- 阿里云 API 有 QPS 限制 +- 大文档切片后向量较多 + +**应对策略**: +- 使用 p-queue 控制并发(固定 3 并发) +- 批量 Embedding(每次最多 25 条) +- 增量处理,支持断点续传 + +--- + +## 📅 详细开发计划 + +### 总览时间线 + +``` +Week 1: 基础设施 + 核心服务开发 +├── Day 1: 数据库设计 + Prisma 迁移 +├── Day 2: Embedding 服务 + 切片服务 +├── Day 3: 全要素提取服务(Prompt 调优) +├── Day 4: 向量检索服务(pgvector SQL) +├── Day 5: 混合检索 + RRF 融合 + +Week 2: 服务替换 + 测试 + 迁移 +├── Day 6: 修改 knowledgeBaseService(检索替换) +├── Day 7: 修改 documentService(上传替换) +├── Day 8: 集成测试 + 效果调优 +├── Day 9: 数据迁移(现有文档向量化) +├── Day 10: 清理 + 文档 + 上线 +``` + +--- + +### Day 1:数据库设计 + Prisma 迁移 + +**目标**:创建向量存储的数据表 + +**任务清单**: +- [ ] 设计 `EkbDocument` 表(增强文档,含临床数据 JSONB 字段) +- [ ] 设计 `EkbChunk` 表(向量切片,含 pgvector 字段) +- [ ] 编写 Prisma schema +- [ ] 运行 `prisma migrate dev` +- [ ] 创建 HNSW 索引(手动 SQL) +- [ ] 验证向量插入和查询 + +**交付物**: +- `prisma/schema.prisma` 更新 +- `migrations/xxx_add_ekb_tables.sql` +- 索引创建脚本 + +**预计工时**:4-6 小时 + +**关键代码**: + +```prisma +// schema.prisma + +model EkbDocument { + id String @id @default(uuid()) + kbId String + userId String + + // 基础信息 + filename String + fileType String + fileSizeBytes BigInt + fileUrl String // 原始 PDF 的 OSS 地址 + extractedText String? @db.Text // 解析后的 Markdown/文本 + + // 临床数据(JSONB) + pico Json? + studyDesign Json? + regimen Json? + safety Json? + criteria Json? + endpoints Json? + + // 状态 + status String @default("pending") + errorMessage String? @db.Text + + chunks EkbChunk[] + knowledgeBase KnowledgeBase @relation(fields: [kbId], references: [id], onDelete: Cascade) + + createdAt DateTime @default(now()) + updatedAt DateTime @updatedAt + + @@index([kbId]) + @@index([status]) + @@schema("pkb_schema") +} + +model EkbChunk { + id String @id @default(uuid()) + documentId String + + content String @db.Text + pageNumber Int? + sectionType String? + + // pgvector 字段(需要手动创建) + embedding Unsupported("vector(1024)")? + + document EkbDocument @relation(fields: [documentId], references: [id], onDelete: Cascade) + + createdAt DateTime @default(now()) + + @@index([documentId]) + @@schema("pkb_schema") +} +``` + +**手动 SQL(创建索引)**: + +```sql +-- 创建 HNSW 索引 +CREATE INDEX IF NOT EXISTS ekb_chunk_embedding_idx +ON "pkb_schema"."EkbChunk" +USING hnsw (embedding vector_cosine_ops) +WITH (m = 16, ef_construction = 64); + +-- 创建全文检索索引 +CREATE INDEX IF NOT EXISTS ekb_chunk_content_idx +ON "pkb_schema"."EkbChunk" +USING gin (to_tsvector('simple', content)); + +-- 创建 JSONB GIN 索引(用于临床数据查询) +CREATE INDEX IF NOT EXISTS ekb_document_pico_idx +ON "pkb_schema"."EkbDocument" +USING gin (pico); + +CREATE INDEX IF NOT EXISTS ekb_document_safety_idx +ON "pkb_schema"."EkbDocument" +USING gin (safety); +``` + +--- + +### Day 2:Embedding 服务 + 切片服务 + +**目标**:实现文本向量化和文档切片 + +**任务清单**: +- [ ] 创建 `EmbeddingService.ts`(阿里云 text-embedding-v3) +- [ ] 创建 `ChunkService.ts`(RecursiveCharacterTextSplitter) +- [ ] 单元测试:Embedding API 调用 +- [ ] 单元测试:切片效果验证 +- [ ] 环境变量配置(DASHSCOPE_API_KEY) + +**交付物**: +- `backend/src/common/rag/EmbeddingService.ts` +- `backend/src/common/rag/ChunkService.ts` +- 单元测试文件 + +**预计工时**:4-6 小时 + +**关键代码**: + +```typescript +// EmbeddingService.ts +export class EmbeddingService { + private apiKey: string; + private baseUrl = 'https://dashscope.aliyuncs.com/api/v1/services/embeddings/text-embedding/text-embedding'; + + async embed(text: string): Promise { ... } + async embedBatch(texts: string[]): Promise { ... } + async embedQuery(query: string): Promise { ... } +} + +// ChunkService.ts +export class ChunkService { + splitDocument( + text: string, + options: { chunkSize: number; chunkOverlap: number } + ): Chunk[] { ... } + + detectSections(text: string): Section[] { ... } +} +``` + +--- + +### Day 3:全要素提取服务 + +**目标**:实现 PICO、用药方案等临床数据的 AI 提取 + +**任务清单**: +- [ ] 创建 `ClinicalExtractionService.ts` +- [ ] 设计提取 Prompt(参考 EKB 方案) +- [ ] 实现三层 JSON 解析容错 +- [ ] 测试不同类型文献(RCT、综述、病例) +- [ ] Prompt 调优(提高提取准确率) + +**交付物**: +- `backend/src/modules/pkb/services/ClinicalExtractionService.ts` +- `backend/prompts/clinical_extraction.txt` +- 测试用例 + +**预计工时**:6-8 小时(含 Prompt 调优) + +**关键 Prompt**: + +``` +你是一个医学数据专家。请阅读这篇文献,严格按照以下 JSON 格式提取关键信息。 +如果文中未提及,字段留空(null)。 + +提取字段: +1. pico: { "P": "患者人群", "I": "干预措施", "C": "对照", "O": "结局指标" } +2. studyDesign: { "design": "研究类型", "sampleSize": 数字, "blinding": "盲法" } +3. regimen: [{ "drug": "药物名", "dose": "剂量", "frequency": "频率" }] +4. safety: { "ae_all": ["不良反应列表"], "ae_grade34": ["严重不良反应"] } +5. criteria: { "inclusion": ["纳入标准"], "exclusion": ["排除标准"] } +6. endpoints: { "primary": ["主要终点"], "secondary": ["次要终点"] } + +输出必须是纯 JSON,不要有任何前言或后缀。 + +--- +文献内容: +{{fullText}} +``` + +--- + +### Day 4:向量检索服务(pgvector SQL) + +**目标**:实现基于 pgvector 的向量检索 + +**任务清单**: +- [ ] 创建 `VectorSearchService.ts` +- [ ] 实现向量检索(余弦相似度) +- [ ] 实现关键词检索(PostgreSQL FTS) +- [ ] 测试检索性能(1000+ 向量) +- [ ] 优化查询(索引使用验证) + +**交付物**: +- `backend/src/common/rag/VectorSearchService.ts` +- 性能测试报告 + +**预计工时**:6 小时 + +**关键 SQL**: + +```sql +-- 向量检索 +SELECT + c.id, + c.content, + d.filename, + 1 - (c.embedding <=> $1::vector) as score +FROM "pkb_schema"."EkbChunk" c +JOIN "pkb_schema"."EkbDocument" d ON c."documentId" = d.id +WHERE d."kbId" = $2 +ORDER BY c.embedding <=> $1::vector +LIMIT $3; + +-- 关键词检索 +SELECT + c.id, + c.content, + d.filename, + ts_rank_cd(to_tsvector('simple', c.content), plainto_tsquery('simple', $1)) as score +FROM "pkb_schema"."EkbChunk" c +JOIN "pkb_schema"."EkbDocument" d ON c."documentId" = d.id +WHERE d."kbId" = $2 + AND to_tsvector('simple', c.content) @@ plainto_tsquery('simple', $1) +ORDER BY score DESC +LIMIT $3; +``` + +--- + +### Day 5:混合检索 + RRF 融合 + +**目标**:实现 R-C-R-G 架构中的混合检索 + +**任务清单**: +- [ ] 实现 RRF(Reciprocal Rank Fusion)算法 +- [ ] 实现并发三路检索(向量 + 关键词 + SQL 筛选) +- [ ] 集成 Rerank API(可选,qwen-rerank) +- [ ] 效果评估(对比 Dify 检索) +- [ ] 参数调优(k 值、权重) + +**交付物**: +- RRF 融合模块 +- 效果评估报告 + +**预计工时**:6-8 小时 + +**RRF 算法**: + +```typescript +function rrfFusion( + vectorResults: Result[], + keywordResults: Result[], + k: number = 60 // RRF 常数,通常取 60 +): Result[] { + const scoreMap = new Map(); + + // 计算 RRF 分数 + vectorResults.forEach((r, idx) => { + const rrfScore = 1 / (k + idx + 1); + scoreMap.set(r.id, (scoreMap.get(r.id) || 0) + rrfScore); + }); + + keywordResults.forEach((r, idx) => { + const rrfScore = 1 / (k + idx + 1); + scoreMap.set(r.id, (scoreMap.get(r.id) || 0) + rrfScore); + }); + + // 排序返回 + return Array.from(scoreMap.entries()) + .sort((a, b) => b[1] - a[1]) + .map(([id, score]) => ({ id, score })); +} +``` + +--- + +### Day 6:修改 knowledgeBaseService(检索替换) + +**目标**:替换 Dify 检索为 pgvector 检索 + +**任务清单**: +- [ ] 修改 `searchKnowledgeBase()` 函数 +- [ ] 移除 `difyClient.retrieveKnowledge()` 调用 +- [ ] 使用 `vectorSearchService.hybridSearch()` +- [ ] 保持返回格式兼容(前端零修改) +- [ ] 单元测试 + +**交付物**: +- 更新后的 `knowledgeBaseService.ts` + +**预计工时**:4 小时 + +**关键修改**: + +```typescript +// 修改前 +const results = await difyClient.retrieveKnowledge( + knowledgeBase.difyDatasetId, + query, + { retrieval_model: { search_method: 'semantic_search', top_k: topK } } +); + +// 修改后 +const searchResults = await vectorSearchService.hybridSearch(kbId, query, topK); + +// 格式转换(保持兼容) +return { + query: { content: query }, + records: searchResults.map((r, idx) => ({ + segment_id: r.id, + document_id: r.documentId, + document_name: r.documentName, + position: idx + 1, + score: r.score, + content: r.content, + })), +}; +``` + +--- + +### Day 7:修改 documentService(上传替换) + +**目标**:替换 Dify 上传流程为本地向量化流程 + +**任务清单**: +- [ ] 修改 `uploadDocument()` 函数 +- [ ] 移除 `difyClient.uploadDocumentDirectly()` 调用 +- [ ] 实现本地处理流程(提取 → 切片 → 向量化) +- [ ] 移除 Dify 状态轮询逻辑 +- [ ] 实现自己的异步处理和状态更新 +- [ ] 单元测试 + +**交付物**: +- 更新后的 `documentService.ts` + +**预计工时**:6 小时 + +--- + +### Day 8:集成测试 + 效果调优 + +**目标**:端到端测试,确保功能正常 + +**任务清单**: +- [ ] 前端测试:创建知识库 +- [ ] 前端测试:上传文档 +- [ ] 前端测试:RAG 检索问答 +- [ ] 效果对比:Dify vs pgvector 检索质量 +- [ ] 性能测试:检索延迟 +- [ ] Bug 修复 + +**交付物**: +- 测试报告 +- Bug 修复记录 + +**预计工时**:8 小时 + +--- + +### Day 9:数据迁移(现有文档向量化) + +**目标**:将现有知识库文档迁移到新表并向量化 + +**任务清单**: +- [ ] 编写迁移脚本(Document → EkbDocument) +- [ ] 批量向量化现有文档 +- [ ] 验证迁移完整性 +- [ ] 验证检索效果 + +**交付物**: +- `scripts/migrate-to-ekb.ts` +- 迁移日志 + +**预计工时**:6 小时 + +**迁移脚本**: + +```typescript +// scripts/migrate-to-ekb.ts +async function migrateDocuments() { + // 1. 获取所有现有文档 + const documents = await prisma.document.findMany({ + where: { status: 'completed', extractedText: { not: null } }, + }); + + console.log(`Found ${documents.length} documents to migrate`); + + // 2. 逐个迁移 + for (const doc of documents) { + try { + // 创建 EkbDocument + const ekbDoc = await prisma.ekbDocument.create({ + data: { + kbId: doc.kbId, + userId: doc.userId, + filename: doc.filename, + fileType: doc.fileType, + fileSizeBytes: doc.fileSizeBytes, + extractedText: doc.extractedText, + status: 'embedding', + }, + }); + + // 切片 + const chunks = chunkService.splitDocument(doc.extractedText!); + + // 向量化 + const embeddings = await embeddingService.embedBatch( + chunks.map(c => c.content) + ); + + // 存入数据库 + // ... + + console.log(`✅ Migrated: ${doc.filename}`); + } catch (error) { + console.error(`❌ Failed: ${doc.filename}`, error); + } + } +} +``` + +--- + +### Day 10:清理 + 文档 + 上线 + +**目标**:清理遗留代码,更新文档,正式上线 + +**任务清单**: +- [ ] 删除 `DifyClient.ts` +- [ ] 删除 `difyDatasetId` 字段(可选,下个版本) +- [ ] 删除 `difyDocumentId` 字段(可选,下个版本) +- [ ] 更新 `00-模块当前状态与开发指南.md` +- [ ] 更新环境变量文档 +- [ ] 代码 Review +- [ ] 合并到主分支 + +**交付物**: +- 更新后的文档 +- 清理后的代码 + +**预计工时**:4 小时 + +--- + +## ⚠️ 风险评估与应对 + +### 风险矩阵 + +| 风险 | 概率 | 影响 | 等级 | 应对措施 | +|------|------|------|------|----------| +| 检索效果下降 | 中 | 高 | 🔴 | 效果评估 + 参数调优 + 回滚方案 | +| API 兼容性问题 | 低 | 高 | 🟡 | 格式转换层 + 充分测试 | +| Embedding API 限流 | 中 | 中 | 🟡 | 并发控制 + 重试机制 | +| 迁移数据丢失 | 低 | 高 | 🟡 | 备份 + 验证 + 回滚 | +| 性能下降 | 低 | 中 | 🟢 | 索引优化 + 缓存 | + +### 回滚方案 + +如果新方案效果不理想,可以: +1. 保留 `difyDatasetId` 字段,随时切回 Dify +2. 新旧服务通过 Feature Flag 切换 +3. 灰度发布:先 10% 用户使用 pgvector + +--- + +## 📊 资源需求 + +### 人力资源 + +| 角色 | 工作量 | 说明 | +|------|--------|------| +| 后端开发 | 10 人天 | 核心开发 | +| 测试 | 2 人天 | 集成测试 + 效果评估 | +| **总计** | **12 人天** | 约 2 周 | + +### 技术资源 + +| 资源 | 用途 | 成本 | +|------|------|------| +| 阿里云 DashScope | Embedding API | ~¥50/月 | +| 阿里云 DashScope | Rerank API(可选) | ~¥20/月 | +| PostgreSQL | 已有 | ¥0 | + +--- + +## ✅ 验收标准 + +### 功能验收 + +- [ ] 创建知识库:不依赖 Dify,直接创建 +- [ ] 上传文档:本地处理 + 向量化 +- [ ] RAG 检索:混合检索效果 ≥ Dify +- [ ] 全文阅读模式:正常工作 +- [ ] 批处理模式:正常工作 + +### 性能验收 + +- [ ] 检索延迟:< 500ms(95 分位) +- [ ] 上传处理:< 60s/文档(平均) +- [ ] 向量化吞吐:> 100 文档/小时 + +### 质量验收 + +- [ ] 检索召回率:≥ 80%(测试集) +- [ ] 无 Dify 相关代码残留 +- [ ] 文档更新完整 + +--- + +## 📝 附录 + +### A. 相关文档 + +- [企业级医学知识库综合技术解决方案 V2](../00-系统设计/企业级医学知识库_综合技术解决方案%20V2.md) +- [PostgreSQL与pgvector深度应用分析](../00-系统设计/医疗科研AI系统架构评估报告:PostgreSQL与pgvector在RAG及知识库中的深度应用分析.md) +- [PKB模块当前状态](../00-模块当前状态与开发指南.md) + +### B. 环境变量配置 + +```bash +# .env 新增 +DASHSCOPE_API_KEY=sk-xxx # 阿里云 DashScope API Key +EMBEDDING_MODEL=text-embedding-v3 # Embedding 模型 +EMBEDDING_DIMENSION=1024 # 向量维度 +RERANK_MODEL=gte-rerank # Rerank 模型(可选) +``` + +### C. 依赖更新 + +```json +// package.json +{ + "dependencies": { + // 新增 + "langchain": "^0.1.0", // 可选,用于切片 + "p-queue": "^8.0.0" // 并发控制 + } +} +``` + +--- + +**文档维护**:PKB 模块开发团队 +**最后更新**:2026-01-19 +**下次更新**:开发完成后更新进度 + diff --git a/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07-前端迁移与批处理功能完善.md b/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07-前端迁移与批处理功能完善.md index 3617bec1..e4223c50 100644 --- a/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07-前端迁移与批处理功能完善.md +++ b/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07-前端迁移与批处理功能完善.md @@ -368,3 +368,4 @@ const newResults = resultsData.map((docResult: any) => ({ + diff --git a/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07_PKB模块前端V3设计实现.md b/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07_PKB模块前端V3设计实现.md index 578f6e2f..81122d58 100644 --- a/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07_PKB模块前端V3设计实现.md +++ b/docs/03-业务模块/PKB-个人知识库/06-开发记录/2026-01-07_PKB模块前端V3设计实现.md @@ -241,3 +241,4 @@ const chatApi = axios.create({ + diff --git a/docs/03-业务模块/Redcap/01-部署与配置/10-REDCap_Docker部署操作手册.md b/docs/03-业务模块/Redcap/01-部署与配置/10-REDCap_Docker部署操作手册.md index 891ad4eb..ebd13638 100644 --- a/docs/03-业务模块/Redcap/01-部署与配置/10-REDCap_Docker部署操作手册.md +++ b/docs/03-业务模块/Redcap/01-部署与配置/10-REDCap_Docker部署操作手册.md @@ -776,5 +776,6 @@ docker exec redcap-apache php /tmp/create-redcap-password.php + diff --git a/docs/03-业务模块/Redcap/README.md b/docs/03-业务模块/Redcap/README.md index e8625661..72dfcf4c 100644 --- a/docs/03-业务模块/Redcap/README.md +++ b/docs/03-业务模块/Redcap/README.md @@ -158,5 +158,6 @@ AIclinicalresearch/redcap-docker-dev/ + diff --git a/docs/04-开发规范/09-数据库开发规范.md b/docs/04-开发规范/09-数据库开发规范.md index 54ab94b9..3d727ce8 100644 --- a/docs/04-开发规范/09-数据库开发规范.md +++ b/docs/04-开发规范/09-数据库开发规范.md @@ -326,3 +326,4 @@ npx tsx check_iit_asl_data.ts + diff --git a/docs/04-开发规范/10-模块认证规范.md b/docs/04-开发规范/10-模块认证规范.md index d099ef4a..15a20ba3 100644 --- a/docs/04-开发规范/10-模块认证规范.md +++ b/docs/04-开发规范/10-模块认证规范.md @@ -194,3 +194,4 @@ interface DecodedToken { + diff --git a/docs/05-部署文档/02-SAE部署完全指南(产品经理版).md b/docs/05-部署文档/02-SAE部署完全指南(产品经理版).md index 50ce8c02..3fabf52b 100644 --- a/docs/05-部署文档/02-SAE部署完全指南(产品经理版).md +++ b/docs/05-部署文档/02-SAE部署完全指南(产品经理版).md @@ -895,5 +895,6 @@ ACR镜像仓库: + diff --git a/docs/05-部署文档/07-前端Nginx-SAE部署操作手册.md b/docs/05-部署文档/07-前端Nginx-SAE部署操作手册.md index a0e4416c..614cee08 100644 --- a/docs/05-部署文档/07-前端Nginx-SAE部署操作手册.md +++ b/docs/05-部署文档/07-前端Nginx-SAE部署操作手册.md @@ -1382,5 +1382,6 @@ SAE应用配置: + diff --git a/docs/05-部署文档/08-PostgreSQL数据库部署操作手册.md b/docs/05-部署文档/08-PostgreSQL数据库部署操作手册.md index c1f799a2..fc80ceb5 100644 --- a/docs/05-部署文档/08-PostgreSQL数据库部署操作手册.md +++ b/docs/05-部署文档/08-PostgreSQL数据库部署操作手册.md @@ -1198,5 +1198,6 @@ docker exec -e PGPASSWORD="密码" ai-clinical-postgres psql -h RDS地址 -U air + diff --git a/docs/05-部署文档/10-Node.js后端-Docker镜像构建手册.md b/docs/05-部署文档/10-Node.js后端-Docker镜像构建手册.md index cfeda02a..bee11446 100644 --- a/docs/05-部署文档/10-Node.js后端-Docker镜像构建手册.md +++ b/docs/05-部署文档/10-Node.js后端-Docker镜像构建手册.md @@ -609,5 +609,6 @@ scripts/*.ts + diff --git a/docs/05-部署文档/11-Node.js后端-SAE部署配置清单.md b/docs/05-部署文档/11-Node.js后端-SAE部署配置清单.md index 8ea12ba1..6129e584 100644 --- a/docs/05-部署文档/11-Node.js后端-SAE部署配置清单.md +++ b/docs/05-部署文档/11-Node.js后端-SAE部署配置清单.md @@ -297,5 +297,6 @@ Node.js后端部署成功后: + diff --git a/docs/05-部署文档/12-Node.js后端-SAE部署操作手册.md b/docs/05-部署文档/12-Node.js后端-SAE部署操作手册.md index ce275569..3e602cdc 100644 --- a/docs/05-部署文档/12-Node.js后端-SAE部署操作手册.md +++ b/docs/05-部署文档/12-Node.js后端-SAE部署操作手册.md @@ -520,5 +520,6 @@ Node.js后端 (SAE) ← http://172.17.173.88:3001 + diff --git a/docs/05-部署文档/13-Node.js后端-镜像修复记录.md b/docs/05-部署文档/13-Node.js后端-镜像修复记录.md index e63d2373..b0e39b35 100644 --- a/docs/05-部署文档/13-Node.js后端-镜像修复记录.md +++ b/docs/05-部署文档/13-Node.js后端-镜像修复记录.md @@ -235,5 +235,6 @@ curl http://localhost:3001/health + diff --git a/docs/05-部署文档/14-Node.js后端-pino-pretty问题修复.md b/docs/05-部署文档/14-Node.js后端-pino-pretty问题修复.md index 49070460..bfaf1b86 100644 --- a/docs/05-部署文档/14-Node.js后端-pino-pretty问题修复.md +++ b/docs/05-部署文档/14-Node.js后端-pino-pretty问题修复.md @@ -273,5 +273,6 @@ npm run dev + diff --git a/docs/05-部署文档/16-前端Nginx-部署成功总结.md b/docs/05-部署文档/16-前端Nginx-部署成功总结.md index 50642e80..e1abf8e0 100644 --- a/docs/05-部署文档/16-前端Nginx-部署成功总结.md +++ b/docs/05-部署文档/16-前端Nginx-部署成功总结.md @@ -497,5 +497,6 @@ pgm-2zex1m2y3r23hdn5.pg.rds.aliyuncs.com:5432 + diff --git a/docs/05-部署文档/17-完整部署实战手册-2025版.md b/docs/05-部署文档/17-完整部署实战手册-2025版.md index 8be1d443..69819613 100644 --- a/docs/05-部署文档/17-完整部署实战手册-2025版.md +++ b/docs/05-部署文档/17-完整部署实战手册-2025版.md @@ -1825,5 +1825,6 @@ curl http://8.140.53.236/ + diff --git a/docs/05-部署文档/18-部署文档使用指南.md b/docs/05-部署文档/18-部署文档使用指南.md index 924dcdef..40a3570f 100644 --- a/docs/05-部署文档/18-部署文档使用指南.md +++ b/docs/05-部署文档/18-部署文档使用指南.md @@ -373,5 +373,6 @@ crpi-cd5ij4pjt65mweeo.cn-beijing.personal.cr.aliyuncs.com/ai-clinical/backend-se + diff --git a/docs/05-部署文档/19-日常更新快速操作手册.md b/docs/05-部署文档/19-日常更新快速操作手册.md index 217e22d4..15727197 100644 --- a/docs/05-部署文档/19-日常更新快速操作手册.md +++ b/docs/05-部署文档/19-日常更新快速操作手册.md @@ -695,5 +695,6 @@ docker login --username=gofeng117@163.com \ + diff --git a/docs/05-部署文档/文档修正报告-20251214.md b/docs/05-部署文档/文档修正报告-20251214.md index 1404b9a5..07c34ca5 100644 --- a/docs/05-部署文档/文档修正报告-20251214.md +++ b/docs/05-部署文档/文档修正报告-20251214.md @@ -506,5 +506,6 @@ NAT网关成本¥100/月,对初创团队是一笔开销 + diff --git a/docs/07-运维文档/03-SAE环境变量配置指南.md b/docs/07-运维文档/03-SAE环境变量配置指南.md index f777c4ad..d4641b44 100644 --- a/docs/07-运维文档/03-SAE环境变量配置指南.md +++ b/docs/07-运维文档/03-SAE环境变量配置指南.md @@ -411,5 +411,6 @@ curl http://你的SAE地址:3001/health + diff --git a/docs/07-运维文档/05-Redis缓存与队列的区别说明.md b/docs/07-运维文档/05-Redis缓存与队列的区别说明.md index 4578921d..7ad87b66 100644 --- a/docs/07-运维文档/05-Redis缓存与队列的区别说明.md +++ b/docs/07-运维文档/05-Redis缓存与队列的区别说明.md @@ -743,5 +743,6 @@ const job = await queue.getJob(jobId); + diff --git a/docs/07-运维文档/06-长时间任务可靠性分析.md b/docs/07-运维文档/06-长时间任务可靠性分析.md index f3ccec72..c73d7400 100644 --- a/docs/07-运维文档/06-长时间任务可靠性分析.md +++ b/docs/07-运维文档/06-长时间任务可靠性分析.md @@ -510,5 +510,6 @@ processLiteraturesInBackground(task.id, projectId, testLiteratures); + diff --git a/docs/07-运维文档/07-Redis使用需求分析(按模块).md b/docs/07-运维文档/07-Redis使用需求分析(按模块).md index 4d263500..22b93aba 100644 --- a/docs/07-运维文档/07-Redis使用需求分析(按模块).md +++ b/docs/07-运维文档/07-Redis使用需求分析(按模块).md @@ -987,5 +987,6 @@ ROI = (¥22,556 - ¥144) / ¥144 × 100% = 15,564% + diff --git a/docs/08-项目管理/03-每周计划/2025-12-13-Postgres-Only架构改造完成.md b/docs/08-项目管理/03-每周计划/2025-12-13-Postgres-Only架构改造完成.md index a5811011..6b238d0a 100644 --- a/docs/08-项目管理/03-每周计划/2025-12-13-Postgres-Only架构改造完成.md +++ b/docs/08-项目管理/03-每周计划/2025-12-13-Postgres-Only架构改造完成.md @@ -1044,5 +1044,6 @@ Redis 实例:¥500/月 + diff --git a/docs/08-项目管理/05-技术债务/通用对话服务抽取计划.md b/docs/08-项目管理/05-技术债务/通用对话服务抽取计划.md index ae953bb1..007dbaa6 100644 --- a/docs/08-项目管理/05-技术债务/通用对话服务抽取计划.md +++ b/docs/08-项目管理/05-技术债务/通用对话服务抽取计划.md @@ -502,5 +502,6 @@ import { ChatContainer } from '@/shared/components/Chat'; + diff --git a/docs/08-项目管理/2026-01-11-数据库事故总结.md b/docs/08-项目管理/2026-01-11-数据库事故总结.md index fe45f2f9..ceb22a7b 100644 --- a/docs/08-项目管理/2026-01-11-数据库事故总结.md +++ b/docs/08-项目管理/2026-01-11-数据库事故总结.md @@ -210,3 +210,4 @@ VALUES ('user-mock-001', '13800000000', ..., 'tenant-mock-001', ...); + diff --git a/docs/08-项目管理/PKB前端问题修复报告.md b/docs/08-项目管理/PKB前端问题修复报告.md index 48b8208a..28eb0f24 100644 --- a/docs/08-项目管理/PKB前端问题修复报告.md +++ b/docs/08-项目管理/PKB前端问题修复报告.md @@ -422,3 +422,4 @@ frontend-v2/src/modules/pkb/ + diff --git a/docs/08-项目管理/PKB前端验证指南.md b/docs/08-项目管理/PKB前端验证指南.md index 6616132b..704a6f12 100644 --- a/docs/08-项目管理/PKB前端验证指南.md +++ b/docs/08-项目管理/PKB前端验证指南.md @@ -284,3 +284,4 @@ npm run dev + diff --git a/docs/08-项目管理/PKB功能审查报告-阶段0.md b/docs/08-项目管理/PKB功能审查报告-阶段0.md index 8baf689f..4e460e53 100644 --- a/docs/08-项目管理/PKB功能审查报告-阶段0.md +++ b/docs/08-项目管理/PKB功能审查报告-阶段0.md @@ -799,3 +799,4 @@ AIA智能问答模块 + diff --git a/docs/08-项目管理/PKB和RVW功能迁移计划.md b/docs/08-项目管理/PKB和RVW功能迁移计划.md index 8217baee..aa1bd004 100644 --- a/docs/08-项目管理/PKB和RVW功能迁移计划.md +++ b/docs/08-项目管理/PKB和RVW功能迁移计划.md @@ -942,5 +942,6 @@ CREATE INDEX idx_rvw_tasks_created_at ON rvw_schema.review_tasks(created_at); + diff --git a/docs/08-项目管理/PKB精细化优化报告.md b/docs/08-项目管理/PKB精细化优化报告.md index 5f95ac10..1da5c981 100644 --- a/docs/08-项目管理/PKB精细化优化报告.md +++ b/docs/08-项目管理/PKB精细化优化报告.md @@ -597,3 +597,4 @@ const typography = { + diff --git a/docs/08-项目管理/PKB迁移-超级安全执行计划.md b/docs/08-项目管理/PKB迁移-超级安全执行计划.md index dbcc07b4..3388a9a0 100644 --- a/docs/08-项目管理/PKB迁移-超级安全执行计划.md +++ b/docs/08-项目管理/PKB迁移-超级安全执行计划.md @@ -909,3 +909,4 @@ app.use('/api/v1/knowledge', (req, res) => { + diff --git a/docs/08-项目管理/PKB迁移-阶段1完成报告.md b/docs/08-项目管理/PKB迁移-阶段1完成报告.md index 342b3595..cd56e00e 100644 --- a/docs/08-项目管理/PKB迁移-阶段1完成报告.md +++ b/docs/08-项目管理/PKB迁移-阶段1完成报告.md @@ -223,3 +223,4 @@ rm -rf src/modules/pkb + diff --git a/docs/08-项目管理/PKB迁移-阶段2完成报告.md b/docs/08-项目管理/PKB迁移-阶段2完成报告.md index cfb5ba3c..8eb19a42 100644 --- a/docs/08-项目管理/PKB迁移-阶段2完成报告.md +++ b/docs/08-项目管理/PKB迁移-阶段2完成报告.md @@ -398,3 +398,4 @@ GET /api/v2/pkb/batch-tasks/batch/templates + diff --git a/docs/08-项目管理/PKB迁移-阶段2进行中.md b/docs/08-项目管理/PKB迁移-阶段2进行中.md index 1a5e8e69..2c2a6d60 100644 --- a/docs/08-项目管理/PKB迁移-阶段2进行中.md +++ b/docs/08-项目管理/PKB迁移-阶段2进行中.md @@ -42,3 +42,4 @@ import pkbRoutes from './modules/pkb/routes/index.js'; + diff --git a/docs/08-项目管理/PKB迁移-阶段3完成报告.md b/docs/08-项目管理/PKB迁移-阶段3完成报告.md index 053f7923..3cb6aefc 100644 --- a/docs/08-项目管理/PKB迁移-阶段3完成报告.md +++ b/docs/08-项目管理/PKB迁移-阶段3完成报告.md @@ -311,3 +311,4 @@ backend/ + diff --git a/docs/08-项目管理/PKB迁移-阶段4完成报告.md b/docs/08-项目管理/PKB迁移-阶段4完成报告.md index 476ed0bf..4cb8544f 100644 --- a/docs/08-项目管理/PKB迁移-阶段4完成报告.md +++ b/docs/08-项目管理/PKB迁移-阶段4完成报告.md @@ -522,3 +522,4 @@ const response = await fetch('/api/v2/pkb/batch-tasks/batch/execute', { + diff --git a/extraction_service/.dockerignore b/extraction_service/.dockerignore index f633f0ea..606148bc 100644 --- a/extraction_service/.dockerignore +++ b/extraction_service/.dockerignore @@ -80,5 +80,6 @@ models/ + diff --git a/extraction_service/operations/__init__.py b/extraction_service/operations/__init__.py index eae8e338..aff87dc6 100644 --- a/extraction_service/operations/__init__.py +++ b/extraction_service/operations/__init__.py @@ -68,5 +68,6 @@ __version__ = '1.0.0' + diff --git a/extraction_service/operations/dropna.py b/extraction_service/operations/dropna.py index 1515f129..4ba958c6 100644 --- a/extraction_service/operations/dropna.py +++ b/extraction_service/operations/dropna.py @@ -201,5 +201,6 @@ def get_missing_summary(df: pd.DataFrame) -> dict: + diff --git a/extraction_service/operations/filter.py b/extraction_service/operations/filter.py index 03eb8167..2339be30 100644 --- a/extraction_service/operations/filter.py +++ b/extraction_service/operations/filter.py @@ -161,5 +161,6 @@ def apply_filter( + diff --git a/extraction_service/operations/unpivot.py b/extraction_service/operations/unpivot.py index 34bd6d33..f612c672 100644 --- a/extraction_service/operations/unpivot.py +++ b/extraction_service/operations/unpivot.py @@ -325,5 +325,6 @@ def get_unpivot_preview( + diff --git a/extraction_service/test_dc_api.py b/extraction_service/test_dc_api.py index b5a011d9..4e34d1da 100644 --- a/extraction_service/test_dc_api.py +++ b/extraction_service/test_dc_api.py @@ -335,5 +335,6 @@ if __name__ == "__main__": + diff --git a/extraction_service/test_execute_simple.py b/extraction_service/test_execute_simple.py index 57bfdaec..584d3de6 100644 --- a/extraction_service/test_execute_simple.py +++ b/extraction_service/test_execute_simple.py @@ -101,5 +101,6 @@ except Exception as e: + diff --git a/extraction_service/test_module.py b/extraction_service/test_module.py index 67f79ea6..124cd553 100644 --- a/extraction_service/test_module.py +++ b/extraction_service/test_module.py @@ -81,5 +81,6 @@ except Exception as e: + diff --git a/frontend-v2/.dockerignore b/frontend-v2/.dockerignore index 2dc0460d..185b36b0 100644 --- a/frontend-v2/.dockerignore +++ b/frontend-v2/.dockerignore @@ -100,5 +100,6 @@ vite.config.*.timestamp-* + diff --git a/frontend-v2/docker-entrypoint.sh b/frontend-v2/docker-entrypoint.sh index a48b4a2b..90c55e50 100644 --- a/frontend-v2/docker-entrypoint.sh +++ b/frontend-v2/docker-entrypoint.sh @@ -67,5 +67,6 @@ exec nginx -g 'daemon off;' + diff --git a/frontend-v2/nginx.conf b/frontend-v2/nginx.conf index 2cc987c2..e26b9be1 100644 --- a/frontend-v2/nginx.conf +++ b/frontend-v2/nginx.conf @@ -223,5 +223,6 @@ http { + diff --git a/frontend-v2/src/common/api/axios.ts b/frontend-v2/src/common/api/axios.ts index 00abed30..ca683536 100644 --- a/frontend-v2/src/common/api/axios.ts +++ b/frontend-v2/src/common/api/axios.ts @@ -52,3 +52,4 @@ export default apiClient; + diff --git a/frontend-v2/src/framework/auth/api.ts b/frontend-v2/src/framework/auth/api.ts index 53b903e1..16081fea 100644 --- a/frontend-v2/src/framework/auth/api.ts +++ b/frontend-v2/src/framework/auth/api.ts @@ -251,3 +251,4 @@ export async function logout(): Promise { + diff --git a/frontend-v2/src/framework/auth/index.ts b/frontend-v2/src/framework/auth/index.ts index a0efa503..6393e042 100644 --- a/frontend-v2/src/framework/auth/index.ts +++ b/frontend-v2/src/framework/auth/index.ts @@ -17,3 +17,4 @@ export * from './api'; + diff --git a/frontend-v2/src/framework/auth/moduleApi.ts b/frontend-v2/src/framework/auth/moduleApi.ts index 2f456c22..f22a1c03 100644 --- a/frontend-v2/src/framework/auth/moduleApi.ts +++ b/frontend-v2/src/framework/auth/moduleApi.ts @@ -41,3 +41,4 @@ export async function fetchUserModules(): Promise { + diff --git a/frontend-v2/src/modules/admin/components/ModulePermissionModal.tsx b/frontend-v2/src/modules/admin/components/ModulePermissionModal.tsx index 86d0f6a3..7ee51e2c 100644 --- a/frontend-v2/src/modules/admin/components/ModulePermissionModal.tsx +++ b/frontend-v2/src/modules/admin/components/ModulePermissionModal.tsx @@ -121,3 +121,4 @@ export default ModulePermissionModal; + diff --git a/frontend-v2/src/modules/admin/index.tsx b/frontend-v2/src/modules/admin/index.tsx index 60927b08..e22897e8 100644 --- a/frontend-v2/src/modules/admin/index.tsx +++ b/frontend-v2/src/modules/admin/index.tsx @@ -32,3 +32,4 @@ export default AdminModule; + diff --git a/frontend-v2/src/modules/admin/types/user.ts b/frontend-v2/src/modules/admin/types/user.ts index d869a14f..5a7c94d5 100644 --- a/frontend-v2/src/modules/admin/types/user.ts +++ b/frontend-v2/src/modules/admin/types/user.ts @@ -197,3 +197,4 @@ export const TENANT_TYPE_NAMES: Record = { + diff --git a/frontend-v2/src/modules/aia/components/AgentCard.tsx b/frontend-v2/src/modules/aia/components/AgentCard.tsx index 550f102e..d752ecbd 100644 --- a/frontend-v2/src/modules/aia/components/AgentCard.tsx +++ b/frontend-v2/src/modules/aia/components/AgentCard.tsx @@ -81,3 +81,4 @@ export default AgentCard; + diff --git a/frontend-v2/src/modules/aia/components/index.ts b/frontend-v2/src/modules/aia/components/index.ts index b2fff91d..7b7d44db 100644 --- a/frontend-v2/src/modules/aia/components/index.ts +++ b/frontend-v2/src/modules/aia/components/index.ts @@ -11,3 +11,4 @@ export { ChatWorkspace } from './ChatWorkspace'; + diff --git a/frontend-v2/src/modules/aia/constants.ts b/frontend-v2/src/modules/aia/constants.ts index fa247a42..c64aec94 100644 --- a/frontend-v2/src/modules/aia/constants.ts +++ b/frontend-v2/src/modules/aia/constants.ts @@ -175,3 +175,4 @@ export const BRAND_COLORS = { + diff --git a/frontend-v2/src/modules/aia/styles/agent-card.css b/frontend-v2/src/modules/aia/styles/agent-card.css index baabf420..ae1b1c6e 100644 --- a/frontend-v2/src/modules/aia/styles/agent-card.css +++ b/frontend-v2/src/modules/aia/styles/agent-card.css @@ -213,3 +213,4 @@ + diff --git a/frontend-v2/src/modules/asl/components/FulltextDetailDrawer.tsx b/frontend-v2/src/modules/asl/components/FulltextDetailDrawer.tsx index 08a6a89a..1a181333 100644 --- a/frontend-v2/src/modules/asl/components/FulltextDetailDrawer.tsx +++ b/frontend-v2/src/modules/asl/components/FulltextDetailDrawer.tsx @@ -570,5 +570,6 @@ export default FulltextDetailDrawer; + diff --git a/frontend-v2/src/modules/dc/hooks/useAssets.ts b/frontend-v2/src/modules/dc/hooks/useAssets.ts index b590e6f1..0d9cbedb 100644 --- a/frontend-v2/src/modules/dc/hooks/useAssets.ts +++ b/frontend-v2/src/modules/dc/hooks/useAssets.ts @@ -163,5 +163,6 @@ export const useAssets = (activeTab: AssetTabType) => { + diff --git a/frontend-v2/src/modules/dc/hooks/useRecentTasks.ts b/frontend-v2/src/modules/dc/hooks/useRecentTasks.ts index 40d832a2..858b194b 100644 --- a/frontend-v2/src/modules/dc/hooks/useRecentTasks.ts +++ b/frontend-v2/src/modules/dc/hooks/useRecentTasks.ts @@ -153,5 +153,6 @@ export const useRecentTasks = () => { + diff --git a/frontend-v2/src/modules/dc/pages/tool-c/components/DropnaDialog.tsx b/frontend-v2/src/modules/dc/pages/tool-c/components/DropnaDialog.tsx index 59b9fc09..d8b8292f 100644 --- a/frontend-v2/src/modules/dc/pages/tool-c/components/DropnaDialog.tsx +++ b/frontend-v2/src/modules/dc/pages/tool-c/components/DropnaDialog.tsx @@ -352,5 +352,6 @@ export default DropnaDialog; + diff --git a/frontend-v2/src/modules/dc/pages/tool-c/components/MetricTimePanel.tsx b/frontend-v2/src/modules/dc/pages/tool-c/components/MetricTimePanel.tsx index 1d02e56f..08f89812 100644 --- a/frontend-v2/src/modules/dc/pages/tool-c/components/MetricTimePanel.tsx +++ b/frontend-v2/src/modules/dc/pages/tool-c/components/MetricTimePanel.tsx @@ -437,5 +437,6 @@ export default MetricTimePanel; + diff --git a/frontend-v2/src/modules/dc/pages/tool-c/components/PivotPanel.tsx b/frontend-v2/src/modules/dc/pages/tool-c/components/PivotPanel.tsx index 8d06f5b8..8724de0a 100644 --- a/frontend-v2/src/modules/dc/pages/tool-c/components/PivotPanel.tsx +++ b/frontend-v2/src/modules/dc/pages/tool-c/components/PivotPanel.tsx @@ -323,5 +323,6 @@ export default PivotPanel; + diff --git a/frontend-v2/src/modules/dc/pages/tool-c/hooks/useSessionStatus.ts b/frontend-v2/src/modules/dc/pages/tool-c/hooks/useSessionStatus.ts index aab0ec37..5f18e383 100644 --- a/frontend-v2/src/modules/dc/pages/tool-c/hooks/useSessionStatus.ts +++ b/frontend-v2/src/modules/dc/pages/tool-c/hooks/useSessionStatus.ts @@ -123,5 +123,6 @@ export function useSessionStatus({ + diff --git a/frontend-v2/src/modules/dc/pages/tool-c/types/index.ts b/frontend-v2/src/modules/dc/pages/tool-c/types/index.ts index cf786e8b..df77aea6 100644 --- a/frontend-v2/src/modules/dc/pages/tool-c/types/index.ts +++ b/frontend-v2/src/modules/dc/pages/tool-c/types/index.ts @@ -115,5 +115,6 @@ export interface DataStats { + diff --git a/frontend-v2/src/modules/dc/types/portal.ts b/frontend-v2/src/modules/dc/types/portal.ts index 87580bed..c8caa357 100644 --- a/frontend-v2/src/modules/dc/types/portal.ts +++ b/frontend-v2/src/modules/dc/types/portal.ts @@ -111,5 +111,6 @@ export type AssetTabType = 'all' | 'processed' | 'raw'; + diff --git a/frontend-v2/src/modules/pkb/pages/KnowledgePage.tsx b/frontend-v2/src/modules/pkb/pages/KnowledgePage.tsx index 06bd19fc..f0e20180 100644 --- a/frontend-v2/src/modules/pkb/pages/KnowledgePage.tsx +++ b/frontend-v2/src/modules/pkb/pages/KnowledgePage.tsx @@ -300,3 +300,4 @@ export default KnowledgePage; + diff --git a/frontend-v2/src/modules/pkb/types/workspace.ts b/frontend-v2/src/modules/pkb/types/workspace.ts index 1d2ce68b..3efa6a51 100644 --- a/frontend-v2/src/modules/pkb/types/workspace.ts +++ b/frontend-v2/src/modules/pkb/types/workspace.ts @@ -55,3 +55,4 @@ export interface BatchTemplate { + diff --git a/frontend-v2/src/modules/rvw/components/AgentModal.tsx b/frontend-v2/src/modules/rvw/components/AgentModal.tsx index 9462435a..480b4458 100644 --- a/frontend-v2/src/modules/rvw/components/AgentModal.tsx +++ b/frontend-v2/src/modules/rvw/components/AgentModal.tsx @@ -133,3 +133,4 @@ export default function AgentModal({ visible, taskCount, onClose, onConfirm }: A + diff --git a/frontend-v2/src/modules/rvw/components/BatchToolbar.tsx b/frontend-v2/src/modules/rvw/components/BatchToolbar.tsx index 290f8391..a82c28b4 100644 --- a/frontend-v2/src/modules/rvw/components/BatchToolbar.tsx +++ b/frontend-v2/src/modules/rvw/components/BatchToolbar.tsx @@ -53,3 +53,4 @@ export default function BatchToolbar({ selectedCount, onRunBatch, onClearSelecti + diff --git a/frontend-v2/src/modules/rvw/components/FilterChips.tsx b/frontend-v2/src/modules/rvw/components/FilterChips.tsx index 5ec7370b..5e22b3eb 100644 --- a/frontend-v2/src/modules/rvw/components/FilterChips.tsx +++ b/frontend-v2/src/modules/rvw/components/FilterChips.tsx @@ -76,3 +76,4 @@ export default function FilterChips({ filters, counts, onFilterChange }: FilterC + diff --git a/frontend-v2/src/modules/rvw/components/Header.tsx b/frontend-v2/src/modules/rvw/components/Header.tsx index c82c4f0b..859a5c91 100644 --- a/frontend-v2/src/modules/rvw/components/Header.tsx +++ b/frontend-v2/src/modules/rvw/components/Header.tsx @@ -66,3 +66,4 @@ export default function Header({ onUpload }: HeaderProps) { + diff --git a/frontend-v2/src/modules/rvw/components/ReportDetail.tsx b/frontend-v2/src/modules/rvw/components/ReportDetail.tsx index b0d26ff3..f41d377a 100644 --- a/frontend-v2/src/modules/rvw/components/ReportDetail.tsx +++ b/frontend-v2/src/modules/rvw/components/ReportDetail.tsx @@ -120,3 +120,4 @@ export default function ReportDetail({ report, onBack }: ReportDetailProps) { + diff --git a/frontend-v2/src/modules/rvw/components/ScoreRing.tsx b/frontend-v2/src/modules/rvw/components/ScoreRing.tsx index 95ffc66e..6e227627 100644 --- a/frontend-v2/src/modules/rvw/components/ScoreRing.tsx +++ b/frontend-v2/src/modules/rvw/components/ScoreRing.tsx @@ -48,3 +48,4 @@ export default function ScoreRing({ score, size = 'medium', showLabel = true }: + diff --git a/frontend-v2/src/modules/rvw/components/Sidebar.tsx b/frontend-v2/src/modules/rvw/components/Sidebar.tsx index 367eec7a..4e4b7bbc 100644 --- a/frontend-v2/src/modules/rvw/components/Sidebar.tsx +++ b/frontend-v2/src/modules/rvw/components/Sidebar.tsx @@ -83,3 +83,4 @@ export default function Sidebar({ currentView, onViewChange, onSettingsClick }: + diff --git a/frontend-v2/src/modules/rvw/components/index.ts b/frontend-v2/src/modules/rvw/components/index.ts index ed62a6ad..db697d2a 100644 --- a/frontend-v2/src/modules/rvw/components/index.ts +++ b/frontend-v2/src/modules/rvw/components/index.ts @@ -25,3 +25,4 @@ export { default as TaskDetail } from './TaskDetail'; + diff --git a/frontend-v2/src/modules/rvw/pages/Dashboard.tsx b/frontend-v2/src/modules/rvw/pages/Dashboard.tsx index 6f872f41..225b7802 100644 --- a/frontend-v2/src/modules/rvw/pages/Dashboard.tsx +++ b/frontend-v2/src/modules/rvw/pages/Dashboard.tsx @@ -294,3 +294,4 @@ export default function Dashboard() { + diff --git a/frontend-v2/src/modules/rvw/styles/index.css b/frontend-v2/src/modules/rvw/styles/index.css index 1bb01665..db7e3a98 100644 --- a/frontend-v2/src/modules/rvw/styles/index.css +++ b/frontend-v2/src/modules/rvw/styles/index.css @@ -243,3 +243,4 @@ + diff --git a/frontend-v2/src/pages/admin/tenants/TenantListPage.tsx b/frontend-v2/src/pages/admin/tenants/TenantListPage.tsx index 487afa3f..fe91e18c 100644 --- a/frontend-v2/src/pages/admin/tenants/TenantListPage.tsx +++ b/frontend-v2/src/pages/admin/tenants/TenantListPage.tsx @@ -344,3 +344,4 @@ export default TenantListPage; + diff --git a/frontend-v2/src/pages/admin/tenants/api/tenantApi.ts b/frontend-v2/src/pages/admin/tenants/api/tenantApi.ts index b149453c..e6b8bd19 100644 --- a/frontend-v2/src/pages/admin/tenants/api/tenantApi.ts +++ b/frontend-v2/src/pages/admin/tenants/api/tenantApi.ts @@ -253,3 +253,4 @@ export async function fetchModuleList(): Promise { + diff --git a/frontend-v2/src/shared/components/Chat/AIStreamChat.tsx b/frontend-v2/src/shared/components/Chat/AIStreamChat.tsx index f5b8a526..ea2b37db 100644 --- a/frontend-v2/src/shared/components/Chat/AIStreamChat.tsx +++ b/frontend-v2/src/shared/components/Chat/AIStreamChat.tsx @@ -472,3 +472,4 @@ export default AIStreamChat; + diff --git a/frontend-v2/src/shared/components/Chat/ConversationList.tsx b/frontend-v2/src/shared/components/Chat/ConversationList.tsx index 40f261d1..66679aa7 100644 --- a/frontend-v2/src/shared/components/Chat/ConversationList.tsx +++ b/frontend-v2/src/shared/components/Chat/ConversationList.tsx @@ -172,3 +172,4 @@ export default ConversationList; + diff --git a/frontend-v2/src/shared/components/Chat/hooks/index.ts b/frontend-v2/src/shared/components/Chat/hooks/index.ts index 45e2258a..ae03c6f1 100644 --- a/frontend-v2/src/shared/components/Chat/hooks/index.ts +++ b/frontend-v2/src/shared/components/Chat/hooks/index.ts @@ -24,3 +24,4 @@ export type { + diff --git a/frontend-v2/src/shared/components/Chat/hooks/useAIStream.ts b/frontend-v2/src/shared/components/Chat/hooks/useAIStream.ts index 7c5701a7..55996cf8 100644 --- a/frontend-v2/src/shared/components/Chat/hooks/useAIStream.ts +++ b/frontend-v2/src/shared/components/Chat/hooks/useAIStream.ts @@ -316,3 +316,4 @@ export default useAIStream; + diff --git a/frontend-v2/src/shared/components/Chat/hooks/useConversations.ts b/frontend-v2/src/shared/components/Chat/hooks/useConversations.ts index ff4b5c2d..e809f8e1 100644 --- a/frontend-v2/src/shared/components/Chat/hooks/useConversations.ts +++ b/frontend-v2/src/shared/components/Chat/hooks/useConversations.ts @@ -245,3 +245,4 @@ export default useConversations; + diff --git a/frontend-v2/src/shared/components/Chat/styles/ai-stream-chat.css b/frontend-v2/src/shared/components/Chat/styles/ai-stream-chat.css index 26890f30..f9d64d0f 100644 --- a/frontend-v2/src/shared/components/Chat/styles/ai-stream-chat.css +++ b/frontend-v2/src/shared/components/Chat/styles/ai-stream-chat.css @@ -280,3 +280,4 @@ + diff --git a/frontend-v2/src/shared/components/Chat/styles/conversation-list.css b/frontend-v2/src/shared/components/Chat/styles/conversation-list.css index f1248eaf..bba9eeac 100644 --- a/frontend-v2/src/shared/components/Chat/styles/conversation-list.css +++ b/frontend-v2/src/shared/components/Chat/styles/conversation-list.css @@ -216,3 +216,4 @@ + diff --git a/frontend-v2/src/shared/components/Chat/styles/thinking.css b/frontend-v2/src/shared/components/Chat/styles/thinking.css index 00669e36..00fdcebc 100644 --- a/frontend-v2/src/shared/components/Chat/styles/thinking.css +++ b/frontend-v2/src/shared/components/Chat/styles/thinking.css @@ -153,3 +153,4 @@ + diff --git a/frontend-v2/src/shared/components/index.ts b/frontend-v2/src/shared/components/index.ts index f6c83c6f..2233bd51 100644 --- a/frontend-v2/src/shared/components/index.ts +++ b/frontend-v2/src/shared/components/index.ts @@ -66,5 +66,6 @@ export { default as Placeholder } from './Placeholder'; + diff --git a/frontend-v2/src/vite-env.d.ts b/frontend-v2/src/vite-env.d.ts index ee7e20e7..6fe6fabf 100644 --- a/frontend-v2/src/vite-env.d.ts +++ b/frontend-v2/src/vite-env.d.ts @@ -46,5 +46,6 @@ interface ImportMeta { + diff --git a/frontend/src/pages/rvw/components/BatchToolbar.tsx b/frontend/src/pages/rvw/components/BatchToolbar.tsx index 4ddcf290..17028a29 100644 --- a/frontend/src/pages/rvw/components/BatchToolbar.tsx +++ b/frontend/src/pages/rvw/components/BatchToolbar.tsx @@ -55,3 +55,4 @@ export default function BatchToolbar({ selectedCount, onRunBatch, onClearSelecti + diff --git a/frontend/src/pages/rvw/components/EditorialReport.tsx b/frontend/src/pages/rvw/components/EditorialReport.tsx index ca3d5e02..4a3b0fdf 100644 --- a/frontend/src/pages/rvw/components/EditorialReport.tsx +++ b/frontend/src/pages/rvw/components/EditorialReport.tsx @@ -120,3 +120,4 @@ export default function EditorialReport({ data }: EditorialReportProps) { + diff --git a/frontend/src/pages/rvw/components/FilterChips.tsx b/frontend/src/pages/rvw/components/FilterChips.tsx index 5d9ad79b..deda01d8 100644 --- a/frontend/src/pages/rvw/components/FilterChips.tsx +++ b/frontend/src/pages/rvw/components/FilterChips.tsx @@ -78,3 +78,4 @@ export default function FilterChips({ filters, counts, onFilterChange }: FilterC + diff --git a/frontend/src/pages/rvw/components/Header.tsx b/frontend/src/pages/rvw/components/Header.tsx index bc160158..7c687797 100644 --- a/frontend/src/pages/rvw/components/Header.tsx +++ b/frontend/src/pages/rvw/components/Header.tsx @@ -68,3 +68,4 @@ export default function Header({ onUpload }: HeaderProps) { + diff --git a/frontend/src/pages/rvw/components/ReportDetail.tsx b/frontend/src/pages/rvw/components/ReportDetail.tsx index 486d7654..fcdbfca1 100644 --- a/frontend/src/pages/rvw/components/ReportDetail.tsx +++ b/frontend/src/pages/rvw/components/ReportDetail.tsx @@ -122,3 +122,4 @@ export default function ReportDetail({ report, onBack }: ReportDetailProps) { + diff --git a/frontend/src/pages/rvw/components/ScoreRing.tsx b/frontend/src/pages/rvw/components/ScoreRing.tsx index 8c61d2f3..88d6ca57 100644 --- a/frontend/src/pages/rvw/components/ScoreRing.tsx +++ b/frontend/src/pages/rvw/components/ScoreRing.tsx @@ -50,3 +50,4 @@ export default function ScoreRing({ score, size = 'medium', showLabel = true }: + diff --git a/frontend/src/pages/rvw/components/Sidebar.tsx b/frontend/src/pages/rvw/components/Sidebar.tsx index 8d5610d6..792101f8 100644 --- a/frontend/src/pages/rvw/components/Sidebar.tsx +++ b/frontend/src/pages/rvw/components/Sidebar.tsx @@ -85,3 +85,4 @@ export default function Sidebar({ currentView, onViewChange, onSettingsClick }: + diff --git a/frontend/src/pages/rvw/index.ts b/frontend/src/pages/rvw/index.ts index 52cfe7bb..e230d24a 100644 --- a/frontend/src/pages/rvw/index.ts +++ b/frontend/src/pages/rvw/index.ts @@ -19,3 +19,4 @@ export * from './api'; + diff --git a/frontend/src/pages/rvw/styles.css b/frontend/src/pages/rvw/styles.css index 7bd17e6c..092440d2 100644 --- a/frontend/src/pages/rvw/styles.css +++ b/frontend/src/pages/rvw/styles.css @@ -245,3 +245,4 @@ + diff --git a/git-cleanup-redcap.ps1 b/git-cleanup-redcap.ps1 index 89496411..7b19fcb0 100644 --- a/git-cleanup-redcap.ps1 +++ b/git-cleanup-redcap.ps1 @@ -39,5 +39,6 @@ Write-Host "Next step: Run the commit command" -ForegroundColor Cyan + diff --git a/git-commit-day1.ps1 b/git-commit-day1.ps1 index bab0d924..0097d645 100644 --- a/git-commit-day1.ps1 +++ b/git-commit-day1.ps1 @@ -95,5 +95,6 @@ Write-Host "Git commit and push completed!" -ForegroundColor Green + diff --git a/git-fix-lock.ps1 b/git-fix-lock.ps1 index e704fb3f..d96fe31d 100644 --- a/git-fix-lock.ps1 +++ b/git-fix-lock.ps1 @@ -43,5 +43,6 @@ Write-Host "Now you can run git commands again." -ForegroundColor Cyan + diff --git a/pgvector-0.8.0.tar.gz b/pgvector-0.8.0.tar.gz new file mode 100644 index 00000000..86e71562 Binary files /dev/null and b/pgvector-0.8.0.tar.gz differ diff --git a/postgres_volume_backup_20260119.tar b/postgres_volume_backup_20260119.tar new file mode 100644 index 00000000..e1a410dc Binary files /dev/null and b/postgres_volume_backup_20260119.tar differ diff --git a/python-microservice/operations/__init__.py b/python-microservice/operations/__init__.py index eae8e338..aff87dc6 100644 --- a/python-microservice/operations/__init__.py +++ b/python-microservice/operations/__init__.py @@ -68,5 +68,6 @@ __version__ = '1.0.0' + diff --git a/python-microservice/operations/binning.py b/python-microservice/operations/binning.py index 4757f37c..9919ec7a 100644 --- a/python-microservice/operations/binning.py +++ b/python-microservice/operations/binning.py @@ -175,5 +175,6 @@ def apply_binning( + diff --git a/python-microservice/operations/filter.py b/python-microservice/operations/filter.py index 03eb8167..2339be30 100644 --- a/python-microservice/operations/filter.py +++ b/python-microservice/operations/filter.py @@ -161,5 +161,6 @@ def apply_filter( + diff --git a/python-microservice/operations/recode.py b/python-microservice/operations/recode.py index b2492032..9b7ee9dd 100644 --- a/python-microservice/operations/recode.py +++ b/python-microservice/operations/recode.py @@ -131,5 +131,6 @@ def apply_recode( + diff --git a/recover_dc_code.py b/recover_dc_code.py index 2a5d7f5d..0b862cd1 100644 --- a/recover_dc_code.py +++ b/recover_dc_code.py @@ -275,5 +275,6 @@ if __name__ == "__main__": + diff --git a/redcap-docker-dev/.gitattributes b/redcap-docker-dev/.gitattributes index 9f6a4d3a..93e94698 100644 --- a/redcap-docker-dev/.gitattributes +++ b/redcap-docker-dev/.gitattributes @@ -55,5 +55,6 @@ + diff --git a/redcap-docker-dev/.gitignore b/redcap-docker-dev/.gitignore index 56114b58..17ed4d5d 100644 --- a/redcap-docker-dev/.gitignore +++ b/redcap-docker-dev/.gitignore @@ -86,5 +86,6 @@ Desktop.ini + diff --git a/redcap-docker-dev/README.md b/redcap-docker-dev/README.md index 5506e356..4f8779a6 100644 --- a/redcap-docker-dev/README.md +++ b/redcap-docker-dev/README.md @@ -387,5 +387,6 @@ docker-compose -f docker-compose.prod.yml up -d + diff --git a/redcap-docker-dev/docker-compose.prod.yml b/redcap-docker-dev/docker-compose.prod.yml index beefe430..1cf5786e 100644 --- a/redcap-docker-dev/docker-compose.prod.yml +++ b/redcap-docker-dev/docker-compose.prod.yml @@ -148,5 +148,6 @@ volumes: + diff --git a/redcap-docker-dev/docker-compose.yml b/redcap-docker-dev/docker-compose.yml index 89f7b513..b02380ee 100644 --- a/redcap-docker-dev/docker-compose.yml +++ b/redcap-docker-dev/docker-compose.yml @@ -146,5 +146,6 @@ volumes: + diff --git a/redcap-docker-dev/env.template b/redcap-docker-dev/env.template index 86d1daa8..659791ef 100644 --- a/redcap-docker-dev/env.template +++ b/redcap-docker-dev/env.template @@ -82,5 +82,6 @@ PMA_UPLOAD_LIMIT=50M + diff --git a/redcap-docker-dev/scripts/clean-redcap.ps1 b/redcap-docker-dev/scripts/clean-redcap.ps1 index e963774c..03af114d 100644 --- a/redcap-docker-dev/scripts/clean-redcap.ps1 +++ b/redcap-docker-dev/scripts/clean-redcap.ps1 @@ -90,5 +90,6 @@ Write-Host "" + diff --git a/redcap-docker-dev/scripts/create-redcap-password.php b/redcap-docker-dev/scripts/create-redcap-password.php index 568aa4d1..e35e2c15 100644 --- a/redcap-docker-dev/scripts/create-redcap-password.php +++ b/redcap-docker-dev/scripts/create-redcap-password.php @@ -68,5 +68,6 @@ try { + diff --git a/redcap-docker-dev/scripts/logs-redcap.ps1 b/redcap-docker-dev/scripts/logs-redcap.ps1 index 1d92b1d8..c4f45cb7 100644 --- a/redcap-docker-dev/scripts/logs-redcap.ps1 +++ b/redcap-docker-dev/scripts/logs-redcap.ps1 @@ -81,5 +81,6 @@ Write-Host "" + diff --git a/redcap-docker-dev/scripts/reset-admin-password.php b/redcap-docker-dev/scripts/reset-admin-password.php index de386f5d..22b4c563 100644 --- a/redcap-docker-dev/scripts/reset-admin-password.php +++ b/redcap-docker-dev/scripts/reset-admin-password.php @@ -44,5 +44,6 @@ if ($result) { + diff --git a/redcap-docker-dev/scripts/start-redcap.ps1 b/redcap-docker-dev/scripts/start-redcap.ps1 index f1b5bc1e..77179aa5 100644 --- a/redcap-docker-dev/scripts/start-redcap.ps1 +++ b/redcap-docker-dev/scripts/start-redcap.ps1 @@ -66,5 +66,6 @@ if ($LASTEXITCODE -eq 0) { + diff --git a/redcap-docker-dev/scripts/stop-redcap.ps1 b/redcap-docker-dev/scripts/stop-redcap.ps1 index 153b4cc1..53051b9a 100644 --- a/redcap-docker-dev/scripts/stop-redcap.ps1 +++ b/redcap-docker-dev/scripts/stop-redcap.ps1 @@ -52,5 +52,6 @@ if ($LASTEXITCODE -eq 0) { + diff --git a/run_recovery.ps1 b/run_recovery.ps1 index 5f8a77c8..d21943a9 100644 --- a/run_recovery.ps1 +++ b/run_recovery.ps1 @@ -99,5 +99,6 @@ Write-Host "==================================================================== + diff --git a/tests/QUICKSTART_快速开始.md b/tests/QUICKSTART_快速开始.md index 7e0b1b74..7fba61be 100644 --- a/tests/QUICKSTART_快速开始.md +++ b/tests/QUICKSTART_快速开始.md @@ -146,5 +146,6 @@ INFO: Uvicorn running on http://0.0.0.0:8001 + diff --git a/tests/README_测试说明.md b/tests/README_测试说明.md index e8cd7231..1aa53050 100644 --- a/tests/README_测试说明.md +++ b/tests/README_测试说明.md @@ -302,5 +302,6 @@ df_numeric.to_excel('test_data/numeric_test.xlsx', index=False) + diff --git a/tests/run_tests.bat b/tests/run_tests.bat index b40473d2..d8bea01f 100644 --- a/tests/run_tests.bat +++ b/tests/run_tests.bat @@ -97,5 +97,6 @@ pause + diff --git a/tests/run_tests.sh b/tests/run_tests.sh index 9b5fee86..b273226a 100644 --- a/tests/run_tests.sh +++ b/tests/run_tests.sh @@ -93,5 +93,6 @@ echo "========================================" + diff --git a/快速部署到SAE.md b/快速部署到SAE.md index e0a34f5b..304bfab1 100644 --- a/快速部署到SAE.md +++ b/快速部署到SAE.md @@ -358,5 +358,6 @@ OSS AccessKeySecret:_______________ + diff --git a/部署检查清单.md b/部署检查清单.md index 3246e35f..26a6b21f 100644 --- a/部署检查清单.md +++ b/部署检查清单.md @@ -394,5 +394,6 @@ OSS配置: +