{"repo": "castlecry/teka", "files": {"database_init.sql": {"e17337723a0e6516350f703e0202a31a3c33b80f": {"t": 1785746545.0112488, "n": 14720, "h": "e0795ad6b83039f0", "c": "-- ============================================================\n-- 智汇办公 AI 智能平台 - 数据库初始化脚本\n-- 数据库类型: PostgreSQL\n-- 包含: 建表语句 + 示例数据\n-- ============================================================\n\n-- ============================================================\n-- 第一部分: 建表语句\n-- ============================================================\n\n-- 角色表\nCREATE TABLE IF NOT EXISTS roles (\n id SERIAL PRIMARY KEY,\n name VARCHAR(50) NOT NULL UNIQUE,\n description TEXT,\n permissions JSONB DEFAULT '[]'::jsonb,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 用户表\nCREATE TABLE IF NOT EXISTS users (\n id SERIAL PRIMARY KEY,\n username VARCHAR(50) NOT NULL UNIQUE,\n email VARCHAR(100) NOT NULL UNIQUE,\n password_hash VARCHAR(255) NOT NULL,\n full_name VARCHAR(100),\n department VARCHAR(50),\n role_id INTEGER REFERENCES roles(id),\n status BOOLEAN DEFAULT TRUE,\n avatar VARCHAR(500),\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 知识库表\nCREATE TABLE IF NOT EXISTS knowledge_bases (\n id SERIAL PRIMARY KEY,\n name VARCHAR(100) NOT NULL,\n description TEXT,\n department VARCHAR(50),\n owner_id INTEGER REFERENCES users(id),\n embedding_model VARCHAR(100) DEFAULT 'qwen3-embedding:0.6b',\n is_personal BOOLEAN DEFAULT FALSE,\n module VARCHAR(50) DEFAULT 'general',\n is_shared BOOLEAN DEFAULT FALSE,\n is_locked BOOLEAN DEFAULT FALSE,\n status BOOLEAN DEFAULT TRUE,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 文档表\nCREATE TYPE document_status AS ENUM ('pending', 'processing', 'completed', 'failed', 'rejected', 'pending_review');\n\nCREATE TABLE IF NOT EXISTS documents (\n id SERIAL PRIMARY KEY,\n knowledge_base_id INTEGER REFERENCES knowledge_bases(id),\n filename VARCHAR(255) NOT NULL,\n file_path VARCHAR(500),\n file_type VARCHAR(50),\n size INTEGER,\n chunk_count INTEGER DEFAULT 0,\n status document_status DEFAULT 'pending',\n uploaded_by INTEGER REFERENCES users(id),\n uploaded_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n audit_id INTEGER,\n audit_status VARCHAR(20) DEFAULT 'pending',\n rejection_reason TEXT\n);\n\n-- 内容审核日志表\nCREATE TABLE IF NOT EXISTS content_audit_logs (\n id SERIAL PRIMARY KEY,\n document_id INTEGER REFERENCES documents(id),\n filename VARCHAR(300) NOT NULL,\n knowledge_base_id INTEGER REFERENCES knowledge_bases(id),\n user_id INTEGER NOT NULL REFERENCES users(id),\n verdict VARCHAR(20) NOT NULL, -- PASS / REVIEW / BLOCK\n confidence REAL DEFAULT 0.5,\n categories JSONB DEFAULT '[]'::jsonb,\n reasons JSONB DEFAULT '[]'::jsonb,\n summary TEXT,\n raw_result TEXT,\n status VARCHAR(20) DEFAULT 'pending',\n reviewer_id INTEGER REFERENCES users(id),\n reviewer_comment TEXT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n reviewed_at TIMESTAMP\n);\n\n-- 对话记录表\nCREATE TABLE IF NOT EXISTS conversation_logs (\n id SERIAL PRIMARY KEY,\n conversation_id VARCHAR(50),\n user_id INTEGER REFERENCES users(id),\n query TEXT,\n answer TEXT,\n sources JSONB DEFAULT '[]'::jsonb,\n knowledge_base_ids JSONB DEFAULT '[]'::jsonb,\n module VARCHAR(50) DEFAULT 'general',\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 系统配置表\nCREATE TABLE IF NOT EXISTS system_config (\n id SERIAL PRIMARY KEY,\n key VARCHAR(100) NOT NULL UNIQUE,\n value TEXT,\n description TEXT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP,\n updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 用户反馈表\nCREATE TABLE IF NOT EXISTS feedback (\n id SERIAL PRIMARY KEY,\n conversation_id VARCHAR(50),\n message_id VARCHAR(50),\n user_id INTEGER REFERENCES users(id),\n rating INTEGER,\n correction TEXT,\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 对话收藏表\nCREATE TABLE IF NOT EXISTS conversation_favorites (\n id SERIAL PRIMARY KEY,\n conversation_id VARCHAR(50) NOT NULL,\n message_id VARCHAR(100),\n user_id INTEGER NOT NULL REFERENCES users(id),\n title VARCHAR(200),\n query TEXT,\n answer TEXT,\n module VARCHAR(50) DEFAULT 'general',\n created_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP\n);\n\n-- 索引\nCREATE INDEX IF NOT EXISTS idx_users_username ON users(username);\nCREATE INDEX IF NOT EXISTS idx_users_email ON users(email);\nCREATE INDEX IF NOT EXISTS idx_users_role_id ON users(role_id);\nCREATE INDEX IF NOT EXISTS idx_knowledge_bases_owner_id ON knowledge_bases(owner_id);\nCREATE INDEX IF NOT EXISTS idx_knowledge_bases_module ON knowledge_bases(module);\nCREATE INDEX IF NOT EXISTS idx_documents_kb_id ON documents(knowledge_base_id);\nCREATE INDEX IF NOT EXISTS idx_documents_uploaded_by ON documents(uploaded_by);\nCREATE INDEX IF NOT EXISTS idx_conversation_logs_user_id ON conversation_logs(user_id);\nCREATE INDEX IF NOT EXISTS idx_conversation_logs_conv_id ON conversation_logs(conversation_id);\nCREATE INDEX IF NOT EXISTS idx_conversation_logs_module ON conversation_logs(module);\nCREATE INDEX IF NOT EXISTS idx_content_audit_user_id ON content_audit_logs(user_id);\nCREATE INDEX IF NOT EXISTS idx_content_audit_verdict ON content_audit_logs(verdict);\nCREATE INDEX IF NOT EXISTS idx_feedback_user_id ON feedback(user_id);\nCREATE INDEX IF NOT EXISTS idx_favorites_user_id ON conversation_favorites(user_id);\n\n-- ============================================================\n-- 第二部分: 示例数据\n-- ============================================================\n\n-- 角色数据\nINSERT INTO roles (name, description, permissions) VALUES\n ('admin', '管理员,拥有全部权限', '[\"user.create\",\"user.read\",\"user.update\",\"user.delete\",\"kb.create\",\"kb.read\",\"kb.update\",\"kb.delete\",\"doc.upload\",\"doc.delete\",\"audit.review\",\"config.manage\",\"feedback.read\"]'::jsonb),\n ('user', '普通用户,基础使用权限', '[\"user.read\",\"kb.read\",\"doc.upload\",\"feedback.create\",\"feedback.read\"]'::jsonb);\n\n-- 用户数据(密码均为 bcrypt 加密,明文为 \"123456\")\nINSERT INTO users (username, email, password_hash, full_name, department, role_id, status) VALUES\n ('admin', 'admin@company.com', '$2b$12$LJ3m4ys3Lk0pKZxKxKxKxOqJ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5', '系统管理员', '技术部', 1, TRUE),\n ('zhangsan', 'zhangsan@company.com', '$2b$12$LJ3m4ys3Lk0pKZxKxKxKxOqJ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5', '张三', '人力资源部', 2, TRUE),\n ('lisi', 'lisi@company.com', '$2b$12$LJ3m4ys3Lk0pKZxKxKxKxOqJ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5', '李四', '财务部', 2, TRUE),\n ('wangwu', 'wangwu@company.com', '$2b$12$LJ3m4ys3Lk0pKZxKxKxKxOqJ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5', '王五', '技术部', 2, TRUE),\n ('zhaoliu', 'zhaoliu@company.com', '$2b$12$LJ3m4ys3Lk0pKZxKxKxKxOqJ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5qZ5', '赵六', '行政部', 2, FALSE);\n\n-- 知识库数据\nINSERT INTO knowledge_bases (name, description, department, owner_id, is_personal, module, is_shared, is_locked) VALUES\n ('规章制度', '公司规章制度,包含考勤、薪酬、绩效、请假等制度文件', NULL, 1, FALSE, 'policy', TRUE, TRUE),\n ('产品技术', '产品技术文档,包含API文档、架构说明、运维手册等', NULL, 1, FALSE, 'tech', TRUE, TRUE),\n ('行政服务', '行政服务指南,包含场地预约、IT设备、员工福利等', NULL, 1, FALSE, 'admin', TRUE, TRUE),\n ('通用知识库', '通用知识问答库', NULL, 1, FALSE, 'general', TRUE, FALSE),\n ('张三的个人笔记', '张三个人整理的学习笔记', '人力资源部', 2, TRUE, 'general', FALSE, FALSE),\n ('李四的财务备忘', '李四个人的财务工作备忘', '财务部', 3, TRUE, 'general', FALSE, FALSE);\n\n-- 文档数据\nINSERT INTO documents (knowledge_base_id, filename, file_path, file_type, size, chunk_count, status, uploaded_by, audit_status) VALUES\n (1, '员工手册.pdf', '/uploads/employee_handbook.pdf', 'pdf', 2048576, 120, 'completed', 1, 'passed'),\n (1, '考勤管理制度.docx', '/uploads/attendance_policy.docx', 'docx', 524288, 35, 'completed', 1, 'passed'),\n (1, '薪酬福利制度.pdf', '/uploads/compensation_policy.pdf', 'pdf', 1048576, 60, 'completed', 1, 'passed'),\n (2, 'API接口文档.pdf', '/uploads/api_docs.pdf', 'pdf', 3145728, 200, 'completed', 1, 'passed'),\n (2, '系统架构说明.docx', '/uploads/architecture.docx', 'docx', 1572864, 80, 'completed', 1, 'passed'),\n (3, '场地预约指南.pdf', '/uploads/venue_guide.pdf', 'pdf', 786432, 25, 'completed', 1, 'passed'),\n (3, 'IT设备申领流程.docx', '/uploads/it_equipment.docx', 'docx', 262144, 15, 'completed', 1, 'passed'),\n (4, '公司简介.pdf', '/uploads/company_intro.pdf', 'pdf', 524288, 30, 'completed', 1, 'passed'),\n (5, 'Python学习笔记.pdf', '/uploads/python_notes.pdf', 'pdf', 1048576, 50, 'completed', 2, 'passed'),\n (1, '违规文档.docx', '/uploads/violation.docx', 'docx', 102400, 0, 'rejected', 2, 'rejected');\n\n-- 内容审核日志数据\nINSERT INTO content_audit_logs (document_id, filename, knowledge_base_id, user_id, verdict, confidence, categories, reasons, summary, status) VALUES\n (1, '员工手册.pdf', 1, 1, 'PASS', 0.85, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (2, '考勤管理制度.docx', 1, 1, 'PASS', 0.90, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (3, '薪酬福利制度.pdf', 1, 1, 'PASS', 0.88, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (4, 'API接口文档.pdf', 2, 1, 'PASS', 0.92, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (5, '系统架构说明.docx', 2, 1, 'PASS', 0.87, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (6, '场地预约指南.pdf', 3, 1, 'PASS', 0.91, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (7, 'IT设备申领流程.docx', 3, 1, 'PASS', 0.89, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (8, '公司简介.pdf', 4, 1, 'PASS', 0.93, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (9, 'Python学习笔记.pdf', 5, 2, 'PASS', 0.86, '[]'::jsonb, '[]'::jsonb, '文档内容合规,未发现敏感信息', 'auto_processed'),\n (10, '违规文档.docx', 1, 2, 'BLOCK', 0.95, '[\"商业机密\",\"个人隐私\"]'::jsonb, '[\"包含公司内部源代码\",\"包含员工身份证号\"]'::jsonb, '文档包含商业机密和个人隐私信息,已被拒绝', 'auto_processed');\n\n-- 对话记录数据\nINSERT INTO conversation_logs (conversation_id, user_id, query, answer, sources, knowledge_base_ids, module) VALUES\n ('conv-001', 2, '公司年假有多少天?', '根据公司《员工手册》规定:\n\n- 工作满1年不满10年:5天年假\n- 工作满10年不满20年:10天年假\n- 工作满20年以上:15天年假\n\n年假需在当年使用完毕,特殊情况可申请跨年度使用。', '[{\"title\":\"员工手册.pdf\",\"page\":15,\"snippet\":\"年假天数根据工龄计算...\"}]'::jsonb, '[1]'::jsonb, 'policy'),\n ('conv-001', 2, '怎么申请年假?', '年假申请流程如下:\n\n1. 登录OA系统,进入\"请假申请\"模块\n2. 选择\"年假\"类型,填写起止日期\n3. 提交后由直属领导审批\n4. 审批通过后自动同步到考勤系统\n\n注意:需提前3个工作日申请。', '[{\"title\":\"员工手册.pdf\",\"page\":16,\"snippet\":\"年假申请需提前3个工作日...\"}]'::jsonb, '[1]'::jsonb, 'policy'),\n ('conv-002', 3, '报销流程是什么?', '报销流程如下:\n\n1. 收集发票和消费凭证\n2. 填写报销单(OA系统-财务模块)\n3. 直属领导审批\n4. 财务部审核\n5. 每月15日和30日统一打款\n\n报销时限:消费发生后30天内。', '[{\"title\":\"员工手册.pdf\",\"page\":28,\"snippet\":\"报销流程及注意事项...\"}]'::jsonb, '[1]'::jsonb, 'policy'),\n ('conv-003', 4, 'API认证方式是什么?', '我们的API采用JWT Token认证方式:\n\n1. 调用 /api/auth/login 获取Token\n2. 在请求头中添加 Authorization: Bearer \n3. Token有效期30分钟,过期需重新登录\n\n详细文档请参考《API接口文档》第3章。', '[{\"title\":\"API接口文档.pdf\",\"page\":12,\"snippet\":\"JWT认证机制说明...\"}]'::jsonb, '[2]'::jsonb, 'tech'),\n ('conv-004', 2, '今天天气怎么样?', '抱歉,我无法直接获取天气信息。但我可以帮您搜索一下。\n\n根据搜索结果,今天北京天气:晴转多云,气温18℃~28℃,空气质量良好。适合户外活动。', '[]'::jsonb, '[4]'::jsonb, 'general'),\n ('conv-005', 3, '帮我写一份会议纪要模板', '以下是一份标准的会议纪要模板:\n\n---\n# 会议纪要\n\n**会议主题:**\n**会议时间:**\n**会议地点:**\n**参会人员:**\n**记录人:**\n\n## 会议议程\n1.\n2.\n\n## 讨论内容\n...\n\n## 决议事项\n| 序号 | 事项 | 负责人 | 完成时间 |\n|------|------|--------|----------|\n\n---\n\n需要我帮您生成Word文档吗?', '[]'::jsonb, '[4]'::jsonb, 'general');\n\n-- 系统配置数据\nINSERT INTO system_config (key, value, description) VALUES\n ('llm_model', 'deepseek-chat', '默认使用的LLM模型'),\n ('llm_api_base', 'https://api.deepseek.com/v1', 'LLM API地址'),\n ('llm_api_key', 'sk-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'LLM API密钥(已脱敏)'),\n ('embedding_model', 'qwen3-embedding:0.6b', '向量嵌入模型'),\n ('opensearch_host', 'http://localhost:9200', 'OpenSearch地址'),\n ('redis_host', 'localhost', 'Redis地址'),\n ('redis_port', '6379', 'Redis端口'),\n ('jwt_secret_key', 'your-secret-key-change-in-production', 'JWT签名密钥'),\n ('jwt_algorithm', 'HS256', 'JWT签名算法'),\n ('jwt_expire_minutes', '30', 'JWT Token有效期(分钟)'),\n ('chunk_size', '500', '文本切片大小'),\n ('chunk_overlap', '50', '文本切片重叠大小'),\n ('top_k', '5', 'RAG检索返回的文档数量'),\n ('rerank_model', 'bge-reranker-v2-m3', 'Rerank精排模型'),\n ('max_iterations', '10', 'LangGraph最大迭代次数'),\n ('content_moderation_enabled', 'true', '是否启用内容审核'),\n ('web_search_enabled', 'true', '是否启用联网搜索'),\n ('tavily_api_key', 'tvly-xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx', 'Tavily搜索API密钥(已脱敏)');\n\n-- 用户反馈数据\nINSERT INTO feedback (conversation_id, message_id, user_id, rating, correction) VALUES\n ('conv-001', 'msg-001', 2, 5, NULL),\n ('conv-001', 'msg-002', 2, 5, NULL),\n ('conv-002', 'msg-003', 3, 4, '报销时限应该是60天而不是30天'),\n ('conv-003', 'msg-004', 4, 5, NULL),\n ('conv-004', 'msg-005', 2, 3, '天气信息不够准确,建议接入实时天气API'),\n ('conv-005', 'msg-006', 3, 5, '会议纪要模板很实用');\n\n-- 对话收藏数据\nINSERT INTO conversation_favorites (conversation_id, message_id, user_id, title, query, answer, module) VALUES\n ('conv-001', 'msg-001', 2, '年假天数查询', '公司年假有多少天?', '根据公司《员工手册》规定:工作满1年不满10年5天,满10年不满20年10天,满20年以上15天。', 'policy'),\n ('conv-003', 'msg-004', 4, 'API认证方式', 'API认证方式是什么?', 'API采用JWT Token认证,调用/login获取Token,有效期30分钟。', 'tech'),\n ('conv-005', 'msg-006', 3, '会议纪要模板', '帮我写一份会议纪要模板', '标准会议纪要模板,包含会议主题、时间、地点、参会人员、议程、讨论内容、决议事项等。', 'general');\n\n-- ============================================================\n-- 第三部分: 常用查询示例\n-- ============================================================\n\n-- 查询所有知识库及其文档数量\n-- SELECT kb.name, kb.module, COUNT(d.id) AS doc_count\n-- FROM knowledge_bases kb\n-- LEFT JOIN documents d ON kb.id = d.knowledge_base_id AND d.status = 'completed'\n-- GROUP BY kb.id;\n\n-- 查询用户的对话记录\n-- SELECT cl.query, cl.answer, cl.module, cl.created_at\n-- FROM conversation_logs cl\n-- WHERE cl.user_id = 2\n-- ORDER BY cl.created_at DESC;\n\n-- 查询审核被拒绝的文档\n-- SELECT d.filename, d.rejection_reason, cal.verdict, cal.confidence, cal.reasons\n-- FROM documents d\n-- JOIN content_audit_logs cal ON d.audit_id = cal.id\n-- WHERE cal.verdict = 'BLOCK';\n\n-- 查询各模块的对话统计\n-- SELECT module, COUNT(*) AS total_queries, AVG(LENGTH(answer)) AS avg_answer_length\n-- FROM conversation_logs\n-- GROUP BY module;\n\n-- 查询用户收藏的对话\n-- SELECT cf.title, cf.query, cf.module, cf.created_at\n-- FROM conversation_favorites cf\n-- WHERE cf.user_id = 2\n-- ORDER BY cf.created_at DESC;"}}, "backend/.env.example": {"e17337723a0e6516350f703e0202a31a3c33b80f": {"t": 1785746736.7755864, "n": 890, "h": "7d7d03c3a7e1a441", "c": "# LLM 配置\nLLM_MODE=local\nOLLAMA_MODEL=qwen3.5:9b\nOLLAMA_BASE_URL=http://localhost:11434\n\n# DeepSeek API 配置\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_BASE_URL=https://api.deepseek.com\n\n# JWT 密钥\nJWT_SECRET_KEY=your-jwt-secret-key-change-in-production\n\n# Embedding 模型\nEMBED_MODEL=qwen3-embedding:0.6b\n\n# PostgreSQL 配置\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_DB=rag_db\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=MyPassword123!\n\n# OpenSearch 配置\nOPENSEARCH_HOST=https://localhost:9200\nOPENSEARCH_USER=admin\nOPENSEARCH_PASSWORD=MyPassword123!\n\n# Redis 配置\nREDIS_HOST=localhost\nREDIS_PORT=6379\n\n# SearXNG 配置\nSEARXNG_HOST=http://localhost:18080\nSEARXNG_SECRET=your-random-secret-key-change-this\n\n# MinerU API 配置\nMINERU_HOST=http://127.0.0.1:8000\n\n# 文本切片配置\nCHUNK_SIZE=500\nCHUNK_OVERLAP=100\n\n# 检索配置\nTOP_K=5\nWEB_SEARCH_COUNT=3\n\n# 对话历史\nHISTORY_TURNS=10\n\n# LLM 推理超时(秒)\nLLM_TIMEOUT=600\n"}, "aa39b74bc6403d764d5d18f91ae97cbdb35dbb66": {"t": 1785765494.9310665, "n": 890, "h": "7d7d03c3a7e1a441", "c": "# LLM 配置\nLLM_MODE=local\nOLLAMA_MODEL=qwen3.5:9b\nOLLAMA_BASE_URL=http://localhost:11434\n\n# DeepSeek API 配置\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_BASE_URL=https://api.deepseek.com\n\n# JWT 密钥\nJWT_SECRET_KEY=your-jwt-secret-key-change-in-production\n\n# Embedding 模型\nEMBED_MODEL=qwen3-embedding:0.6b\n\n# PostgreSQL 配置\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_DB=rag_db\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=MyPassword123!\n\n# OpenSearch 配置\nOPENSEARCH_HOST=https://localhost:9200\nOPENSEARCH_USER=admin\nOPENSEARCH_PASSWORD=MyPassword123!\n\n# Redis 配置\nREDIS_HOST=localhost\nREDIS_PORT=6379\n\n# SearXNG 配置\nSEARXNG_HOST=http://localhost:18080\nSEARXNG_SECRET=your-random-secret-key-change-this\n\n# MinerU API 配置\nMINERU_HOST=http://127.0.0.1:8000\n\n# 文本切片配置\nCHUNK_SIZE=500\nCHUNK_OVERLAP=100\n\n# 检索配置\nTOP_K=5\nWEB_SEARCH_COUNT=3\n\n# 对话历史\nHISTORY_TURNS=10\n\n# LLM 推理超时(秒)\nLLM_TIMEOUT=600\n"}, "2facdc1348d3e8f5a5b339a72dee42436cce2da1": {"t": 1785765496.2861958, "n": 888, "h": "b89d2f07e4a8f845", "c": "# LLM 配置\nLLM_MODE=local\nOLLAMA_MODEL=qwen3.5:9b\nOLLAMA_BASE_URL=http://localhost:11434\n\n# DeepSeek API 配置\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_BASE_URL=https://api.deepseek.com\n\n# JWT 密钥\nJWT_SECRET_KEY=your-jwt-secret-key-change-in-production\n\n# Embedding 模型\nEMBED_MODEL=qwen3-embedding:4b\n\n# PostgreSQL 配置\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_DB=rag_db\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=MyPassword123!\n\n# OpenSearch 配置\nOPENSEARCH_HOST=https://localhost:9200\nOPENSEARCH_USER=admin\nOPENSEARCH_PASSWORD=MyPassword123!\n\n# Redis 配置\nREDIS_HOST=localhost\nREDIS_PORT=6379\n\n# SearXNG 配置\nSEARXNG_HOST=http://localhost:18080\nSEARXNG_SECRET=your-random-secret-key-change-this\n\n# MinerU API 配置\nMINERU_HOST=http://127.0.0.1:8000\n\n# 文本切片配置\nCHUNK_SIZE=500\nCHUNK_OVERLAP=100\n\n# 检索配置\nTOP_K=5\nWEB_SEARCH_COUNT=3\n\n# 对话历史\nHISTORY_TURNS=10\n\n# LLM 推理超时(秒)\nLLM_TIMEOUT=600\n"}, "d444073f37ba283a997bb4c308a8176880a92f5d": {"t": 1785765497.590361, "n": 896, "h": "2af842898f2da630", "c": "# LLM 配置\nLLM_MODE=local\nOLLAMA_MODEL=qwen3.5:9b\nOLLAMA_BASE_URL=http://localhost:11434\n\n# DeepSeek API 配置\nDEEPSEEK_API_KEY=your-deepseek-api-key-here\nDEEPSEEK_BASE_URL=https://api.deepseek.com\n\n# JWT 密钥\nJWT_SECRET_KEY=your-jwt-secret-key-change-in-production\n\n# Embedding 模型\nEMBEDDING_MODEL=BAAI/bge-small-zh-v1.5\n\n# PostgreSQL 配置\nPOSTGRES_HOST=localhost\nPOSTGRES_PORT=5432\nPOSTGRES_DB=rag_db\nPOSTGRES_USER=postgres\nPOSTGRES_PASSWORD=MyPassword123!\n\n# OpenSearch 配置\nOPENSEARCH_HOST=https://localhost:9200\nOPENSEARCH_USER=admin\nOPENSEARCH_PASSWORD=MyPassword123!\n\n# Redis 配置\nREDIS_HOST=localhost\nREDIS_PORT=6379\n\n# SearXNG 配置\nSEARXNG_HOST=http://localhost:18080\nSEARXNG_SECRET=your-random-secret-key-change-this\n\n# MinerU API 配置\nMINERU_HOST=http://127.0.0.1:8000\n\n# 文本切片配置\nCHUNK_SIZE=500\nCHUNK_OVERLAP=100\n\n# 检索配置\nTOP_K=5\nWEB_SEARCH_COUNT=3\n\n# 对话历史\nHISTORY_TURNS=10\n\n# LLM 推理超时(秒)\nLLM_TIMEOUT=600\n"}}, "backend/docker-compose.yml": {"e17337723a0e6516350f703e0202a31a3c33b80f": {"t": 1786068533.1997807, "n": 3031, "h": "f77c7b73a8e4a329", "c": "version: '3.8'\n\nservices:\n postgres:\n image: pgvector/pgvector:pg17\n container_name: pg-vector\n environment:\n - POSTGRES_PASSWORD=MyPassword123!\n - POSTGRES_DB=rag_db\n - POSTGRES_USER=postgres\n ports:\n - \"5432:5432\"\n volumes:\n - postgres-data:/var/lib/postgresql/data\n networks:\n - rag-network\n healthcheck:\n test: [\"CMD-SHELL\", \"pg_isready -U postgres -d rag_db\"]\n interval: 10s\n timeout: 5s\n retries: 3\n\n opensearch:\n image: opensearchproject/opensearch:2.15.0\n container_name: opensearch\n environment:\n - discovery.type=single-node\n - plugins.security.disabled=true\n - OPENSEARCH_JAVA_OPTS=-Xms512m -Xmx512m\n ports:\n - \"9200:9200\"\n - \"9600:9600\"\n volumes:\n - opensearch-data:/usr/share/opensearch/data\n networks:\n - rag-network\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:9200/_cluster/health\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n redis:\n image: redis:7-alpine\n container_name: redis\n ports:\n - \"6379:6379\"\n volumes:\n - redis-data:/data\n networks:\n - rag-network\n healthcheck:\n test: [\"CMD\", \"redis-cli\", \"ping\"]\n interval: 10s\n timeout: 5s\n retries: 3\n\n searxng:\n image: searxng/searxng:latest\n container_name: searxng\n ports:\n - \"18080:8080\"\n volumes:\n - ./searxng-settings.yml:/etc/searxng/settings.yml:ro\n - searxng-data:/etc/searxng\n - searxng-log:/var/log/searxng\n networks:\n - rag-network\n healthcheck:\n test: [\"CMD\", \"curl\", \"-f\", \"http://localhost:8080/\"]\n interval: 30s\n timeout: 10s\n retries: 3\n\n rag-app:\n build: .\n container_name: rag-app\n ports:\n - \"8888:8888\"\n environment:\n - POSTGRES_HOST=postgres\n - POSTGRES_PORT=5432\n - POSTGRES_DB=rag_db\n - POSTGRES_USER=postgres\n - POSTGRES_PASSWORD=MyPassword123!\n - OPENSEARCH_HOST=http://opensearch:9200\n - OPENSEARCH_USER=admin\n - OPENSEARCH_PASSWORD=\n - OLLAMA_HOST=http://host.docker.internal:11434\n - DEEPSEEK_API_KEY=your-deepseek-api-key\n - DEEPSEEK_BASE_URL=https://api.deepseek.com\n - SEARXNG_HOST=http://searxng:8080\n - SEARXNG_SECRET=your-random-secret-key-change-this\n - MINERU_HOST=http://host.docker.internal:8000\n - REDIS_HOST=redis\n - REDIS_PORT=6379\n volumes:\n - ./knowledge_base:/app/knowledge_base\n - ./uploads:/app/uploads\n extra_hosts:\n - \"host.docker.internal:host-gateway\"\n depends_on:\n postgres:\n condition: service_healthy\n opensearch:\n condition: service_healthy\n redis:\n condition: service_healthy\n searxng:\n condition: service_healthy\n networks:\n - rag-network\n command: [\"uvicorn\", \"main:app\", \"--host\", \"0.0.0.0\", \"--port\", \"8888\"]\n\nvolumes:\n postgres-data:\n opensearch-data:\n redis-data:\n searxng-data:\n searxng-log:\n\nnetworks:\n rag-network:\n driver: bridge\n"}}}}