# langgraph-studio **Repository Path**: cy2015/langgraph-studio ## Basic Information - **Project Name**: langgraph-studio - **Description**: No description available - **Primary Language**: Unknown - **License**: MIT - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 1 - **Created**: 2025-11-11 - **Last Updated**: 2025-11-11 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # React Agent 文件管理系统 ## 📖 项目概述 本项目是一个基于 FastAPI 的文件管理系统,集成了 PostgreSQL 数据库用于文件记录管理。支持普通文件上传和分片上传,每个上传的文件都会在数据库中生成唯一的文件ID。 ## 🚀 功能特性 ### 📁 文件管理功能 - ✅ 单文件上传,返回文件ID - ✅ 分片上传(支持大文件),返回文件ID - ✅ 文件列表查询(从数据库查询) - ✅ 根据文件ID或文件名下载文件 - ✅ 根据文件ID或文件名删除文件 - ✅ 文件信息查询(根据文件ID) ### 🤖 智能问答功能 - ✅ PDF文档问答(集成远程OCR接口) - ✅ Word文档问答(支持.docx和.doc格式) - ✅ Excel文档问答(支持.xlsx和.xls格式,提取所有工作表) - ✅ CSV文档问答(自动检测编码) - ✅ TXT文档问答(自动检测编码) - ✅ 压缩包问答(支持.zip、.tar、.tar.gz,自动解压递归处理) - ✅ 智能分块处理(根据文档大小自适应分块策略) - ✅ 并行问答处理(提高处理效率) - ✅ 结果智能汇总(整合多个分块的分析结果) ### 🗄️ 数据库集成 - ✅ PostgreSQL 数据库存储文件元数据 - ✅ 文件记录表 (`file_records`) 包含: - `file_id`: 文件唯一标识符 (UUID) - `user_id`: 上传用户ID - `original_filename`: 原始文件名 - `stored_filename`: 存储文件名 - `file_path`: 文件完整路径 - `file_size`: 文件大小(字节) - `content_type`: 文件MIME类型 - `is_multipart`: 是否为分片上传 - `upload_id`: 分片上传ID - `uploaded_at`: 上传时间 - `updated_at`: 更新时间 - `metadata`: 扩展元数据(JSON) ## 🏗️ 系统架构 ``` src/ ├── webapp/ │ ├── database.py # 数据库连接和配置 │ ├── models.py # 数据库模型定义 │ ├── file_manager.py # 文件管理核心逻辑 │ ├── routes/ │ │ └── file_routes.py # 文件API路由 │ └── webapp.py # FastAPI应用入口 └── react_agent/ # LangGraph智能体 ``` ## 📋 API 接口 ### 基础文件操作 #### 上传文件 ```http POST /files/{user_id}/upload Content-Type: multipart/form-data Body: file (文件) ``` **响应示例:** ```json { "file_id": "123e4567-e89b-12d3-a456-426614174000", "filename": "example.pdf", "message": "上传成功", "full_path": "/path/to/file" } ``` #### 文件列表 ```http GET /files/{user_id}/list ``` **响应示例:** ```json [ { "file_id": "123e4567-e89b-12d3-a456-426614174000", "user_id": "user123", "original_filename": "document.pdf", "stored_filename": "document.pdf", "file_path": "/path/to/file", "file_size": 1024000, "content_type": "application/pdf", "is_multipart": false, "upload_id": null, "uploaded_at": "2024-01-01T12:00:00", "updated_at": "2024-01-01T12:00:00", "metadata": null } ] ``` #### 文件下载 ```http # 根据用户ID和文件名 GET /files/{user_id}/{filename}/download # 根据文件ID GET /files/download/{file_id} ``` #### 文件删除 ```http # 根据用户ID和文件名 DELETE /files/{user_id}/{filename} # 根据文件ID DELETE /files/delete/{file_id} ``` #### 文件信息查询 ```http GET /files/info/{file_id} ``` ### 分片上传 #### 1. 初始化分片上传 ```http POST /files/{user_id}/multipart/initiate ``` #### 2. 上传分片 ```http PUT /files/{user_id}/multipart/{upload_id}/part?part_number=1 Content-Type: multipart/form-data Body: chunk (分片文件,<1MB) ``` #### 3. 完成分片上传 ```http POST /files/{user_id}/multipart/{upload_id}/complete Content-Type: application/json { "filename": "large_file.zip", "total_parts": 10, "content_type": "application/zip" } ``` ## 🗄️ 数据库配置 ### 环境变量 - `POSTGRES_URI`: PostgreSQL连接字符串 - 默认值: `postgresql://root:root@localhost:5433/postgres` ### Docker 配置 项目使用 Docker Compose 运行 PostgreSQL: ```yaml # docker-compose.yml services: langgraph-postgres: image: postgres:16 ports: - "5433:5432" environment: POSTGRES_DB: postgres POSTGRES_USER: root POSTGRES_PASSWORD: root ``` ## 🚀 快速开始 ### 1. 安装依赖 ```bash pip install -r requirements.txt # 或使用项目配置文件 pip install -e . ``` ### 2. 启动数据库 ```bash docker-compose up -d langgraph-postgres ``` ### 3. 运行应用 ```bash uvicorn src.webapp.webapp:app --reload --port 8000 ``` ### 4. 测试API 访问 `http://localhost:8000/docs` 查看 Swagger 文档 ## 🔧 开发注意事项 ### 数据库操作 - 所有数据库操作都使用事务确保数据一致性 - 文件删除时会同时删除物理文件和数据库记录 - 上传失败时会回滚数据库操作并清理文件 ### 错误处理 - 数据库连接失败时会记录日志但不会终止应用 - 文件操作失败时会返回详细的错误信息 - 分片上传失败时会自动清理临时文件 ### 安全考虑 - 文件名进行安全处理,防止目录遍历攻击 - 用户文件按用户ID隔离存储 - 分片上传使用唯一的upload_id防止冲突 ## 📈 未来扩展 - [ ] 文件版本控制 - [ ] 文件标签和分类 - [ ] 文件搜索功能 - [ ] 文件预览功能 - [ ] 批量操作API - [ ] 文件访问权限控制 - [ ] 文件统计和监控 ## 🤝 贡献指南 1. Fork 项目 2. 创建功能分支 3. 提交代码变更 4. 创建 Pull Request ## 📄 许可证 MIT License ## CRM跟进记录提交工具调用示例 ### ⚠️ 重要提醒 **绝对禁止硬编码任何参数值!所有编码(fu_way、fu_target、relevance_type等)都是动态的,必须通过工具实时获取!** ### submit_follow_record 工具标准使用流程 #### 第一步:获取所有必需的动态数据 ```python # 1. 获取关联类型选项(绝对不能假设"1"是客户) association_types = get_association_type_list("") # 2. 获取跟进方式选项(绝对不能假设"1"是电话) follow_methods = get_follow_method_list("") # 3. 获取跟进目标选项(绝对不能假设"1"是了解需求) follow_targets = get_association_target_list("") # 4. 获取签到信息(必须执行,不能跳过) checkin_info = get_checkin_list("") # 5. 获取联系人信息 contact_info = get_contact_list("联系人姓名") # 6. 根据需要获取客户信息 customer_info = get_customer_list("客户名称") ``` #### 第二步:从响应中提取实际的enCode值 ```python # 从API响应中提取实际的编码值 # 注意:这些编码会变化,绝对不能硬编码 customer_relation_code = association_types['data'][0]['enCode'] # 假设选择客户关联 phone_method_code = follow_methods['data'][0]['enCode'] # 假设选择电话沟通 requirement_target_code = follow_targets['data'][0]['enCode'] # 假设选择了解需求 # 提取IDs contact_id = contact_info['data']['list'][0]['f_id'] customer_id = customer_info['data']['list'][0]['f_id'] # 提取签到信息(如果有的话) checkin_id = checkin_info['data']['list'][0]['f_id'] if checkin_info['data']['list'] else "" ``` #### 第三步:提交跟进记录 ```python # 使用动态获取的真实编码值提交跟进记录 result = submit_follow_record( contact_id=contact_id, # 从联系人查询获得 fu_content="电话沟通了AI agent开发需求", # 跟进内容 fu_way=phone_method_code, # 从工具获得的跟进方式编码 fu_target=requirement_target_code, # 从工具获得的跟进目标编码 relevance_type=customer_relation_code, # 从工具获得的关联类型编码 customer_id=customer_id, # 从客户查询获得 clue_id="", # 关联线索时使用 fu_sign_id=checkin_id # 从签到查询获得 ) ``` ### ❌ 错误示例(绝对禁止) ```python # 错误!绝对不能这样硬编码 submit_follow_record( contact_id="xxx", fu_content="跟进内容", fu_way="1", # ❌ 硬编码,禁止! fu_target="1", # ❌ 硬编码,禁止! relevance_type="1" # ❌ 硬编码,禁止! ) ``` ### 参数说明 #### 动态必填参数(必须通过工具获取) - `contact_id`: 联系人ID,通过 `get_contact_list()` 工具查询获得 - `fu_content`: 跟进内容,描述本次跟进的具体情况 - `fu_way`: 跟进方式编码,**必须**通过 `get_follow_method_list("")` 工具查询获得enCode值 - `fu_target`: 跟进目标编码,**必须**通过 `get_association_target_list("")` 工具查询获得enCode值 - `relevance_type`: 关联类型编码,**必须**通过 `get_association_type_list("")` 工具查询获得enCode值 #### 条件必填参数 - `customer_id`: 客户ID,当关联类型为客户时必填,通过 `get_customer_list()` 工具查询获得 - `clue_id`: 线索ID,当关联类型为线索时必填,通过相应工具查询获得 #### 强烈建议填写的参数 - `fu_sign_id`: 签到信息ID,**必须**通过 `get_checkin_list("")` 工具查询获得。如果有签到记录则使用其ID,没有则传空字符串"" #### 可选参数 - `notes`: 备注内容,额外的补充说明 - `contact_role_type`: 联系人角色类型编码,可选,默认可使用"1" - `opportunity_id`: 商机ID,如果跟进关联特定商机 - `query`: 查询参数,通常留空 ### 重要注意事项 1. **编码值动态性**:所有编码值(enCode)都可能随时变化,绝对不能在代码中硬编码 2. **签到信息检查**:每次提交跟进记录前,必须先查询签到信息 3. **关联类型验证**:不能假设任何编码的含义,必须根据实际的fullName字段判断 4. **工具调用顺序**:严格按照标准流程的顺序调用工具 5. **错误处理**:如果任何一个工具调用失败,应该停止后续操作并提示用户 ### 典型使用流程总结 1. 调用 `get_association_type_list("")` → 获取关联类型选项 2. 调用 `get_follow_method_list("")` → 获取跟进方式选项 3. 调用 `get_association_target_list("")` → 获取跟进目标选项 4. 调用 `get_checkin_list("")` → 获取签到信息(必须) 5. 调用 `get_contact_list("联系人姓名")` → 获取联系人信息 6. 调用 `get_customer_list("客户名称")` → 获取客户信息(如需要) 7. 从各工具响应中提取正确的enCode值 8. 使用真实的enCode值调用 `submit_follow_record()` 提交跟进记录