• [高校训练营] 基于华为云码道(CodeArts)的碳足迹与生命周期评价智能系统
    基于华为云码道(CodeArts)的碳足迹与生命周期评价智能系统一、概述1.1 案例介绍碳足迹核算与生命周期评价(LCA)是量化产品全生命周期环境负荷、支撑绿色低碳转型的核心方法。传统工具往往存在清单提取低效、专业门槛高、结果难落地等问题。本案例基于华为云码道(CodeArts) AI 代码智能体,采用 SDD 规格驱动 + Vibe-Coding 开发范式,从零构建一套碳足迹与生命周期评价系统,并以水泥生产为典型行业示例进行落地演示(如“两磨一烧”工艺边界、清单阶段与 IEII 核算参数)。系统采用前后端分离架构(Flask + Vue3),内置 IEII(综合环境负荷指数)核算引擎,支持异构清单文档的大模型智能解析,并通过 LangGraph Agent 实现自然语言驱动的全流程任务调度。完整源码与演示视频见 GitCode 仓库:cid:link_4。1.2 适用对象工业界环境相关从业者(碳足迹核算、LCA 评价、绿色低碳管理等)高校学生( AI 开发实训)1.3 案例时间直接使用仓库源码:完成资源准备、部署和功能验证,预计需要 60~90 分钟。通过码道手动复现:从 SDD 规格驱动到分阶段 Vibe-Coding 完整走通,预计需要 4~5 小时。1.4 案例流程 前期准备(环境 + 码道 + 大模型 API) ↓ 需求分析 / Skill 规格文档(spec / design / tasks) ↓ 基于码道智能体生成后端(认证、清单解析、LCA 计算等) ↓ 基于码道智能体生成前端及页面美化 ↓ LangGraph Agent:自然语言驱动全流程任务调度说明:前期准备:配置大模型 API Key,准备 PostgreSQL、Python、Node.js 等运行环境;登录华为开发者空间,创建云开发环境,安装并进入码道(CodeArts)AI IDE 的 Vibe-Coding 模式;需求分析 / Skill 文档:使用码道官方 SDD 系列 Skill(如 creating-sdd-directory、managing-spec-document、managing-design-document、managing-tasks-document),完成需求规格、总体设计与任务分解文档;基于智能体生成后端:按业务模块向码道输入 Prompt,分阶段生成认证、LCA 核算、清单智能解析、参数配置等后端能力;基于智能体生成前端及美化:使用码道智能体(可结合 frontend-design Skill)生成项目管理、清单录入、影响评价、对比分析等页面,并完成界面美化与交互打磨;LangGraph Agent 全流程调度:封装建项、清单解析、IEII 计算等工具,通过自然语言对话驱动 LCA 端到端任务链式执行,降低专业操作门槛。1.5 资源总览资源名称规格说明费用参考华为云码道(CodeArts)代码智能体专业版(含 6000 万 Token/月/席位)139 元/月/席位华为云 MaaS 大模型服务 API通过华为云 ModelArts Studio(MaaS)调用 LLM,用于清单解析与 Agent 推理按实际 Token 用量计费(可领取免费额度或使用包月套餐)PostgreSQL 数据库自建,存储项目与清单数据免费说明:码道通用体验版可免费使用,但每月仅 500 万 Token 额度,建议按需升级专业版以保证开发体验。LLM API 推荐使用华为云 MaaS 领取的模型服务(如 DeepSeek、GLM 等),或按实际环境配置可用的 API Key / 模型名称 / 接口地址。PostgreSQL 可在开发环境中直接自建,无需额外付费。二、环境和资源准备2.1 准备华为云码道(CodeArts)AI IDE登录华为开发者空间,进入码道(CodeArts)产品页,开通代码智能体(专业版)服务,获取在线代码生成与迭代能力。参考案例《AI IDE华为云码道(CodeArts)代码智能体安装部署》,完成 Windows 版华为云码道(CodeArts)代码智能体 AI IDE 安装部署,进入码道代码智能体。2.2 领取华为云 MaaS 平台大模型 Tokens登录华为开发者空间,参考案例《华为云MaaS平台大模型Tokens领取使用指导》中的“二、领取 MaaS 平台大模型 Tokens”章节内容,领取 Tokens 代金券并开通模型服务,获取 API 地址、模型名称和 API Key。将获取到的密钥写入后续 backend/.env。2.3 准备本地 / 云开发基础软件本案例技术栈如下:类别选型前端Vue 3 + Vite + ECharts + Vue Router后端Flask 3 + Flask-SQLAlchemy + Flask-CORS数据库PostgreSQL认证JWT + bcrypt + RBAC(admin / normal)AgentLangChain StructuredTool + LangGraph 状态编排大模型通义千问等(DashScope / 华为云 MaaS 兼容接入)文档解析openpyxl / pandas / python-docx / PyMuPDF 等请确保环境满足:Python 3.10+Node.js 18+PostgreSQL 14.2(创建数据库 lca)Redis,用于 Agent 对话检查点持久化;不可用时可降级为内存模式也可在码道中使用 dev-env-setup 专业技能一键安装 Python / Node.js 并校验版本:使用 dev-env-setup 专业技能搭建本地开发环境,安装 Python 3.10+、Node.js 18+、pip 包管理器,配置环境变量并输出版本验证结果。三、基于码道的 AI 开发过程本章聚焦本项目的 AI Coding 开发过程:先明确业务场景与需求边界,再用码道官方 Skill 完成 SDD 规格设计,最后按业务阶段用 Prompt / Vibe-Coding 生成前后端代码。3.1 业务场景与需求概要3.1.1 业务场景与用户角色本平台面向碳足迹与生命周期评价业务,支撑从数据录入、核算执行到结果分析、Agent 辅助调度的端到端工作流;演示数据与工艺边界以水泥“两磨一烧”为例。基于业务权限与操作职责,系统划分为两类核心角色——普通用户与系统管理员。管理员默认继承普通用户的全部业务操作权限,并在系统运维与参数配置层面扩展能力:维度普通用户系统管理员权限范围与功能边界聚焦 LCA 核心业务流:(1)项目全流程管理:创建项目、界定系统边界、录入/解析清单数据、IEII 核算、结果对比;(2)AI 助手对话:通过多轮交互调用 Agent 完成文件上传、数据提取、计算调度等自动化任务继承普通用户全部权限,并扩展:(1)用户管理:角色权限分配、操作日志监控;(2)核算参数配置:物质当量系数、环境类别权重、生产步骤与折算比矩阵等 IEII 基准数据典型使用场景企业环境评估人员执行日常 LCA 评价、工艺数据填报、核算结果分析平台运维人员或领域专家进行底层参数配置、系统配置优化及数据权限管控上述角色通过统一鉴权实现数据视图隔离:普通用户仅可访问本人创建的项目与对话历史;管理员具备全局配置权限,但不可越权修改他人业务数据。3.1.2 功能性需求(1)用户认证与权限管理:支持邮箱密码注册与验证码快捷登录;采用 JWT 无状态会话(有效期 24 小时);基于 RBAC 区分普通用户与管理员的数据视图与操作边界。(2)LCA 项目全生命周期管理:遵循“项目建档 → 目标与范围界定 → 清单录入 → 执行计算 → 结果分析/对比”流程。范围界定支持水泥品种、基准年、工艺路线、系统边界及评价指标的结构化配置;清单录入依据系统边界动态生成各阶段产出/消耗/排放填报;内置 IEII 引擎,仅对用户勾选指标执行特征化、归一化与加权求和,并支持项目快速复制。(3)大模型辅助清单解析:支持 PDF/Excel/Word 等异构文档上传后由大模型抽取结构化清单,前端预览确认后再入库。(4)Agent 交互与任务调度:基于 LangGraph 状态机实现多轮对话智能体;封装清单解析、项目创建、IEII 计算等工具,完成多步链式编排;可用 Redis 持久化对话记忆;强制结构化响应协议(消息/表格等 blocks),保证前端稳定渲染。(5)系统后台管理:管理员可管理用户账号(查看、禁用等),并动态维护环境类别权重、物质当量系数、生产步骤及折算比矩阵。3.2 使用码道完成 SDD 规格驱动设计本案例强调“先设计、后开发”。请在码道对话框中依次执行以下指令,生成 SDD 文档(生成结果可参考仓库中 .codeartsdoer/specs/lca_system/)。3.2.1 初始化 SDD 目录使用 creating-sdd-directory 技能,基于以下需求创建 SDD 项目目录:基于华为云码道的碳足迹与生命周期评价系统(以水泥生产为示例场景),后端 Flask + PostgreSQL,前端 Vue3 + Vite + ECharts,包含 LCA 核算与评估模块、智能体交互与编排模块、系统运维与参数配置模块。生成后的典型目录:.codeartsdoer/specs/lca_system/ ├── spec.md # 需求规格说明书 ├── design.md # 总设计文档 └── tasks.md # 开发任务分解清单 3.2.2 生成需求规格(spec.md)使用 managing-spec-document 技能,为碳足迹与生命周期评价系统生成 spec.md,核心需求包括:用户认证与权限管理(JWT + RBAC,admin/normal 两级角色)LCA 项目全生命周期管理(项目建档→范围界定→清单录入→IEII 计算→结果对比)大模型辅助异构文档智能解析(PDF/Excel/Word→结构化清单)智能体 Agent 对话交互(LangGraph 工具编排,自然语言驱动任务调度)系统参数配置(环境类型权重、物质当量系数、生产步骤与折算比)生成完成后,在码道中打开 .codeartsdoer/specs/lca_system/spec.md,界面示例如下:3.2.3 生成总体设计(design.md)使用 managing-design-document 技能,基于 spec.md 生成 design.md,包含:前后端分离分层架构(表现层 / 业务逻辑层 / 数据访问层 / 外部集成层)PostgreSQL 数据模型(Users、UserLog、UploadedFile、Project、Step2Record、Step3Record、LcaResult、CategoriesWeight、MaterialsWeight、ProductionStep、ConversionRatio、Conversation 等)RESTful API 设计(/auth/、/lca/、/api/agent/、/api/file/、/api/lca-params/、/user/、/admin/)IEII 计算引擎(特征化→归一化→加权求和)Agent 工具编排(StructuredTool + LangGraph 状态机)生成完成后,打开 design.md,界面示例如下:3.2.4 生成任务分解(tasks.md)使用 managing-tasks-document 技能,基于 design.md 生成 tasks.md,按开发阶段拆解任务,标注优先级(P0 核心 / P1 扩展)和依赖关系。生成完成后,打开 tasks.md,界面示例如下:3.3 使用码道分阶段 Vibe-Coding 开发以下 Prompt 可直接输入码道,按阶段生成代码。实际仓库已按该路径落地,可对照验证或在空白工程中复现。3.3.1 阶段一:项目骨架与认证(后端起步)使用 Flask + Vue3 搭建碳足迹与生命周期评价系统,并以水泥生产为示例业务场景。后端 Flask + SQLAlchemy + PostgreSQL,前端 Vue3 + Vite + ECharts。要求:后端结构:app.py、config.py、models.py;按功能域划分 auth/、calculate/、agent/、file/、user/、lca_params/;定义 Users、UserLog、UploadedFile、Project、Step2Record、Step3Record、LcaResult、CategoriesWeight、MaterialsWeight、ProductionStep、ConversionRatio、Conversation 等 ORM 模型;前端侧边栏导航 + 路由守卫(登录 / 管理员权限);JWT 认证:邮箱密码注册登录、验证码登录、退出,Token 有效期 24 小时;CORS 允许前端 localhost:5173 访问后端 localhost:5000。3.3.2 阶段二:用户管理与个人中心实现 RBAC 用户管理、操作日志审计、个人中心:管理员用户列表(分页/搜索/筛选)、启用禁用与权限变更、日志查询导出;个人中心支持资料编辑、改密、头像上传;SMTP 发送 6 位验证码(5 分钟有效);写操作写入 UserLog。3.3.3 阶段三:LCA 核算主流程(ISO 14040/44)以水泥生产为示例,实现 LCA 四阶段流程(示例工艺可按“两磨一烧”配置系统边界与生产步骤):Step1 项目管理(创建/编辑/删除/复制,状态:空项目→范围界定→清单录入→已计算);Step2 研究目标与范围(以水泥为例:品种规格、基准年、工艺、系统边界、评价指标 ADP/GWP/AP/HTP/POCP/EP/LU);Step3 清单录入(按阶段维护产出/消耗/排放 JSON);Step4 IEII 计算:产出量倒推 → 单位强度 → 特征化 → 归一化 → 加权求和;电力按 0.5703 kg CO₂/kWh 折算;仅计算用户勾选指标。3.3.4 阶段四:大模型清单智能解析支持 PDF/Excel/Word/CSV/图片上传;调用大模型按阶段解析产出/消耗/排放并返回结构化 JSON;前端先预览可编辑,用户确认后再写入 Step3;文件状态 uploaded→parsed→stored。3.3.5 阶段五:Agent 智能助手基于 LangGraph 实现 LCA Agent:对话 CRUD;工具包括 upload_file、create_lca_project、list_lca_projects、parse_inventory_file_for_project、calculate_lca_for_project;结构化响应协议(blocks 消息块/表格块等);前端对话页解析 blocks 渲染。3.3.6 阶段六:前端生成、美化与对比分析使用 frontend-design 技能生成/优化项目管理、清单录入、影响评价、对比分析等页面;管理员维护环境类型权重与物质当量系数(ECharts 可视化);使用 data-analysis 技能,以水泥示例数据校验关键阶段(如熟料煅烧)IEII 是否显著偏高、GWP 占比是否符合行业经验。本项目 AI 开发过程中使用的码道 Skill :阶段Skill作用设计creating-sdd-directory初始化 SDD 目录设计managing-spec-document生成 spec.md设计managing-design-document生成 design.md设计managing-tasks-document生成 tasks.md前端frontend-design生成对比分析、影响评价等高质页面验证data-analysis分析校验 LCA 计算结果四、项目结构与关键代码解析本章说明码道生成后的工程结构,并对认证、IEII 计算、清单解析、Agent 编排等关键能力给出源码 + 分析。4.1 项目结构说明CemLCA/ ├── backend/ # Flask 后端 │ ├── app.py # 入口与 Blueprint 注册 │ ├── config.py # 数据库 / JWT / 邮件 / 模型密钥配置 │ ├── models.py # SQLAlchemy ORM 模型 │ ├── requirements.txt │ ├── auth/ # 认证(注册/登录/验证码) │ ├── calculate/ # LCA 项目、Step2/3、IEII 计算、清单解析 │ ├── agent/ # Agent 对话、工具编排 │ ├── file/ # 文件上传与管理 │ ├── user/ # 个人中心 / 管理员接口 │ ├── lca_params/ # IEII 参数配置 API │ └── utils/ # Token、邮件、响应封装、LLM 工具等 ├── frontend/ # Vue3 前端 │ ├── package.json │ └── src/ │ ├── views/ │ │ ├── lca/ # 项目管理 / 清单 / 影响评价 / 对比 │ │ ├── agent/ # Agent 对话页 │ │ ├── system/ # 用户管理 / 参数配置 │ │ └── user/ # 登录注册 │ ├── components/ # Sidebar 等 │ ├── router/index.js │ └── services/api.js ├── .codeartsdoer/specs/lca_system/ # 码道 SDD 规格文档 ├── chatfile/ # Agent 上传文件目录 └── README.md4.2 关键代码讲解4.2.1 后端入口与模块注册backend/app.py 优先加载 .env,再注册各业务 Blueprint,并在启动时建表、开启 CORS:# backend/app.py(节选) app = Flask(__name__) app.config.from_object(config) app.register_blueprint(auth_bp, url_prefix='/auth') app.register_blueprint(calculate_route) app.register_blueprint(agent_route) app.register_blueprint(file_route) app.register_blueprint(admin_bp) app.register_blueprint(user_bp) app.register_blueprint(lca_params_route) db.init_app(app) with app.app_context(): db.create_all() CORS(app, resources={r"/*": {"origins": ["http://localhost:5173", "http://127.0.0.1:5173"]}}) 分析:按功能域拆 Blueprint,便于码道按模块增量生成;calculate 与 agent 解耦后,同一套 IEII / 清单解析逻辑既可被页面调用,也可被 Agent 工具复用。4.2.2 核心数据模型与 PostgreSQL 存储PostgreSQL 作为核心关系型存储底座,集中管理用户档案、项目元数据、LCA 核算基准参数与评价结果等强事务型业务数据。数据访问层基于 Flask-SQLAlchemy ORM 实现标准化访问;概念设计遵循第三范式,按业务域划分实体,依托主外键约束保障一致性。LCA 核算与评估模块的核心数据表如下:表名表用途projects项目主表,项目归属与进度追踪容器,含用户隔离、示例项目标识等step2_record研究目标与范围表,存储水泥品种、基准年、系统边界和评价指标等元数据step3_record生命周期清单表,以 JSON 结构存储各生产阶段的产出、消耗和排放数据lca_result计算结果表,每条记录对应一个阶段×一种产品,存储单位强度、IEII 与指标分解production_steps生产步骤配置表,定义工艺步骤名称、顺序、默认产出物和启用状态conversion_ratios产出物折算比表,供逆向倒推各步真实产出量materials_weight物质当量系数表,存储各物质在七个环境类别下的特征化系数categories_weight环境影响类型权重表,含 IEII 加权系数和归一化基准系统逻辑数据模型图(ER / 表关系)如下:核心业务表示例如下:# backend/models.py(节选) class Project(db.Model): __tablename__ = "projects" id = db.Column(db.Integer, primary_key=True, autoincrement=True) user_email = db.Column(db.String(50), db.ForeignKey("users.email", ondelete="SET NULL")) name = db.Column(db.String(100), nullable=False) type = db.Column(db.String(50), nullable=True) intro = db.Column(db.Text, nullable=True) is_example = db.Column(db.Boolean, nullable=False, server_default=text("false")) class Step2Record(db.Model): __tablename__ = "step2_record" project_id = db.Column(db.Integer, db.ForeignKey("projects.id", ondelete="CASCADE"), unique=True) cement_spec = db.Column(db.String(100), nullable=True) system_border = db.Column(db.JSON, nullable=True) # 系统边界多选 appraise_index = db.Column(db.JSON, nullable=True) # 评价指标多选 class Step3Record(db.Model): __tablename__ = "step3_record" project_id = db.Column(db.Integer, db.ForeignKey("projects.id", ondelete="CASCADE"), unique=True) phases = db.Column(db.JSON, nullable=True) # 各阶段产出/消耗/排放 分析:Step2/Step3 与 Project 一对一,删除项目时级联清理;phases 用 JSON 承载多阶段异构清单,适配水泥示例中可变系统边界,也方便大模型解析结果整包写入。4.2.3 JWT 登录认证# backend/auth/view.py(节选) @auth_bp.route('/login', methods=['POST']) def login(): data = request.get_json(silent=True) or {} email = data.get('email', '').strip() password = data.get('password', '') res = PgSQL.hasUser(email, password) if res.status != 200 or not res.data: record_log(email=email, operation=LOGIN, detail="登录失败:邮箱或密码不正确", result="failure") return jsonify(Error(message='邮箱或密码不正确').to_dict()), 401 user_data = PgSQL.getUserByEmail(email).data if user_data.get('state') == UserState.disabled.value: return jsonify(Warn(message='您的账号被禁用,请联系管理员开放后重试').to_dict()), 403 auth = user_data.get('auth') or 'normal' if hasattr(auth, 'value'): auth = auth.value token = Token.generate_auth_token(user_data.get('id'), user_email=email, auth=auth) return jsonify(Success(data={ 'token': token, 'user_id': user_data.get('id'), 'username': user_data.get('name'), 'email': email, 'auth': auth, }, message='登录成功!').to_dict()) 分析:登录成功后签发 JWT,payload 携带 user_id 与 auth,支撑后续 @token_required / @admin_required;失败与成功均写 UserLog,满足运维审计需求。4.2.4 IEII 计算引擎(特征化 → 归一化 → 加权)计算主逻辑在 backend/calculate/calculate_service.py,同时被 Flask 路由与 Agent 工具复用。LCA 评价过程与计算链路如下:整体遵循:产出量倒推 → 单位强度 → 特征化 → 归一化 → 加权求和 → 写入 LcaResult(1)产出量倒推:默认末步产出 1 t,按折算比矩阵由后向前倒推。以水泥三阶段为例:水泥制备 1 t → 熟料煅烧约 0.726 t → 生料粉磨约 1.118 t(前一步骤产出 = 后一步骤产出 × 折算比)。(2)单位强度:消耗/排放总量 ÷ 该步真实产出量,得到每功能单位强度;电力按 0.5703 kg CO₂/kWh 折算为 CO₂;石油类燃料可将运输距离纳入修正。(3)特征化 / 归一化 / 加权:# backend/calculate/calculate_service.py(节选:归一化 + 加权) normalized_impacts = {} for category in impacts.keys(): category_data = next( (cw for cw in category_weights if cw.get("category_name") == category), None, ) total_equivalent = category_data.get("total_equivalent") if category_data else 0.0 normalized_impacts[category] = ( impacts[category] / total_equivalent if total_equivalent else 0.0 ) weighted_sum = 0.0 for category, value in normalized_impacts.items(): category_weight = next( (cw.get("weight", 0.0) for cw in category_weights if cw.get("category_name") == category), 0.0, ) weighted_sum += value * category_weight ieii = weighted_sum # 单位强度 IEII ieii_total = weighted_sum * actual_product_amount # 总 IEII 分析:特征化把异构清单统一到七类环境影响(ADP/GWP/AP/HTP/POCP/EP/LU);归一化消除量纲差异;加权得到可横向对比的单一指数。仅 Step2 勾选的指标子集参与全过程,保证闭运算。4.2.5 大模型清单智能解析# backend/calculate/inventory_extract.py(节选) def extract_inventory_json_from_file(file_path: str, api_key: Optional[str] = None) -> dict: api_key = api_key or os.getenv("API_KEY") if not api_key: raise ValueError("未配置 API_KEY,无法解析文件") client = OpenAI( api_key=api_key, base_url="https://dashscope.aliyuncs.com/compatible-mode/v1", timeout=180.0, ) file_object = client.files.create(file=path.open("rb"), purpose="file-extract") completion = client.chat.completions.create( model="qwen-long-2025-01-25", messages=[ {"role": "system", "content": _inventory_schema_prompt()}, {"role": "system", "content": f"fileid://{file_object.id}"}, {"role": "user", "content": "请根据上述要求,从文件中提取各阶段的产出、消耗与排放,只输出 JSON。"}, ], temperature=0, stream=True, ) full_content = "" for chunk in completion: if chunk.choices and chunk.choices[0].delta.content: full_content += chunk.choices[0].delta.content or "" return _parse_json_from_llm(full_content) 分析:通过兼容 OpenAI 的接口上传文件,并用 Schema Prompt 约束输出结构;temperature=0 降低随机性。业务上采用「解析预览 → 用户确认 → 写入 Step3」两阶段,避免 LLM 偶发误差直接污染正式清单。文件解析提取与处理流程如下:4.2.6 Agent 工具编排与运行Agent 采用工具驱动架构:不自行“编造”业务结果,而是理解意图后调用专项工具,再聚合为结构化 blocks 返回。执行流程架构如下:设计要点:领域专业化:系统提示词限定能力边界(LCA 建项 / 解析 / 计算),降低幻觉;工具编排:经 LangGraph create_agent 注册 StructuredTool,由模型决定调用顺序与参数;结构化响应:强制 ResponseFormat,前端按 message / table 等块类型渲染;状态化对话:优先 Redis Checkpoint,失败则降级内存,维持多轮上下文。当前注册的核心工具:工具名称功能描述upload_file上传文件并返回服务器路径create_lca_project新建 LCA 项目list_lca_projects列出当前用户可见项目parse_inventory_file_for_project解析清单并写入指定项目 Step3calculate_lca_for_project执行 IEII 计算并返回结果摘要工具注册(backend/agent/tools.py):# backend/agent/tools.py(节选) calculate_lca_for_project = StructuredTool.from_function( func=_calculate_lca_for_project, name="calculate_lca_for_project", description="""执行指定项目的 LCA 计算(复用系统已实现的 IEII 计算算法)...""", parameters={ "type": "object", "properties": { "project_id": {"type": "integer", "description": "项目管理中的整数项目 ID"} }, "required": ["project_id"], }, ) def get_tools(context: Context) -> list: global _ctx _ctx = context return [ upload_file, create_lca_project, list_lca_projects, parse_inventory_file_for_project, calculate_lca_for_project, ] Agent 运行(backend/agent/agent.py):# backend/agent/agent.py(节选) def run_agent(message: str, user_id: int = 1, thread_id: str = None, is_first_message: bool = False): config = {"configurable": {"thread_id": thread_id or f"user_{user_id}"}} ctx = Context(user_id=user_id) with get_checkpointer() as checkpointer: agent = create_agent( model=get_llm(), system_prompt=SYSTEM_PROMPT, tools=get_tools(ctx), checkpointer=checkpointer, response_format=ResponseFormat, # 强制结构化 blocks 输出 ) result = agent.invoke( {"messages": [{"role": "user", "content": message}]}, config=config, ) final_response = _parse_structured_response(result.get("messages", []), invoke_result=result) return {"messages": result.get("messages", []), "response": final_response, ...} 结构化响应块常用类型:类型主要字段用途messagecontent, style(default/success/warning/error)带样式的文本提示tableheader, rows, title, actions表格与操作按钮filefile_id, file_name, file_path文件信息展示cardtitle, content, actions复杂信息容器分析:这是本案例亮点——自然语言驱动“上传 → 建项 → 解析 → 计算”链式任务。4.2.7 前端路由守卫// frontend/src/router/index.js(节选) router.beforeEach((to, from, next) => { const token = localStorage.getItem('token') const userAuth = localStorage.getItem('auth') if (to.meta.requiresAuth && !token) { loginPromptEmitter.emit(to.fullPath) return } if (to.meta.requiresAdmin && userAuth !== 'admin') { next('/lca/projects') return } next() }) 分析:LCA 业务页与 Agent 页设置 requiresAuth;用户管理、参数配置另加 requiresAdmin,与后端 RBAC 前后端双重校验。五、配置运行与系统功能演示本章完成环境配置与前后端启动,并按业务模块讲解系统功能。5.1 配置环境并运行调试5.1.1 配置后端cd backend python -m venv venv # Windows PowerShell .\venv\Scripts\activate # Linux / macOS # source venv/bin/activate pip install -r requirements.txt1)在 PostgreSQL 中创建数据库:CREATE DATABASE "Cemlca"; 2)复制并编辑环境变量文件:cp .env.example .env在 .env 中配置:API_KEY=你的大模型API密钥3)按实际环境修改 backend/config.py 中的数据库连接,例如:SQLALCHEMY_DATABASE_URI = "postgresql://用户名:密码@127.0.0.1:5432/Cemlca" 4)启动后端:python app.py默认监听:http://127.0.0.1:5000。可用 curl 验证:curl http://127.0.0.1:5000/api/ping期望返回:{"message": "Flask 后端已就绪", "status": "ok"} 5.1.2 配置前端cd frontend npm install npm run dev默认访问:http://localhost:5173。5.2 LCA 核算与评估功能演示LCA 核算与评估是系统核心业务,按四步推进:步骤名称说明Step1项目创建建立评价项目,记录名称、类型、简介,作为后续数据归属容器Step2研究目标与范围确定水泥品种、基准年、工艺、系统边界、评价指标Step3生命周期清单按阶段录入产出/消耗/排放;支持手工录入与大模型解析Step4影响评价计算执行特征化→归一化→加权,得到各阶段 IEII 与指标分解完成后可进行结果对比分析。5.2.1 登录与注册打开前端地址,完成注册或登录(支持邮箱密码 / 验证码登录)。登录成功后 Token 存于本地,后续请求自动携带。5.2.2 项目管理(Step1)进入 项目管理 页:列表默认展示当前用户项目;支持卡片 / 列表两种视图;每个项目显示四节点进度条(创建→范围→清单→计算),已完成节点显示 √,当前节点高亮,未到达节点灰色不可点;状态逻辑简述:step2 必填齐全 → phases 非空 → 存在 LcaResult,据此映射进度 1~4;新建项目:名称为必填,同一用户下不可重名;创建后为空项目状态;复制项目:可复制基本信息,可选复制 Step2/Step3,不复制计算结果;普通用户仅可操作本人项目与示例项目;示例项目禁止写操作。5.2.3 研究目标与范围(Step2)在进度条进入 Step2,填写:水泥品种、基准年、生产工艺、系统边界(多选)、评价指标(多选)。系统边界选项来自生产步骤配置;评价指标来自环境类型权重表(七项:ADP/GWP/AP/HTP/POCP/EP/LU)。仅勾选指标参与后续 IEII 计算。保存采用 upsert。5.2.4 生命周期清单录入(Step3)按 Step2 系统边界动态生成阶段分组;每组含产出表、消耗表、排放表,支持行内增删。两种录入方式:手工录入:编辑后保存,JSON 写入 step3_record.phases;大模型辅助解析:上传 PDF/Excel/Word/CSV/图片 → 大模型按 Schema 抽取 → 前端预览可改 → 确认后入库(两阶段设计,避免脏数据)。5.2.5 影响评价计算(Step4)点击执行计算后,后端完成倒推产出量、单位强度、特征化、归一化与加权,结果写入 lca_result。前端影响评价页:表格按阶段×产品展示 IEII 与七项指标分解,可筛选;ECharts 柱状图对比各阶段 IEII;堆叠柱状图展示指标贡献占比。5.2.6 结果对比分析对已完成计算的项目,可从按生产步骤、按产品等维度查看 IEII 与七项指标对比:按步骤 IEII 条形图 / 七项指标分组柱状图;按产品 IEII 饼图与堆叠柱状图;消耗/排放构成分析。5.3 智能体交互功能演示Agent 页采用左侧会话列表 + 右侧对话区。用户可新建/切换/删除会话,发送文本并附带文件;响应按 blocks 渲染消息、表格等。话术示例(可附带清单文件):帮我根据附件创建一个LCA项目,名称叫水泥test1[文件路径:D:\桌面\华为\CemLCA\chatfile\2024.11.xlsx]Agent 依次调用建项、解析、计算等工具,并返回结构化结果(如 LCA 结果明细表格)。5.4 系统运维与参数配置演示5.4.1 用户管理与操作日志(管理员)管理员进入用户管理:分页/搜索/按角色状态筛选;启用禁用;查看并筛选操作日志,可导出。认证为 JWT(24 小时)+ @token_required / @admin_required 栈式叠加。5.4.2 个人中心普通用户可编辑姓名/电话/单位,修改密码(需旧密码),上传/删除头像;查看个人日志与项目统计仪表盘。5.4.3 LCA 计算参数配置(管理员)四类参数可视化维护:参数类型说明前端呈现生产步骤工序名称、顺序、默认产出物、启用状态可排序列表折算比矩阵步骤间物料折算关系热力图等环境类型权重类别权重 + 归一化基准(七类)饼图 / 列表物质当量系数物质在各环境类别下的系数(JSON)科学计数法列表 / 图表5.5 系统能力小结模块能力要点LCA 核算与评估Step1~4 全流程、IEII 自动化计算、结果可视化与对比分析大模型清单解析异构文档 → 结构化清单,预览确认后入库智能体编排自然语言驱动建项、解析、计算等链式任务系统运维JWT+RBAC、操作日志、个人中心、LCA 参数可视化配置六、释放资源6.1 停止本地 / 云开发环境中的服务在运行前后端的终端中按 Ctrl + C 停止进程;如使用 Python 虚拟环境,可 deactivate。6.2 释放云开发环境与按量资源进入华为开发者空间,停止或删除本案例创建的云开发环境容器;若额外购买了 ECS、EIP、CCE 等按量资源,进入对应控制台,勾选实例后执行 更多 > 删除,并勾选释放公网 IP 与数据盘,避免持续计费;大模型 Tokens 套餐按实际剩余额度管理,体验结束可不继续调用推理接口。七、扩展资料说明华为开发者空间主页:cid:link_3华为云码道(CodeArts):https://codearts.huaweicloud.com/华为云 MaaS Tokens 领取指导:《华为云MaaS平台大模型Tokens领取使用指导》LCA 国际标准:ISO 14040 / ISO 14044(生命周期评价原则、框架与要求)Flask 官方文档:https://flask.palletsprojects.com/Vue 3 官方文档:https://vuejs.org/LangGraph 文档:https://langchain-ai.github.io/langgraph/
  • [高校训练营] 基于 MaaS 和 CodeArts 的智能运维与代码重构平台实践
    在线体验地址:http://113.44.103.96(请复制到浏览器访问)项目源码仓库:cid:link_5一、概述1.1 案例介绍在软件研发和云上运维过程中,遗留代码重构依赖人工经验,故障日志分析又常常跨越应用、容器和函数等多个层次,定位慢、重复劳动多。CodeVerse-Ops 将华为云 MaaS 大模型能力接入研发运维流程,提供智能代码重构、云原生日志诊断、代码质量评分、上下文追问、历史任务分析和代码片段管理等能力。本案例将使用华为云 MaaS 的 DeepSeek-V4-Flash 模型作为推理引擎,基于 Next.js、Prisma 和 SQLite 构建全栈应用,并通过 PM2 与 Nginx 部署到弹性云服务器 ECS。完成案例后,您将掌握:使用 OpenAI 兼容接口调用华为云 MaaS 模型;使用华为云码道的 Spec-Driven 模式,将需求依次转化为规格、设计、任务和代码;理解 Server-Sent Events(SSE)任务事件,并在 AI 追问场景中实现流式回复;将模型能力组合为代码重构、日志根因分析和质量评分工作流;使用 Prisma 与 SQLite 管理任务、对话和收藏数据,并理解质量评分的数据模型;在 Ubuntu ECS 上完成 Node.js 应用的一键部署、验证和运维。说明:模型生成内容可能存在偏差。重构代码和运维修复建议应经过人工审查,并在测试环境验证后再应用到生产环境。1.2 适用对象企业开发者及 DevOps、SRE、云原生运维人员;希望学习大模型应用开发的个人开发者;具备 JavaScript/TypeScript、Linux 命令行基础的高校学生。1.3 案例时间直接使用仓库源码完成资源准备、部署和功能验证,预计需要 60~90 分钟。如通过码道分阶段搭建 CodeVerse-Ops,建议预留 2~3 小时,具体时间取决于代码生成、人工评审、依赖下载和构建速度。1.4 案例流程图 1-1 CodeVerse-Ops 案例流程说明:开通 MaaS:登录华为开发者空间,开通 DeepSeek-V4-Flash 预置服务,创建并妥善保存 API Key;创建 ECS:购买 Ubuntu ECS,绑定弹性公网 IP,并在安全组中开放 SSH 和 HTTP 访问;配置并上传:填写 MaaS API Key、基础地址和数据库连接,将项目部署包上传至 ECS;一键部署:运行部署脚本,自动安装依赖,完成数据库迁移、项目构建、PM2 启动和 Nginx 配置;功能体验:依次验证代码重构、批量处理、日志诊断、质量评分、AI 对话、仪表盘和收藏库;验证并释放:检查应用、代理和数据库状态;体验结束后删除 ECS、EIP 及不再使用的模型凭据。流程说明:图 1-1 展示的是“使用现有源码部署体验”的主流程。如需从需求开始复现项目开发过程,请在获取源码和正式部署前完成第三章的码道 Spec-Driven 四阶段实践。1.5 方案架构图 1-2 CodeVerse-Ops 系统运行架构核心调用链如下:浏览器提交代码或日志,Next.js API 创建任务并写入 SQLite;当前版本的提交接口同步调用华为云 MaaS,解析结果并将任务更新为 COMPLETED;浏览器收到 taskId 后连接任务 SSE 接口,通常直接收到 complete 事件并展示结果;用户继续追问时,服务端通过 thinking、result_chunk、complete 或 error 事件逐段推送模型回复;任务结果、对话记录和收藏内容持久化到 SQLite;质量评分接口在收到 taskId 时可持久化评分;仪表盘聚合任务数据,展示近 30 天趋势、任务分布,并预留质量趋势展示。1.6 资源总览本案例使用按需资源。以 1 小时体验、少量公网流量和少量模型调用估算,费用通常由 ECS 实例费用、EIP 流量费用和 MaaS Token 费用组成。云服务价格会因区域、规格和活动变化,最终以购买页面及账单为准。资源名称推荐规格用途计费说明华为开发者空间已完成实名认证的账号进入开发平台和实战案例免费MaaS 模型即服务DeepSeek-V4-Flash代码重构、日志分析、质量评分和对话按实际 Token 用量计费,可优先使用已领取权益弹性云服务器 ECS2 vCPU、4 GiB、Ubuntu 22.04、40 GiB 系统盘运行 CodeVerse-Ops推荐按需计费,价格以控制台为准弹性公网 IP EIP按流量计费、5 Mbit/sSSH 登录和浏览器访问按流量计费,价格以控制台为准费用提示:体验完成后请及时释放 ECS 和 EIP。仅关闭操作系统不会停止 ECS 计费。二、环境和资源准备2.1 前置条件开始前请确认:已注册华为云账号并完成实名认证;账号余额或代金券足以支付本案例资源;本地可使用 SSH 和 SCP。Windows 10/11 可在 PowerShell 中执行 ssh -V 和 scp 检查;已获得完整的 codeverse-ops 项目目录;不要将 API Key 写入公开仓库、聊天记录或截图。2.2 开通 MaaS 模型并创建 API Key登录华为开发者空间。如尚未领取模型权益,可参考《华为云 MaaS 平台大模型 Tokens 领取使用指导》完成领取。然后按以下步骤开通模型:进入 MaaS 控制台 > 模型推理 > 在线推理 > 预置服务;找到 DeepSeek-V4-Flash,单击 开通服务;服务开通后单击 调用说明,确认模型参数为 deepseek-v4-flash;在调用说明页面创建 API Key,并立即复制到安全位置。API Key 通常只在创建时完整显示;记录 OpenAI 兼容接口地址。中国大陆站的 OpenAI 兼容接口当前仅支持 西南-贵阳一,该区域的完整地址为:https://api.modelarts-maas.com/openai/v1/chat/completions本项目会自动在基础地址后追加 /v1/chat/completions,因此项目配置中应填写:https://api.modelarts-maas.com/openai中国香港站应以控制台“调用说明”显示的地址为准,常见基础地址为:https://api-ap-southeast-1.modelarts-maas.com/openai重要:模型服务、API Key 和调用地址必须属于同一区域,并以控制台“调用说明”为准。不要填写完整的 /v1/chat/completions 地址,否则项目会重复拼接路径;不要使用 https://api.deepseek.com,该地址不是华为云 MaaS 服务地址。Linux、macOS 或 ECS 可使用以下命令验证 API Key:export MAAS_API_KEY="<你的MaaS API Key>" curl -sS "https://api.modelarts-maas.com/openai/v1/chat/completions" \ -H "Content-Type: application/json" \ -H "Authorization: Bearer ${MAAS_API_KEY}" \ -d '{ "model": "deepseek-v4-flash", "messages": [{"role": "user", "content": "请回复:连接成功"}], "max_tokens": 64 }' 响应中出现 choices 和模型回复即表示调用成功。若返回 401 或 403,请检查 API Key、模型开通状态和区域是否一致。Windows PowerShell 使用以下命令:$env:MAAS_API_KEY = "<你的MaaS API Key>" $headers = @{ "Content-Type" = "application/json" "Authorization" = "Bearer $env:MAAS_API_KEY" } $body = @{ model = "deepseek-v4-flash" messages = @(@{ role = "user"; content = "请回复:连接成功" }) max_tokens = 64 } | ConvertTo-Json -Depth 4 Invoke-RestMethod ` -Uri "https://api.modelarts-maas.com/openai/v1/chat/completions" ` -Method Post ` -Headers $headers ` -Body $body2.3 创建 ECS登录华为云控制台,进入 服务列表 > 计算 > 弹性云服务器 ECS,单击 购买弹性云服务器。图 2-1 选择 ECS 规格、镜像、磁盘和公网访问配置推荐配置如下:配置项推荐值说明计费模式按需计费便于体验结束后及时释放区域与账号和网络规划一致购买后不可直接更换CPU 架构x86与常用 Node.js 依赖兼容规格2 vCPU、4 GiB低于 4 GiB 可能在 next build 时内存不足镜像Ubuntu 22.04 Server 64bit部署脚本使用 apt-get系统盘40 GiB用于系统、依赖、构建产物和 SQLiteEIP现在购买用于 SSH 和 Web 访问带宽计费按流量计费,5 Mbit/s适合短时体验登录方式密钥对或强密码密钥对安全性更高购买完成后,在 ECS 详情页记录:ECS 公网 IP:后文以 <ECS_IP> 表示;登录用户名:本案例部署脚本固定使用 /root 并以 root 用户配置 PM2,因此应选择支持 root 登录的 Ubuntu 公共镜像;密钥文件路径或登录密码。图 2-2 ECS 创建完成并处于运行中说明:截图中的实例名称、IP、价格和区域仅为操作示例,请以实际控制台页面为准。2.4 配置安全组进入 ECS 详情 > 安全组 > 配置规则 > 入方向规则,添加以下规则:协议端口来源用途TCP22本机公网 IP/32SSH 和 SCPTCP80本机公网 IP/32;公开体验时可临时使用 0.0.0.0/0浏览器访问应用图 2-3 配置 ECS 安全组入方向规则安全建议:不要将 22 端口长期对全网开放。生产环境还应配置 HTTPS、Web 应用防火墙、身份认证和访问审计。本案例应用本身未实现用户登录,不应直接承载敏感代码或生产日志。2.5 准备项目环境变量记录从 MaaS 控制台获取的 API Key 和基础地址。为避免凭据进入压缩包,本案例将在代码上传 ECS 后创建 .env.production,文件内容如下:# 华为云 MaaS API Key HUAWEI_MAAS_API_KEY=<你的MaaS API Key> # 仅填写基础地址,不包含 /v1/chat/completions HUAWEI_MAAS_BASE_URL=https://api.modelarts-maas.com/openai # Prisma 会相对 prisma/schema.prisma 解析该路径 DATABASE_URL=file:../dev.db配置要求:HUAWEI_MAAS_API_KEY 不要添加多余空格或中文引号;HUAWEI_MAAS_BASE_URL 末尾有无 / 均可,客户端会移除末尾斜杠;DATABASE_URL 保持为 file:../dev.db,使 Prisma CLI 和应用运行时使用项目根目录下同一个数据库;.env.production 含敏感信息,不得提交到公开代码仓库或打入部署包;项目已通过 .gitignore 排除 .env.production;提交前仍应使用 git status 确认该文件未被暂存;部署脚本不会输出环境变量内容,终端日志中不应出现 API Key。2.6 获取案例源码通过 Git 下载案例源码:git clone cid:link_5.git codeverse-ops cd codeverse-ops仓库地址:CodeVerse-Ops(GitCode)【本帖子开头有】。下载后确认目录中至少包含:codeverse-ops/ ├── package.json ├── package-lock.json ├── scripts/deploy-ecs.sh ├── prisma/ └── src/检查点:执行 git status 能正常显示仓库状态,且 package.json、scripts/deploy-ecs.sh、prisma/ 和 src/ 均存在。三、通过码道分阶段搭建 CodeVerse-Ops本模块参考华为开发者空间案例中心的码道实践组织方式,结合 CodeVerse-Ops 的实际开发记录,演示如何使用华为云码道(CodeArts)代码智能体,以 Spec-Driven 模式将复杂需求依次转化为需求规格、技术设计、任务清单和可运行代码。说明:码道界面、模型列表和按钮位置可能随版本更新而变化,请以实际产品页面为准。生成代码必须经过人工审查、构建测试和安全检查;不要在对话、截图或提交记录中粘贴 API Key、密码等敏感信息。3.1 开通并进入码道登录华为开发者官网,进入华为云码道(CodeArts)代码智能体体验页面;按页面提示完成体验版开通;下载并安装支持码道的开发工具,登录同一华为云账号;打开码道 Agent Space 或 IDE 右侧智能体面板,确认可以选择 氛围编程(Vibe-Coding) 和 规范开发(Spec-Driven)。图 3-1 开通华为云码道代码智能体体验版图 3-2 进入码道 Agent Space图 3-3 在 IDE 中打开码道代码智能体3.2 创建项目并选择 Spec-Driven 模式新建空工作区,在智能体面板选择 规范开发(Spec-Driven)。首次输入应描述业务目标、技术栈、模型服务、核心功能和交付要求,避免只输入“帮我做一个网站”等宽泛指令。可使用以下需求作为起始提示词:请使用 Next.js 14、TypeScript、Tailwind CSS、Prisma 和 SQLite 构建 CodeVerse-Ops。应用接入华为云 MaaS 的 DeepSeek-V4-Flash, 提供单文件/批量代码重构、CCE/FunctionGraph 日志诊断、代码质量评分、 上下文对话、任务仪表盘和代码片段收藏功能。请采用 Spec-Driven 流程, 先生成需求规格,再生成技术设计和任务清单,经确认后分阶段实现。图 3-4 选择 Spec-Driven 模式并提交项目目标Spec-Driven 流程包含四个阶段:需求规格设计:明确目标、边界、用户故事和验收标准;实现方案创建:确定架构、数据模型、接口和部署方案;编码任务规划:将设计拆分为可追踪、可验证的任务;任务执行:按依赖顺序生成代码,并持续构建验证。3.3 第一阶段:生成并评审 spec.md码道首先将自然语言需求整理为 spec.md。评审时重点检查:是否覆盖代码重构、日志诊断、任务状态、模型调用和数据持久化;是否明确“不负责自动修改生产代码、不直接执行模型生成命令”等安全边界;每个核心能力是否具有可验证的验收标准;模型名称、接口兼容方式和部署目标是否与项目实际一致。图 3-5 第一阶段完成需求规格设计若规格有遗漏,先在对话中提出修改要求,确认 spec.md 后再进入设计阶段。不要让智能体在需求边界未确定时直接批量生成代码。3.4 第二阶段:生成并评审 design.mddesign.md 应把需求落实为可实现的技术方案。本项目重点确认:Next.js App Router 同时承载页面和 API;Prisma/SQLite 数据模型覆盖任务、日志、对话、评分和收藏;MaaS 客户端统一处理鉴权、超时、重试及流式响应;首轮任务与 AI 对话的 SSE 行为描述准确;ECS、PM2、Nginx 和容器化部署路径清晰;API Key 仅通过环境变量注入,不进入源码、镜像和日志。图 3-6 第二阶段完成实现方案设计3.5 第三阶段:生成并评审 tasks.md码道根据规格和设计生成 tasks.md,把工作拆分为初始化、数据模型、MaaS 客户端、任务状态、核心 API、前端页面和部署验证等任务。评审任务清单时应确保:每项任务都能回溯到 spec.md 和 design.md;任务依赖顺序正确,可并行项和串行项明确;每项任务包含完成条件,而不只是文件名;构建、数据库迁移、接口验证和安全检查被列入任务。图 3-7 第三阶段完成编码任务规划3.6 第四阶段:按任务清单执行确认任务清单后进入执行阶段。码道会读取规格和设计,按依赖关系创建文件、安装依赖并实现功能。建议采用“小批次执行—查看变更—运行验证—继续下一批”的节奏:先完成项目初始化、环境变量声明和 Prisma Schema;再实现 MaaS 客户端、任务状态和后端 API;然后实现重构、诊断、仪表盘、收藏等页面;最后补充 Dockerfile、ECS/CCE 部署文件和操作文档;每批变更后查看差异,拒绝与规格无关的修改。图 3-8 码道开始执行初始化与配置任务图 3-9 码道继续实现后端接口和前端页面图 3-10 任务执行阶段完成3.7 本地运行与阶段验收智能体完成首轮实现后,在项目目录执行:npm install npx prisma generate npx prisma migrate deploy npm run dev浏览器访问 http://localhost:3000,先验证页面路由和基本交互,再使用脱敏的测试代码与测试日志验证 MaaS 调用。首个可运行版本可能只具备代码重构和日志诊断,应按 tasks.md 的验收条件逐项检查,而不是仅以“页面能打开”作为完成标准。图 3-11 首个本地可运行版本的代码重构页面图 3-12 本地验证日志诊断功能3.8 模型接入的原型记录与正式配置项目早期曾使用 DeepSeek 官方 API 验证 OpenAI 兼容调用链,以下两张图仅用于说明原型演进,不是本案例的最终配置步骤。图 3-13 早期原型的 API Key 创建记录图 3-14 早期原型的环境变量配置正式案例已经切换到华为云 MaaS。请严格按照 2.2 和 2.5 节配置 HUAWEI_MAAS_API_KEY 与 https://api.modelarts-maas.com/openai,不要照抄历史截图中的 https://api.deepseek.com;截图中的凭据已失效或脱敏。3.9 迭代优化与上下文管理首轮功能完成后,可继续让码道基于实际测试结果迭代,但每次指令应说明问题、预期行为、影响范围和验证方式。本项目的后续迭代包括主题系统、命令面板、仪表盘、收藏库、批量重构、上下文对话以及 ECS 部署加固。图 3-15 基于功能差距分析继续迭代图 3-16 依据新增需求升级功能版本长任务会持续占用上下文。阶段验收后可使用会话压缩保留目标、约束、关键文件和未完成任务,再继续下一轮开发。压缩前应确认摘要未包含 API Key、登录密码等敏感信息。图 3-17 使用会话压缩管理长周期开发上下文完成本模块后,项目应通过 npm run build,数据库迁移可执行,核心页面可访问,且所有环境变量和部署步骤与后续章节一致。四、构建并部署 CodeVerse-Ops 应用4.1 技术栈与项目结构主要技术栈如下:层次技术版本/作用Web 框架Next.js14.2.35,App Router 全栈应用前端React、TypeScript、Tailwind CSSReact 18、TypeScript 5、Tailwind CSS 3.4编辑器CodeMirror 6代码输入、语法高亮和只读结果展示图表Recharts仪表盘与五维质量雷达图数据访问Prisma5.22.0,模型定义、迁移和查询数据库SQLite保存任务、日志、对话、评分和收藏模型服务华为云 MaaSDeepSeek-V4-Flash、OpenAI 兼容接口运行环境Node.js、PM2、NginxNode.js 20、进程守护、反向代理项目关键结构:codeverse-ops/ ├── prisma/ │ ├── schema.prisma # 7 个数据模型 │ └── migrations/ # 数据库迁移 ├── src/ │ ├── app/ │ │ ├── page.tsx # 首页 │ │ ├── refactor/page.tsx # 单文件/批量代码重构 │ │ ├── ops/diagnose/page.tsx # CCE、FunctionGraph 日志诊断 │ │ ├── dashboard/page.tsx # 任务统计与趋势 │ │ ├── snippets/page.tsx # 代码片段收藏库 │ │ └── api/ # 重构、诊断、评分、对话等 API │ ├── components/ # 编辑器、对比、图表、命令面板等组件 │ ├── hooks/ # SSE、主题等 React Hooks │ ├── lib/ │ │ ├── huawei-maas.ts # MaaS 客户端、重试和超时控制 │ │ ├── prisma.ts # Prisma 单例 │ │ ├── sse-client.ts # SSE 消息与响应头 │ │ ├── task-state.ts # 任务状态 │ │ ├── conversation-manager.ts # 30 分钟内存上下文 │ │ └── templates.ts # 代码与日志示例模板 │ └── types/ # API、模板和 SSE 类型 ├── .env.example # 环境变量示例 ├── .env.production # 生产配置,需自行创建 ├── scripts/ │ ├── deploy-ecs.sh # ECS 一键部署脚本 │ └── build-image.sh # SWR 镜像构建脚本 ├── deploy/ │ └── cce-deployment.yaml # CCE 部署清单 ├── Dockerfile # 容器化构建文件 ├── package.json # 项目依赖与命令 └── package-lock.json # 锁定依赖版本Prisma 数据模型职责:模型作用Task保存重构或日志诊断任务及状态CloudLog保存待分析日志及分析状态Snippet保存收藏的原始代码、重构代码和说明BatchGroup管理批量重构的总数和完成进度Conversation关联任务与对话Message持久化用户和助手消息QualityScore在评分接口收到 taskId 时,保存安全性、可维护性、性能、可读性和类型安全评分4.2 关键实现解析4.2.1 MaaS 客户端src/lib/huawei-maas.ts 负责:从环境变量读取 API Key 和基础地址;拼接 /v1/chat/completions;使用 Authorization: Bearer <API_KEY> 鉴权;固定调用 deepseek-v4-flash;同步调用最多尝试 3 次,即首次失败后最多重试 2 次,退避时间依次为 1 秒、2 秒;单次调用超时时间为 120 秒;支持普通 JSON 响应和流式响应。核心请求结构如下:const response = await fetch(`${baseUrl}/v1/chat/completions`, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${apiKey}`, }, body: JSON.stringify({ model: "deepseek-v4-flash", messages, temperature: 0.7, max_tokens: 4096, stream: true, }), }); 4.2.2 任务接口与 SSE 事件代码重构和日志诊断采用“同步任务提交 + SSE 结果回传”的两阶段请求:图 4-1 CodeVerse-Ops 首轮任务与对话请求流程图中编号说明:提交代码或日志:浏览器将用户输入发送到对应的 Next.js API;创建任务:服务端在 SQLite 中创建状态为 PENDING 的任务;进入处理状态:开始推理前,将任务状态更新为 PROCESSING;调用模型:服务端通过 OpenAI 兼容接口同步调用华为云 MaaS;返回完整结果:MaaS 返回完整的代码重构或日志分析结果;保存结果:服务端解析模型输出,将结果写入 SQLite,并将任务标记为 COMPLETED;响应提交请求:Next.js API 向浏览器返回 taskId 和完整结果;连接任务 SSE:浏览器使用 EventSource 连接任务 SSE 接口;返回完成事件:SSE 接口查询到已完成任务后,发送 complete 事件。用户继续对话时,应用则通过 SSE 逐段返回模型回复。实现边界:页面上的“正在连接 AI 服务”和 SSE 状态组件已经具备流式展示结构,但首轮重构、诊断请求的等待主要发生在同步 POST 阶段,当前版本不会逐 Token 展示首轮模型输出。对话追问采用真实流式响应。4.2.3 提示词与结构化结果应用通过系统提示词限定模型角色,并要求模型返回 JSON:代码重构:返回 refactoredCode 和 explanation;日志诊断:返回 analysis 和 patchSuggestion;质量评分:返回五个 0~100 的维度分数及 details。服务端会从模型输出中提取 JSON。若模型未严格返回 JSON,部分接口会回退为原始文本。因此,生成结果仍需人工复核。4.3 打包项目在本地打开项目父目录执行。部署包明确排除环境变量、依赖、构建产物、数据库和 Git 元数据:tar -czf codeverse-ops-deploy.tar.gz \ --exclude=codeverse-ops/node_modules \ --exclude=codeverse-ops/.next \ --exclude=codeverse-ops/dev.db \ --exclude=codeverse-ops/.env \ --exclude=codeverse-ops/.env.production \ --exclude=codeverse-ops/.git \ codeverse-ops/Windows PowerShell 使用反引号续行:tar -czf codeverse-ops-deploy.tar.gz ` --exclude=codeverse-ops/node_modules ` --exclude=codeverse-ops/.next ` --exclude=codeverse-ops/dev.db ` --exclude=codeverse-ops/.env ` --exclude=codeverse-ops/.env.production ` --exclude=codeverse-ops/.git ` codeverse-ops/ 打包后检查文件和压缩包内容:Get-Item .\codeverse-ops-deploy.tar.gz tar -tzf .\codeverse-ops-deploy.tar.gz检查点:压缩包中必须包含 package-lock.json、scripts/deploy-ecs.sh、prisma/ 和 src/,不得包含 .env、.env.production、node_modules、.next 或旧的 dev.db。4.4 上传项目并执行一键部署步骤 1:上传部署包在本地项目父目录执行:scp codeverse-ops-deploy.tar.gz root@<ECS_IP>:/root/使用密钥对时执行:scp -i <私钥文件路径> codeverse-ops-deploy.tar.gz root@<ECS_IP>:/root/步骤 2:登录 ECSssh root@<ECS_IP> 使用密钥对时执行:ssh -i <私钥文件路径> root@<ECS_IP> 步骤 3:解压并运行部署脚本cd /root tar -xzf codeverse-ops-deploy.tar.gz rm -f codeverse-ops-deploy.tar.gz cd /root/codeverse-ops vi .env.production在编辑器中填写 2.5 节准备的三个环境变量,保存后限制文件权限:chmod 600 .env.production # 确保 Node.js 主版本为 20 node -v 2>/dev/null || true 若已安装的 Node.js 不是 20.x,先升级:curl -fsSL https://deb.nodesource.com/setup_20.x | bash - apt-get install -y nodejs首次部署执行:chmod +x scripts/deploy-ecs.sh bash scripts/deploy-ecs.sh重新部署时,scripts/deploy-ecs.sh 会先备份 /opt/codeverse-ops/dev.db,替换应用文件后再恢复数据库并执行增量迁移。重要数据仍建议在部署前单独备份。部署脚本自动完成:阶段操作预期结果1/6安装 Node.js 20、PM2、Nginx、SQLite输出各工具版本2/6备份数据库,替换 /opt/codeverse-ops 中的应用文件并恢复数据项目文件部署完成,历史数据保留3/6将 .env.production 复制为 .env应用可读取配置4/6执行 npm ci、Prisma 生成、迁移和 next build数据表和生产构建生成5/6使用 PM2 启动 npm startcodeverse-ops 状态为 online6/6配置 Nginx,将 80 端口代理到 3000nginx -t 成功并重载部署脚本结束时会输出访问地址。请以实际 ECS 公网 IP 为准:http://<ECS_IP>说明:脚本末尾可能显示脚本内预置的示例 IP,该值不一定是当前 ECS 地址,不应作为访问依据。图 4-2 PM2 启动成功且 Nginx 配置校验通过4.5 部署结果验证依次执行:node -v npm -v pm2 status systemctl is-active nginx curl -I http://127.0.0.1:3000 curl -I http://127.0.0.1预期结果:Node.js 主版本为 v20;PM2 中 codeverse-ops 状态为 online;Nginx 状态为 active;两次 curl 均返回 HTTP 200、301 或 307 等正常响应,而不是连接失败。检查数据库:cd /opt/codeverse-ops sqlite3 dev.db ".tables" 预期至少看到与以下模型对应的数据表:BatchGroup CloudLog Conversation Message QualityScore Snippet Task最后,在浏览器访问 http://<ECS_IP>。首页应显示“代码重构”“日志诊断”“仪表盘”和“收藏库”等入口。图 4-3 通过 ECS 公网地址访问 CodeVerse-Ops图 4-4 首页功能入口、核心特性和任务统计五、功能体验5.1 智能代码重构在首页单击 代码重构;保持 单文件 模式;选择 javascript,单击 快捷模板 > 回调地狱;也可粘贴自己的代码;单击 提交重构;提交后等待 MaaS 返回完整结果。当前版本在此阶段可能仅显示按钮处于处理中;页面连接任务 SSE 接口并显示“重构完成”后,查看 TypeScript 结果和优化点;单击 对比查看,检查原代码与重构代码差异;查看五维质量雷达图,比较原始代码和重构代码;使用复制、导出或收藏功能保存结果。图 5-1 提交代码并获得 TypeScript 重构结果图 5-2 对比重构前后代码并查看质量评分示例输入:function getUserData(userId, callback) { db.query("SELECT * FROM users WHERE id = ?", [userId], function (err, user) { if (err) return callback(err); db.query("SELECT * FROM orders WHERE userId = ?", [userId], function (err, orders) { if (err) return callback(err); callback(null, { user, orders }); }); }); } 验收标准:请求完成后页面显示任务成功状态、完整重构结果和任务 ID;结果包含带明确类型的 TypeScript 代码;优化说明能够指出异步流程、错误处理或类型安全等改进;雷达图至少展示安全性、可维护性、性能、可读性和类型安全五个维度。注意:当前重构提示词统一要求输出 TypeScript。即使输入 Python、Java、Go、PHP、Ruby、C 或 C++,输出目标仍是 TypeScript。5.2 批量代码重构进入 代码重构,切换到 批量;单击 添加文件,填写文件名、语言和代码内容;重复添加多个文件;单击批量提交按钮,查看总体和单文件处理状态;等待各文件状态更新为 COMPLETED 或 FAILED。限制条件:单次最多 20 个文件;接口以 JavaScript 字符串长度统计总量,上限约 500 万字符;该限制不等同于严格的 UTF-8 字节大小;每个文件会创建独立任务,并归属同一个批次;批量处理消耗的模型 Token 通常高于单文件处理,请控制测试代码规模。当前版本说明:批量页面仅展示文件名、语言和任务状态,暂不提供单个文件的重构结果详情入口。5.3 云原生日志故障诊断在首页单击 日志诊断;选择 CCE(云容器引擎);单击 快捷模板 > CCE OOMKilled;单击 提交诊断;等待同步分析完成,查看根因分析和 YAML 修复建议;再选择 FunctionGraph(函数工作流),使用“函数超时”模板重复体验。图 5-3 提交 FunctionGraph 故障日志并查看根因图 5-4 查看结构化修复建议并继续追问示例输入:Warning OOMKilled pod/api-server-7d9f8b6c4-x2k9j Last State: Terminated Reason: OOMKilled Exit Code: 137 Restart Count: 5 Limits: cpu: 1, memory: 512Mi Requests: cpu: 500m, memory: 256Mi验收标准:根因分析能识别容器内存超限和退出码 137;修复建议包含调整 resources.requests、resources.limits 或排查内存泄漏的可执行方向;FunctionGraph 超时案例能给出超时时间、内存、数据读取方式等方面的排查建议。安全提示:提交真实日志前应删除账号、Token、密码、内网地址、用户数据等敏感信息。模型建议不可直接应用于生产集群。5.4 代码质量评分单文件重构完成后,页面会分别调用质量评分接口评估原始代码和重构代码。评分范围为 0~100:维度评估内容常见风险安全性注入、XSS、敏感信息、危险 API拼接 SQL、明文密钥、eval可维护性模块化、重复度、耦合度超长函数、重复逻辑、全局状态性能复杂度、I/O 和资源使用不必要的嵌套循环、重复请求可读性命名、结构、注释单字母变量、深层嵌套类型安全类型覆盖与边界处理any、隐式转换、空值未处理评分由大模型生成,适合辅助比较,不等同于静态代码扫描、单元测试或安全审计结果。当前版本说明:重构页面会展示原始代码和重构代码的即时评分,但页面请求暂未携带 taskId,因此这些评分不会写入 QualityScore 表,仪表盘“质量评分趋势”可能为空。这不影响雷达图展示和其他任务统计。5.5 AI 上下文对话在重构或诊断结果页单击 继续对话;输入针对当前结果的问题,例如“请解释此处的类型设计”或“如何验证该 YAML 修复有效”;查看流式回复;收起对话面板后再次打开,确认历史消息仍可显示。对话消息会写入 SQLite,但服务端用于连续推理的内存上下文有效期为 30 分钟,每 5 分钟清理一次。重新打开“继续对话”面板时,应用会读取持久化消息并重建上下文;如果面板保持打开期间上下文过期,接口会提示重新创建。刷新页面后,当前结果和 taskId 会丢失,现有页面没有从仪表盘重新进入原任务详情的入口。5.6 历史任务仪表盘完成至少一次代码重构和一次日志诊断;进入 仪表盘;查看总任务数、重构次数、诊断次数和成功率;查看近 30 天趋势、任务类型分布、状态分布、质量评分趋势和最近任务;单击 刷新,或保持 30 秒自动刷新。图 5-5 查看任务总量、成功率和近 30 天趋势图 5-6 查看任务分布、质量趋势和最近任务若仪表盘为空,请先确认任务已成功写入数据库,再刷新页面。5.7 代码片段收藏库在代码重构结果页单击 收藏;进入 收藏库;使用关键词或编程语言筛选收藏;复制或导出收藏结果;单击 删除 并确认,可移除不再需要的收藏。图 5-7 搜索、复制、导出或删除收藏内容日志诊断结果也提供收藏入口。收藏前请确认结果中不含敏感日志。5.8 命令面板与主题按 Ctrl+K(macOS 为 Command+K)打开命令面板;输入“重构”“诊断”“仪表盘”“收藏”或“主题”等关键词;使用方向键选择命令,按 Enter 执行,按 Esc 关闭;可通过页面导航切换明暗主题。图 5-8 使用命令面板快速导航图 5-9 切换为浅色主题六、运行维护与故障排查6.1 常用运维命令# 查看进程 pm2 status # 查看最近日志 pm2 logs codeverse-ops --lines 100 # 重启应用 pm2 restart codeverse-ops # 查看 Nginx 状态与配置 systemctl status nginx --no-pager nginx -t # 查看端口监听 ss -lntp | grep -E ':80|:3000' # 查看磁盘和内存 df -h free -h # 查看数据库表和最近任务 cd /opt/codeverse-ops sqlite3 dev.db ".tables" sqlite3 dev.db \ "SELECT id, type, status, language, createdAt FROM Task ORDER BY createdAt DESC LIMIT 10;" 修改 .env 后必须重启应用:cd /opt/codeverse-ops pm2 restart codeverse-ops --update-env6.2 常见问题现象可能原因处理方法浏览器无法访问 http://<ECS_IP>安全组未开放 80、Nginx 未启动、EIP 错误检查安全组、systemctl status nginx 和 ECS 公网 IP502 Bad GatewayNext.js 进程未启动或 3000 端口未监听执行 pm2 status、pm2 logs codeverse-ops,重启 PM2返回 401 或 403API Key 无效、模型未开通、账号区域不匹配重新查看 MaaS 调用说明并创建 API Key返回 404MaaS 基础地址配置错误确保地址不包含 /v1/chat/completions,国内站填写 https://api.modelarts-maas.com/openai页面提示“系统配置异常”环境变量缺失检查 /opt/codeverse-ops/.env 中两个 HUAWEI_MAAS_* 变量AI 请求长时间无响应或连接中断单次 MaaS 调用超时为 120 秒,普通调用最多尝试 3 次缩短输入并检查 MaaS 状态;Nginx 已配置 400 秒读取超时,生产环境仍应结合调用策略统一超时对话流式输出中断Nginx、浏览器网络或模型连接中断检查 PM2/Nginx 日志,重新打开对话面板后重试首轮重构或诊断没有逐 Token 输出当前提交接口同步完成 MaaS 调用后才连接任务 SSE这是当前版本的实现行为;等待请求完成,以最终结果为准next build 被系统终止ECS 内存不足使用 4 GiB 或更高规格,停止无关进程后重试Prisma 报数据库不存在或无表DATABASE_URL 错误或迁移失败恢复 file:../dev.db,执行 npx prisma generate && npx prisma migrate deploy仪表盘有任务但无质量趋势当前重构页面的评分请求未携带 taskId这是当前版本已知限制,不影响即时雷达图和其他任务统计批量任务拒绝提交文件数或字符串总长度超限保持不超过 20 个文件、代码总量约 500 万字符以内6.3 重新构建与升级更新代码后,在 ECS 执行:cd /opt/codeverse-ops npm ci npx prisma generate npx prisma migrate deploy npm run build pm2 restart codeverse-ops --update-env执行数据库迁移前建议备份:cd /opt/codeverse-ops cp dev.db "dev.db.backup.$(date +%Y%m%d%H%M%S)" 6.4 生产化建议本案例以快速体验为目标。用于团队或生产环境前,至少应补充:使用 IAM、统一身份认证或应用登录保护所有页面和 API;使用 ELB/Nginx 配置 HTTPS 证书,禁止明文传输代码和日志;将 API Key 存储到云凭据管理服务,避免落盘和终端输出;使用云数据库替代单机 SQLite,并建立自动备份;将内存对话上下文迁移到 Redis 等共享存储,支持多实例;增加请求限流、输入大小限制、审计日志和敏感信息脱敏;对模型生成代码执行静态扫描、单元测试和人工评审;对模型生成的运维命令和 YAML 建立审批及灰度验证流程;配置 AOM、LTS 或其他可观测服务监控 CPU、内存、错误率和模型调用延迟。七、释放资源7.1 删除 ECS登录华为云控制台,进入 弹性云服务器 ECS > 实例;选择本案例创建的 ECS;单击 更多 > 删除;根据页面提示勾选释放绑定的 EIP、删除系统盘和数据盘;确认资源名称和影响范围后完成删除。删除后再次检查 ECS、云硬盘和 EIP 列表,确认没有遗留按需资源。7.2 处理 MaaS 资源进入 MaaS 控制台 > 模型推理 > 在线推理:预置模型通常按实际调用量计费,停止调用后不会继续产生推理 Token;删除不再使用的 API Key,降低泄露风险;如创建过专属部署实例或其他持续计费资源,请停止并删除;在费用中心检查账单和代金券使用情况。7.3 删除本地敏感文件不再使用项目时,可删除包含 API Key 的部署包和环境变量文件:# Linux/macOS rm -f codeverse-ops-deploy.tar.gz rm -f codeverse-ops/.env.productionWindows PowerShell 执行:Remove-Item .\codeverse-ops-deploy.tar.gz -ErrorAction SilentlyContinue Remove-Item .\codeverse-ops\.env.production -ErrorAction SilentlyContinue若 API Key 曾出现在公开仓库、日志或截图中,应立即在 MaaS 控制台删除并重新创建。八、扩展资料华为云 MaaS OpenAI 兼容接口说明华为云 MaaS 模型列表弹性云服务器 ECS 文档弹性公网 IP 文档云容器引擎 CCE 文档函数工作流 FunctionGraph 文档九、案例验收清单完成以下检查即表示案例体验成功:[ ] 已开通 DeepSeek-V4-Flash,并使用华为云 MaaS API Key 完成接口验证;[ ] 如实践第三章,已通过码道完成 spec.md、design.md、tasks.md 和分阶段任务执行;[ ] ECS、EIP 和安全组配置完成;[ ] codeverse-ops 在 PM2 中为 online,Nginx 为 active;[ ] 浏览器可通过 ECS 公网 IP 打开首页;[ ] 单文件代码重构可通过任务 SSE 接口收到 complete 结果;[ ] 批量重构可显示批次和单文件状态;[ ] CCE 或 FunctionGraph 日志可生成根因分析和修复建议;[ ] 质量雷达图可展示原始代码与重构代码对比;[ ] AI 对话可逐段显示回复,仪表盘和收藏库可正常使用;[ ] 已确认模型输出仅作辅助并经过人工复核;[ ] 体验结束后已释放不再使用的计费资源和 API Key。
  • [高校训练营] 基于华为云码道(CodeArts)代码智能体与 ECS 的 CoursePilot:AI 个性化学习闭环开发实践
    一、概述1.1 案例介绍在课程学习中,学生常常同时面对 PDF 讲义、Markdown 笔记、教材摘录和练习题等多种资料。传统学习工具通常只能解决“保存资料”或“回答问题”中的某一个环节,难以持续回答下面几个问题:一门课程到底包含哪些知识点,它们之间有什么层级和前置关系?学生目前真正薄弱的是哪些知识点,判断依据是什么?学习计划能否根据实际作答结果自动调整?AI 给出的知识点、题目和回答是否有课程资料依据?当模型或外部服务不可用时,核心学习流程能否继续运行?基于这些问题,我利用华为云码道(CodeArts)智能体开发了 CoursePilot。它不是一个只负责聊天的通用助手,而是一个以课程资料和学习证据为基础的 AI 个性化学习教练 Agent。系统围绕以下闭环工作:注册登录 → 创建课程 → 添加资料 → 构建知识结构 → 设置学习目标 → 初始诊断 → 生成知识画像 → 制定学习计划 → 学习与练习 → 错因分析 → 更新掌握度 → 动态调整计划 项目仓库:cid:link_7项目地址:115.120.251.21(由于成本限制,该IP发布帖子几日后可能会释放!)演示视频:项目仓库根目录 demo视频.mp41.2 核心设计原则课程无关:不把业务逻辑绑定到某一门固定课程。资料驱动:知识点、题目和学习辅导尽量建立在用户资料之上。来源可追溯:知识点和 AI 生成题目保留对应资料与分块来源。证据驱动:掌握度来自真实作答、难度、耗时和提示使用情况。人机协同:AI 负责提取、生成和辅助判断,用户保留确认与修正权。可解释与可审计:重要算法采用确定性规则,Skill 与 MCP 调用保存日志。可降级:大模型不可用时,资料解析、诊断和掌握度更新等核心流程仍可运行。1.3 适用对象希望完成 AI Agent 项目实践的高校学生;学习 Vue 3、FastAPI、MCP、Skill 与 Docker 的开发者;需要搭建课程资料管理、诊断或个性化学习系统的团队;希望了解如何将本地全栈应用部署到华为云 ECS 的开发者。1.4 案例时间本案例总时长预计240分钟。1.5 案例流程本案例采用“需求规格—架构设计—任务拆解—分阶段开发—测试验证—云端部署—迭代优化”的流程完成 CoursePilot 的设计与实现。使用华为云码道(CodeArts)代码智能体辅助完成需求分析,编写产品规格、功能需求和用户流程文档,明确 CoursePilot 的产品定位、功能范围、验收条件以及“资料驱动、证据驱动、来源可追溯”等核心原则,定义系统“做什么”。完成系统架构与技术方案设计,确定 Vue 3、FastAPI、SQLAlchemy、MCP、Skill 和 Docker Compose 技术栈,并编写领域模型、总体架构、MCP 设计、Skill 设计及关键算法 ADR,定义系统“怎么做”。根据需求和架构生成开发路线及阶段任务清单,将项目拆分为课程资料、知识结构、题库诊断、知识画像、学习计划、学习 Agent、MCP/Skill、学习看板和云端部署等可独立验收的开发任务。按照任务清单逐步开发:搭建 FastAPI 后端和 Vue 3 前端,实现用户认证、课程管理、资料解析、知识结构生成、AI 辅助出题、动态诊断、掌握度计算、个性化学习计划及渐进式辅导 Agent。建立 CoursePilot MCP Server,封装课程资料、题库、作答记录、学习状态和计划管理等工具;同时实现资料结构化、学习诊断、计划生成和苏格拉底式辅导等可插拔 Skill。使用码道代码智能体辅助进行跨文件代码审查、缺陷定位和测试补充;后端及 MCP Server 使用 Pytest 和 Ruff 验证,前端使用 TypeScript 类型检查、ESLint 和 Vite 生产构建验证。使用 Docker Compose 完成前端、后端和 MCP Server 的容器化编排,并部署至华为云 ECS;结合华为云 SWR 镜像加速解决基础镜像拉取问题,使用 Alembic 完成数据库迁移,并通过健康检查和容器日志验证服务状态。根据实际使用结果持续迭代,修复文件上传 413、AI 长任务 504、生成题目知识点 ID 越界、诊断中断后无法继续等问题,进一步提升系统的数据一致性、容错能力和用户体验。1.6 资源总览资源名称本案例使用规格主要用途计费说明弹性云服务器 ECS通用计算增强型 ac9s.large.2;2 vCPU;4 GiB;Ubuntu 24.04 Server 64 位;60 GiB 通用型 SSD运行前端、FastAPI 后端和 MCP Server 容器0.3452元/小时 弹性公网 IP EIP全动态 BGP;按流量计费;5 Mbit/s提供网站公网访问及 SSH 运维入口0.8元/GB虚拟私有云 VPC 和安全组1 个 VPC、1 个子网、1 个安全组提供私有网络及端口访问控制免费容器镜像服务 SWR使用个人专属镜像加速地址加速拉取 Python、Node.js 和 Nginx 等 Docker 基础镜像免费华为云码道(CodeArts)代码智能体专业版辅助需求分析、架构设计、任务拆解、代码开发、测试及问题定位专业版,139元/6000万tokens免排队MaaS - Console个人使用deepseek-v4-flash用于知识结构优化、AI 辅助出题及学习辅导输入:1元/百万tokens  输出:2元/百万tokensECS 本地存储SQLite 数据库及课程上传目录,共用 ECS 系统盘保存业务数据、课程资料和调用记录已包含在本案例 ECS 云硬盘配置中二、系统方案设计2.1 技术栈层级技术选型前端Vue 3、TypeScript、Pinia、Vue Router、Vite、AxiosWeb 服务Nginx后端Python 3.11、FastAPI、Pydantic、异步 SQLAlchemy数据迁移AlembicAgent 协议Model Context Protocol(MCP)业务能力4 个可插拔 Skill大模型接入OpenAI 兼容 Provider,用户自行配置模型数据库SQLite(案例演示);可切换 PostgreSQL容器化Docker、Docker Compose云资源华为云弹性云服务器 ECS、弹性公网 IP、安全组代码托管GitCodeAI 辅助开发华为云码道(CodeArts)代码智能体2.2 总体架构用户浏览器 │ ▼ Nginx / Vue 3 前端(80/443) │ /api/* ▼ FastAPI 后端(容器内部 8000) ├── SQLAlchemy / Alembic ── SQLite 或 PostgreSQL ├── 课程资料与上传文件 ├── LLM Provider ───────── 用户配置的大模型服务 └── MCP Client │ Streamable HTTP ▼ MCP Server(容器内部 8001) ├── 13 个业务工具 └── 4 个 CoursePilot 运行时 Skill2.3 项目结构CoursePilot/ ├── backend/ # FastAPI、领域模型、服务、Alembic 与测试 ├── frontend/ # Vue 3 前端 ├── mcp-server/ # MCP Server 与业务工具 ├── skills/ # 4 个 CoursePilot 运行时 Skill ├── docs/ # 需求、架构、ADR、验收与阶段报告 ├── AGENTS.md # 项目技术规范与协作约束 ├── docker-compose.yml └── README.md2.4 MCP 与 Skill 设计CoursePilot 的 MCP Server 提供 13 个业务工具,分为四类:课程与资料:课程列表、课程结构、资料检索、资料来源;学习状态:学生画像、知识点掌握度、错题;题库与作答:题目搜索、题目详情、保存作答;计划与掌握度:读取计划、更新计划、更新掌握度。系统还实现了 4 个运行时 Skill:Skill作用course_material_structuring将课程资料整理为知识结构learning_diagnosis根据作答证据分析学习状态和错因study_plan_generator生成及动态调整学习计划socratic_tutor使用分级提示进行启发式辅导三、使用华为云码道进行规范驱动开发3.1 建立项目上下文CoursePilot 涉及课程资料、题库、诊断、知识画像、计划、Agent、MCP 和 Skill 等多个领域。如果只用一句话要求 AI “生成一个学习平台”,很容易得到功能堆叠但规则不一致的代码。因此,本项目先在仓库中沉淀以下上下文:AGENTS.md:技术栈、目录结构、编码规范和测试命令;docs/product-spec.md:产品定位、范围和冻结决策;docs/requirements.md:功能需求与验收条件;docs/domain-model.md:领域实体、关系与约束;docs/architecture.md:系统边界与调用链;docs/adr/:掌握度算法、学习计划算法、Agent 编排等架构决策。3.2 各阶段Prompt每次使用时,可以先附加这段通用要求:请先阅读 AGENTS.md、本阶段相关设计文档和现有代码。 开始修改前必须: 1. 说明当前实现基线; 2. 给出任务拆解、影响文件和数据迁移方案; 3. 明确本阶段边界; 4. 不修改与本阶段无关的模块; 5. 不覆盖用户已有修改; 6. 实现后运行相关自动化测试和质量检查; 7. 最后报告修改文件、测试结果、未完成项和已知限制。 所有新增API统一放在 /api/v1/ 下。 后端IO操作优先使用 async/await。 数据库结构变更必须使用Alembic,不使用create_all代替迁移。 前端使用Vue 3、TypeScript、Pinia和<script setup lang="ts">。前置阶段:需求与规格设计请作为产品经理和系统架构师,为 CoursePilot 建立完整的需求与设计基线。 项目定位: CoursePilot 是一个课程无关、资料驱动、证据驱动、来源可追溯的AI个性化学习教练。系统需要形成: 创建课程 → 添加资料 → 构建知识结构 → 设置学习目标 → 初始诊断 → 知识画像 → 学习计划 → 学习与练习 → 错因诊断 → 掌握度更新 → 动态调整计划 请检查当前项目骨架,并编写或完善: - docs/product-spec.md - docs/requirements.md - docs/mvp-acceptance.md - docs/user-flows.md - docs/domain-model.md - docs/skill-design.md - docs/mcp-design.md - docs/development-roadmap.md - docs/current-gap-analysis.md 具体任务: 1. 定义目标用户、用户痛点、产品定位和产品边界; 2. 将需求划分为Must、Should、Could和Won't; 3. 为每项Must需求定义正常流程、异常流程和验收条件; 4. 使用Given/When/Then编写可执行验收标准; 5. 设计课程、资料、知识点、题目、诊断、画像、计划和Agent等领域实体; 6. 设计4个业务Skill及13个MCP工具; 7. 冻结掌握度、简答题、诊断题数量、模型Provider、账号体系和课程无关性决策; 8. 将开发工作拆分为阶段0至阶段7; 9. 明确每个阶段的目标、任务、边界、验收标准和交付物。 本阶段只编写需求和设计文档,不修改业务代码。 不得提前将尚未实现的功能标记为完成。阶段0:可运行基础设施基线请执行 CoursePilot 阶段0:可运行基础设施基线。 阶段目标: 让FastAPI后端、Vue前端、异步数据库、Alembic和MCP Server形成可启动、可测试的基础工程。 具体任务: 1. 修复FastAPI启动流程,确保GET /health返回200; 2. 建立统一的SQLAlchemy Base、异步engine和AsyncSession; 3. 配置Alembic target_metadata及异步迁移环境; 4. 验证upgrade head、downgrade base、再次upgrade head; 5. 统一Python模块路径和项目依赖,消除循环引用; 6. 修复Vue 3开发启动、TypeScript检查、ESLint和生产构建; 7. 将MCP Server统一为Streamable HTTP传输,端点为/mcp; 8. 确定FastAPI后端是唯一MCP Client,移除前端直连MCP的设计; 9. 修复后端、前端和MCP Server的Dockerfile及docker-compose.yml; 10. 建立后端健康检查、MCP连通性和前端页面加载冒烟测试; 11. 更新AGENTS.md和docs/deployment.md中的启动命令。 阶段边界: - 不实现课程CRUD; - 不实现资料解析; - 不创建完整业务领域模型; - 不实现正式业务Skill和MCP工具; - 不接入真实大模型; - 不实现完整注册、登录和管理员后台。 验收要求: - 后端、前端和MCP Server均可独立启动; - Alembic往返迁移通过; - MCP Streamable HTTP调用通过; - 前端type-check、lint和build通过; - docker compose config验证通过。阶段1:课程、资料与知识结构闭环请执行 CoursePilot 阶段1:课程、资料和知识结构垂直闭环。 请重点阅读: - docs/product-spec.md - docs/requirements.md中的FR-001至FR-003 - docs/domain-model.md - docs/user-flows.md中的流程1至流程4 - docs/mvp-acceptance.md中的AC-001至AC-003 阶段目标: 完成“创建课程→添加资料→解析资料→形成知识结构”的完整闭环。 具体任务: 1. 创建Course、CourseMaterial、MaterialChunk、KnowledgePoint和KnowledgeRelation模型; 2. 编写对应Alembic迁移、约束、外键和索引; 3. 实现课程创建、列表、详情、编辑和软删除API; 4. 实现PDF、Markdown、TXT文件上传及文本粘贴; 5. 实现资料状态、失败原因、重试和删除; 6. 实现规则型文本提取和资料分块; 7. 保存文件名、页码、章节或字符范围等来源信息; 8. 实现知识点新增、编辑、删除、排序和父子层级; 9. 实现prerequisite、contains和related知识关系; 10. 防止知识点关系自引用和循环依赖; 11. 实现课程列表、课程详情、资料管理和知识结构页面; 12. 使用两门内容不同的课程验证业务代码没有学科硬编码。 阶段边界: - 不实现题库和诊断; - 不实现知识画像、掌握度和学习计划; - 不实现正式业务Skill和MCP工具; - 不调用真实大模型。 验收要求: 用户能够创建课程,上传或粘贴资料,查看解析状态、资料分块和来源,并获得可编辑的树形知识结构。阶段2:题库、诊断与作答记录请执行 CoursePilot 阶段2:题库、初始诊断和作答记录。 请重点阅读: - requirements.md中的FR-004、FR-006和FR-010 - mvp-acceptance.md中的AC-004、AC-006和AC-010 - product-spec.md中的D-002和D-003 - domain-model.md中的题目、诊断和作答实体 阶段目标: 完成“建立题库→开始诊断→逐题作答→完成诊断”的业务流程。 具体任务: 1. 创建Question、QuestionOption和QuestionSource模型; 2. 创建question_knowledge_point多对多关联表; 3. 支持单选题、判断题和简答题; 4. 实现题目新增、编辑、删除、列表、筛选和审核状态; 5. 手动题目默认confirmed,AI或导入题目默认pending; 6. 题目必须关联至少一个当前课程知识点; 7. 保存题目对应的资料分块和来源位置; 8. 创建DiagnosticAttempt和AnswerRecord; 9. 按D-003规则选择诊断题: target_count = min(max(核心知识点数量, 10), 20); 10. 题库不足时阻止诊断并提示用户补充; 11. 诊断开始时保存不可变题目快照; 12. 保存答案、正确性、作答时间、跳过状态、提示次数和最高提示等级; 13. 实现L1至L4渐进式提示,L4完整解析需要二次确认; 14. 实现题库、诊断作答和诊断结果前端页面; 15. 为AI辅助出题预留接口,但本阶段不接入真实模型。 阶段边界: - 不计算知识画像和最终掌握度; - 不实现错因诊断; - 不实现学习目标和学习计划; - 不实现业务Skill、正式MCP工具和Agent。 验收要求: 用户能够管理题库并完成一次10至20题的诊断;系统保存完整作答证据,诊断题响应不得提前泄露正确答案和解析。阶段3:知识画像、错因诊断与掌握度请执行 CoursePilot 阶段3:知识画像、错因诊断和掌握度算法。 请重点阅读: - requirements.md中的FR-007、FR-011和FR-012 - mvp-acceptance.md中的对应验收条件 - product-spec.md中的D-001和D-002 - docs/adr/ADR-003-mastery-algorithm.md 阶段目标: 将用户作答记录转换为确定、可解释、可追溯的知识画像。 具体任务: 1. 创建MasteryRecord和ErrorDiagnosis模型及Alembic迁移; 2. 实现mastery-v1确定性掌握度算法; 3. 掌握度范围为0至100,置信度范围为0至1; 4. 算法考虑正确性、难度、作答时间、提示等级、连续错误、时间间隔和前置知识; 5. 使用Decimal和ROUND_HALF_UP,禁止依赖浮点round; 6. 每次有效证据追加MasteryRecord,不覆盖历史记录; 7. 保存旧值、新值、计算依据、变化原因和关联AnswerRecord; 8. 保证同一作答记录不会重复生成掌握度记录; 9. 实现10类规则型错因判断; 10. 保存错因类型、诊断依据、置信度、建议行动和关联知识点; 11. 支持用户确认或修改错因; 12. 实现知识画像列表和掌握度证据详情API; 13. 实现掌握度、置信度、薄弱点、待复习和证据链前端页面。 阶段边界: - 大模型不能直接计算或写入掌握度; - 本阶段不得调用真实LLM; - 不实现学习目标、学习计划和Agent; - 不实现正式业务Skill和MCP工具。 验收要求: 相同输入必须产生相同掌握度结果,每次变化均可追溯到具体作答记录;未经确认的简答题不得影响掌握度。阶段4:学习目标、计划与动态调整请执行 CoursePilot 阶段4:学习目标、个性化学习计划与动态调整。 请重点阅读: - requirements.md中的FR-005、FR-008和FR-013 - mvp-acceptance.md中的对应验收条件 - docs/adr/ADR-004-study-plan-algorithm.md 阶段目标: 根据学习目标、知识画像、知识点关系和时间约束生成确定、可解释的学习计划。 具体任务: 1. 创建LearningGoal、StudyPlan和StudyTask模型及迁移; 2. 每个用户每门课程只维护一个LearningGoal; 3. 支持目标日期、目标掌握度、每日时长和每周学习日; 4. 实现study-plan-v1确定性计划算法; 5. 根据掌握度差距、重要性、复习状态、连续错误和前置关系计算优先级; 6. 使用Kahn算法对前置关系稳定拓扑排序; 7. 检测知识点关系环; 8. 将任务分配到目标日期范围内的可用学习日; 9. 每日总时长不得超过daily_minutes; 10. 超过60分钟的任务拆分为多个子任务; 11. 容量不足时返回结构化错误和调整建议; 12. 每个任务保存generation_reason和generation_basis; 13. 支持完成、跳过、延期和手动调整; 14. 支持评估是否需要重新规划; 15. 重新规划时将旧计划设为superseded,并通过previous_plan_id保留历史; 16. 实现学习目标、当前计划和历史计划前端页面。 阶段边界: - 不调用真实大模型; - 不实现Agent、业务Skill和正式MCP工具; - 不实现错题本、学习看板、日历同步和消息推送。 验收要求: 计划生成结果可重复、可解释,不违反前置关系和时间容量;用户操作任务后能够评估调整需求并保留计划版本历史。阶段5:Skill、MCP、Agent 与 LLM Provider请执行 CoursePilot 阶段5:业务Skill、MCP工具、Agent和LLM Provider。 请重点阅读: - docs/skill-design.md - docs/mcp-design.md - docs/adr/ADR-005-agent-provider-and-orchestration.md - 阶段1至阶段4已经实现的业务服务 阶段目标: 建立可配置、可审计、可降级的CoursePilot Agent体系。 具体任务: 1. 删除course_recommend、schedule_optimizer和learning_analyzer占位Skill; 2. 实现4个正式Skill: - course_material_structuring - learning_diagnosis - study_plan_generator - socratic_tutor 3. 每个Skill包含skill.py、config.yaml和async execute(params); 4. Skill不直接操作数据库,通过业务服务或MCP工具获取数据; 5. 实现13个正式MCP业务工具; 6. 将MCP工具划分为只读工具和写入工具; 7. MCP Server通过BackendGateway调用FastAPI业务API; 8. 前端不得直接连接MCP Server; 9. 实现可配置的LLM Provider抽象; 10. 支持Mock Provider和OpenAI兼容Provider; 11. 自动测试只能使用Mock/Fake Provider; 12. 创建AgentSession、AgentMessage和ToolCallLog; 13. 实现Agent会话创建、消息发送、历史查询和结束会话; 14. 实现L1至L4苏格拉底式辅导; 15. 标记course_material、ai_supplement、mixed和unverified来源; 16. 所有Skill和MCP调用保存审计记录; 17. 对API Key、Token、Cookie、密码和密钥进行递归脱敏; 18. Agent写操作必须先请求用户确认; 19. 实现Agent对话和来源展示前端页面; 20. 实现Provider和MCP不可用时的规则降级。 阶段边界: - 不实现错题本和学习看板; - 不实现管理员后台; - 不允许把具体模型写成不可替换依赖; - Skill不得复制确定性掌握度和计划算法。 验收要求: 4个Skill和13个MCP工具能够独立调用;Agent可读取课程资料、画像和计划,能够恢复会话、显示来源、记录调用并在模型不可用时降级。阶段6:错题本、看板与日志展示请执行 CoursePilot 阶段6:完整前端交互、错题本、学习看板和调用日志展示。 请先检查阶段1至阶段5的数据模型和业务调用链,特别是: - AnswerRecord - DiagnosticAttemptQuestion不可变快照 - ErrorDiagnosis - MasteryRecord - StudyPlan和StudyTask - AgentSession和ToolCallLog 阶段目标: 补齐学习数据展示、错题复习和完整前端体验。 具体任务: 1. 实现WrongQuestionState模型及Alembic迁移; 2. 按user_id、course_id和question_id聚合错题; 3. 错题内容优先读取不可变题目快照; 4. 仅将有效错误作答计入错误次数; 5. 支持按知识点、错因、状态和关键词筛选; 6. 展示历史错误、资料来源、错因证据和掌握度证据; 7. 支持标记已掌握; 8. 用户后续再次答错时自动重新打开错题状态; 9. 复用DiagnosticAttempt体系创建单题练习; 10. 实现学习看板10类确定性指标; 11. 展示今日任务、总体进度、掌握度分布、薄弱点、待复习项、错因分布、本周有效作答时长和计划完成率; 12. 实现课程级ToolCallLog查询; 13. 支持类型、状态、工具、会话、时间和分页筛选; 14. 保存日志和查询输出时均执行敏感信息脱敏; 15. 实现错题本、看板和调用日志前端页面; 16. 完善加载状态、错误提示、空状态、导航、路由参数和刷新恢复。 阶段边界: - 不修改4个Skill核心逻辑; - 不修改13个MCP工具契约; - 不修改mastery-v1和study-plan-v1; - 不实现管理员后台和阶段7部署功能。 验收要求: 错题复习、学习看板和调用日志形成前后端闭环;跨用户访问统一返回404;页面刷新后数据可以从API恢复。3.3 Skill前端美化AI直接生成的前端通常不符合我们的胃口,存在以下问题:全站仍是系统默认字体、同一字号层级和同一种 8px 圆角,页面缺少品牌辨识度。紫色高饱和主色、纯白卡片加灰边框在所有页面重复,是典型的通用 AI 后台视觉。顶栏只是文本平铺,当前页面反馈弱,宽屏松散、窄屏拥挤。首页、课程列表和登录页过度居中,信息层级单薄;题库等高频页面则过密。按钮、表单、弹窗样式在各页面重复且状态不统一,Hover、Pressed、Focus 反馈不足。加载和空状态大多只是一行文字,视觉完成度不足。因此我们可以为Code添加Skill对前端进行美化我们选用GitHub - Leonxlnx/taste-skill: Taste-Skill - gives your AI good taste. stops the AI from generating boring, generic slop · GitHub 这个67.7k Star的Github开源skill进行优化请你根据skill修改现有前端界面,做的更好看一些效果也是很明显:美化前首页美化后首页四、核心功能实现具体核心功能展示请参考仓库内的demo视频,或者通过打开网站或本地部署实际操作,这里简单展示一下界面和操作功能4.1 从课程资料生成可追溯知识结构用户可以上传 PDF、Markdown、TXT 文件,或者直接粘贴文本。后端解析后将内容切分为资料块,并保存文件、位置与内容之间的对应关系。知识结构生成时,系统不会只保存一个无法解释的标题,而是将知识点关联到原始资料。用户可以查看、调整层级和关系,降低模型幻觉对后续诊断的影响。如果知识结构生成不清晰,你可以使用AI进行结构的优化,也可以手动进行修改,使结构更加清晰4.2 基于资料的 AI 辅助出题在题库管理界面你可以手动添加题目,也可以使用AI辅助出题AI 出题只允许引用当前课程中有效的知识点 ID 和资料块 ID。模型输出后,后端还会再次校验:题型和难度是否符合请求;knowledge_point_ids 是否属于允许范围;source_chunk_id 是否来自本次课程资料;选项、答案和解析结构是否完整。如果模型第一次返回了越界 ID,系统会把错误约束和合法范围反馈给模型并重试;连续失败时停止保存,避免产生半成品题目。4.3 测验与知识画像当题库足够完整,能够覆盖全部知识点时,可以进行测验与诊断:测验过程中可以申请不同等级的提示,或者跳过,但是这和答错一样会不同程度影响你的掌握度判定!系统不会让大模型直接决定最终掌握度,而是使用确定性规则综合以下证据:作答是否正确;题目难度;作答耗时;提示次数与提示等级;最近正确率;是否重复犯错;前置知识掌握情况。每次掌握度变化都会保存旧值、新值、变化原因和关联作答记录,用户能够查看“为什么发生了这次变化”。错题可以在“错题本”中进行复习,或者重新做题:4.4 学习计划与动态调整用户可以设置目标日期、目标掌握度、每日学习时长和每周可学习日期。系统根据知识画像、知识点重要程度、前置关系、历史错题和可用时间生成学习任务。当用户完成任务、连续答错或掌握度明显变化时,系统可以触发重新规划,并保留计划版本和调整原因。同时用户也可以在学习看板上查看一系列学习数据:4.5 渐进式学习辅导 Agent学习辅导 Agent 通过 MCP 工具读取当前课程资料、知识结构、学生画像和学习计划,再由 Skill 控制提示节奏:L1:提醒相关知识点;L2:指出思路方向;L3:给出关键步骤;L4:在用户确认后给出完整解析。回复通过 SSE 流式返回,并标记内容来自课程资料、AI 补充或混合来源。模型不可用时,系统可以降级为规则型提示。五、部署到华为云 ECS5.1 案例环境本案例采用一台华为云 ECS 完成演示部署:配置项案例选择区域华东-上海一ECS通用计算增强型,2 vCPU / 4 GiB操作系统Ubuntu 24.04 Server 64 位系统盘通用型 SSD,60 GiB公网访问弹性公网 IP,按流量计费,5 Mbit/s容器编排Docker Compose安全组:端口用途来源建议22SSH 运维仅允许管理员当前公网 IP /3280HTTP0.0.0.0/0443HTTPS0.0.0.0/05.2 登录服务器这里我采用的是密钥对登录:$key = "D:\EdgeDownload\KeyPair-e9f4.pem" icacls $key /inheritance:r icacls $key /grant:r "$($env:USERDOMAIN)\$($env:USERNAME):(R)" icacls $key先执行这一步是为了防止Window私钥文件权限过宽然后执行登录:ssh -i $key root@115.120.251.215.3 安装 Docker 和 Git登录 ECS 后执行:apt update apt install -y ca-certificates curl git install -m 0755 -d /etc/apt/keyrings curl -fsSL https://download.docker.com/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://download.docker.com/linux/ubuntu $(. /etc/os-release && echo ${UBUNTU_CODENAME:-$VERSION_CODENAME}) stable" \ > /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable --now docker docker --version docker compose version这里可能会出现报错,可能是因为访问 Docker 官方源被重置。直接改用华为云 Docker 镜像源即可。curl -fsSL https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu/gpg \ -o /etc/apt/keyrings/docker.asc chmod a+r /etc/apt/keyrings/docker.asc echo "deb [arch=$(dpkg --print-architecture) signed-by=/etc/apt/keyrings/docker.asc] https://mirrors.huaweicloud.com/docker-ce/linux/ubuntu $(. /etc/os-release && echo ${UBUNTU_CODENAME:-$VERSION_CODENAME}) stable" \ > /etc/apt/sources.list.d/docker.list apt update apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin systemctl enable --now docker5.4 克隆 CoursePilot输入:cd /opt git clone cid:link_7.git cd CoursePilot5.5 创建生产环境变量先生成三个密钥,分别复制输出结果:python3 -c "import secrets; print(secrets.token_urlsafe(48))" python3 -c "import secrets; print(secrets.token_urlsafe(48))" python3 -c "import base64,secrets; print(base64.urlsafe_b64encode(secrets.token_bytes(32)).decode())"创建环境变量文件:nano .env填入:SECRET_KEY=第一个随机值 MCP_INTERNAL_API_KEY=第二个随机值 LLM_CREDENTIAL_ENCRYPTION_KEY=第三个随机值 ALLOWED_ORIGINS=["http://你的EIP"]保存退出即可。5.6 添加持久化配置现有 Compose 没有持久化 SQLite 和上传文件,所以不要直接启动。创建覆盖文件:nano docker-compose.override.yml填入:services: backend: environment: DATABASE_URL: sqlite+aiosqlite:////data/coursepilot.db DEBUG: "False" SECRET_KEY: ${SECRET_KEY} LLM_CREDENTIAL_ENCRYPTION_KEY: ${LLM_CREDENTIAL_ENCRYPTION_KEY} MCP_INTERNAL_API_KEY: ${MCP_INTERNAL_API_KEY} MCP_SERVER_URL: http://mcp-server:8001/mcp UPLOAD_DIR: /data/uploads ALLOWED_ORIGINS: '${ALLOWED_ORIGINS}' volumes: - ./data:/data restart: unless-stopped frontend: restart: unless-stopped mcp-server: environment: BACKEND_API_URL: http://backend:8000/api/v1 MCP_INTERNAL_API_KEY: ${MCP_INTERNAL_API_KEY} restart: unless-stopped保存退出,创建数据目录:mkdir -p data/uploads chmod 700 data5.7. 构建并启动docker compose build --pull如果出现报错可能是因为Docker Hub 在大陆网络访问超时。需要给 Docker 配置华为云 SWR 镜像加速器。在华为云控制台:切换到“华东-上海一”。搜索并进入“容器镜像服务 SWR”。左侧选择“镜像资源 → 镜像中心”。点击“镜像加速器”。复制地址在ECS执行:mkdir -p /etc/docker nano /etc/docker/daemon.json填入复制的真实地址:{ "registry-mirrors": [ "https://xxxxxxxx.mirror.swr.myhuaweicloud.com" ] }保存退出即可!然后拉取基础镜像:docker pull python:3.11-slim docker pull node:20-alpine docker pull nginx:alpine三个都成功后,重新构建:cd /opt/CoursePilot docker compose build5.8 文件上传问题解决课程文件上传和 AI 知识结构优化都可能超过 Nginx 默认限制。可以在 /api/ 代理中补充:server { listen 80; server_name _; client_max_body_size 20m; location /api/ { proxy_pass http://backend:8000; proxy_set_header Host $host; proxy_set_header X-Real-IP $remote_addr; proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_connect_timeout 60s; proxy_send_timeout 300s; proxy_read_timeout 300s; } }修改后重新构建并启动前端容器:docker compose build frontenddocker compose up -d --no-deps frontend六、问题排查与踩坑复盘AI生成的代码在一些小细节上会出现疏忽和错误,同时部署过程中一些文件的配置不完全也可能会带来一些问题。这里是我列出的一部分可能会出现的问题可解决方案,如果大家部署过程中产生错误可参考以下内容:6.1 Docker Hub 连接超时现象failed to resolve source metadata for docker.io/library/python:3.11-slimdial tcp ...:443: i/o timeout原因ECS 访问 Docker Hub 不稳定,构建阶段无法获取基础镜像元数据。解决配置华为云 SWR 镜像加速器,先单独执行 docker pull 验证,再重新执行 Compose 构建。拉取完成后若 referrers 请求偶发超时,可重试构建。6.2 Alembic 找不到 app 模块现象ModuleNotFoundError: No module named 'app'原因迁移进程启动时,后端源码目录没有进入 Python 模块搜索路径。解决docker compose run --rm \ -e PYTHONPATH=/app/backend \ backend python -m alembic upgrade head6.3 上传课程资料返回 413现象Request failed with status code 413原因请求在进入 FastAPI 前就被 Nginx 的默认请求体大小限制拒绝。解决在 Nginx server 中设置 client_max_body_size,同时保证该值不小于后端允许的上传上限。6.4 AI 优化知识结构返回 504现象Request failed with status code 504原因模型需要读取多份资料并生成分层结构,耗时超过 Nginx 默认代理等待时间。解决提高 proxy_read_timeout 和 proxy_send_timeout。更长期的方案是将长任务改造成异步任务,并通过任务状态接口或 SSE 返回进度。6.5 模型返回越界知识点 ID现象第 4 道题结构不合法:knowledge_point_ids 不在允许范围内原因旧逻辑只重试题型和难度错误,知识点 ID 到保存阶段才校验,模型没有纠正机会。解决将知识点 ID 和资料块 ID 校验前移到模型重试阶段,反馈非法值与允许范围;连续失败则停止整批保存。6.6 诊断退出后无法再次进入现象该课程已有进行中的诊断,attempt_id=...原因后端正确阻止了重复创建,但前端没有恢复已有 attempt 的入口。解决将“开始诊断”设计为幂等操作:发现进行中的 attempt 时直接返回原记录,前端显示“继续诊断”,再从下一道未答题恢复。八、案例总结CoursePilot 的开发让我认识到,AI Agent 应用的难点不只是“接入一个大模型”,而是如何把模型放进一个可信、可解释、可恢复的业务闭环中。在开发阶段,华为云码道(CodeArts)代码智能体的价值主要体现在:通过 Codebase 理解跨前后端、MCP 与 Skill 的项目上下文;将自然语言需求拆解成可执行、可追踪的开发任务;在多文件修改、测试补充和日志排障中提高效率;结合仓库规范与验收条件,减少无边界生成;帮助整理从本地开发到 ECS 部署的完整过程。在运行阶段,CoursePilot 则通过资料来源、确定性算法、用户确认、调用审计和降级策略约束大模型,让 AI 真正服务于学习过程,而不是只生成看似合理的答案。九、参考资料华为云社区 HCSD 板块华为云码道(CodeArts)代码智能体产品介绍华为云码道(CodeArts)代码智能体下载安装CoursePilot GitCode 项目仓库
  • [高校训练营] 基于 Vue3 + FastAPI + 华为云 MaaS +华为云码道构建会议智脑应用
    1 、概述1.1 案例介绍企业日常会议产生大量记录文本,但缺乏高效的后续跟进手段:摘要靠人工整理、任务靠口头传达、风险靠经验判断。本案例将带你从零构建一款"会议智脑"应用——上传会议记录后,自动调用华为云 MaaS 大模型(DeepSeek V4 Flash)生成摘要、提取关键决策和任务清单,并通过可视化看板、甘特图、日历等多维度视图进行任务追踪与风险预警。1.2 适用对象企业开发者个人开发者1.3 案例时间  本案例总时长预计60分钟。1.4 案例流程  1. 领取华为云 MaaS 平台大模型 Tokens,获取 API Key 和模型接入地址;  2. 配置 .env 环境变量,将 MaaS API Key 等信息写入配置;  3. 初始化数据库并启动后端服务,验证 API 文档可访问;  4. 启动前端开发服务器,登录系统并上传会议记录,体验 AI 自动生成摘要与任务提取;  5. 在任务看板、甘特图、日历等视图中查看和管理提取的任务,触发风险检测。1.5 资源总览  本案例使用的华为云服务均为按需付费,预计花费不超过50元(MaaS Tokens 代金券可覆盖)。体验完成后请及时释放资源,避免产生多余的费用。资源名称规格单价(元)    华为云 MaaSDeepSeek V4 Flash 大模型推理服务代金券可覆盖华为云码道(CodeArts)代码智能体通用体验版免费2 、环境和资源准备2.1 领取华为云MaaS平台大模型Tokens福利   方式一: 登录华为开发者空间,参考案例《华为开发者空间 - ModelArts Studio大模型通用代金券领取使用指导》中的“二、 开通MaaS平台大模型”章节内容领取代金券,获取到模型的API地址、模型名称和API Key。   方式二: 登录华为开发者空间,参考案例《华为云MaaS平台大模型Tokens领取使用指导》中的“二、 领取MaaS平台大模型Tokens”章节内容,领取MaaS平台DeepSeek V3系列大模型Tokens代金券,购买ModelArts Studio DeepSeek Tokens套餐包,开通模型服务,最后获取到模型的API地址、模型名称和API Key。     2.2 安装本地开发环境本案例需要以下开发工具: 工具版本要求用途Python≥ 3.11后端运行时Node.js≥ 18.0前端构建npm≥ 9.0前端包管理Git≥ 2.30版本控制3 、构建会议智脑应用3.1 部署项目代码1)项目结构说明:ai-meeting/├── app/│   ├── core/                    # 核心基础设施│   │   ├── config.py            # Pydantic Settings 配置管理│   │   ├── database.py          # 异步数据库引擎 + 会话工厂│   │   ├── exceptions.py        # 统一异常处理器│   │   └── logging.py           # 日志配置│   ├── models/                  # SQLAlchemy ORM 模型│   │   ├── user.py              # 用户模型│   │   ├── meeting.py           # 会议模型│   │   ├── task.py              # 任务模型│   │   └── risk_alert.py        # 风险预警模型│   ├── schemas/                 # Pydantic 请求/响应 Schema│   ├── api/                     # FastAPI 路由│   │   ├── auth.py              # 认证 + 用户管理 API│   │   ├── meetings.py          # 会议 CRUD + 搜索 + 导出│   │   ├── tasks.py             # 任务列表 + 更新 + 排序│   │   └── skill.py             # 风险检测 API│   ├── services/                # 业务逻辑层│   │   ├── auth_service.py      # 注册/登录/JWT/密码哈希│   │   ├── meeting_service.py   # 会议业务逻辑│   │   ├── task_service.py      # 任务业务逻辑│   │   └── maas_service.py      # MaaS API + 本地摘要引擎│   └── main.py                  # FastAPI 应用入口├── frontend/│   ├── package.json             # 前端依赖│   ├── vite.config.js           # Vite 配置(API 代理)│   └── src/│       ├── main.js              # 入口(ElementPlus 中文 locale)│       ├── App.vue              # 布局(侧边栏 + 路由 + 登录状态)│       └── components/          # 12 个功能组件├── .env                         # 环境变量├── requirements.txt             # Python 依赖└── init_db.py                   # 数据库初始化脚本 2)下载源码         通过git下载源码到本地(含demo演示),代码仓地址:ai-meeting - AtomGitgit clone https://gitcode.com/ gcw_Xpooy7x3/ai-meeting.gitcd ai-meeting 3)关键代码讲解   3.1 配置管理——从 .env 加载 MaaS API Key        使用 Pydantic Settings 从 .env 文件加载配置,extra: "ignore" 允许旧变量不报错,@lru_cache 实现全局单例:from pydantic_settings import BaseSettingsfrom functools import lru_cacheclass AppSettings(BaseSettings):    DATABASE_URL: str = "sqlite+aiosqlite:///./ai_meeting.db"    REDIS_URL: str = "redis://localhost:6379/0"    MAAS_API_KEY: str = ""    MAAS_API_URL: str = "https://api.modelarts-maas.com/v2/chat/completions"    MAAS_MODEL: str = "deepseek-v4-flash"    APP_NAME: str = "会议智脑"    DEBUG: bool = False    JWT_SECRET: str = "change-me-in-production"    JWT_ALGORITHM: str = "HS256"    JWT_EXPIRE_MINUTES: int = 1440    model_config = {        "env_file": ".env",        "env_file_encoding": "utf-8",        "extra": "ignore",    }@lru_cache()def get_settings() -> AppSettings:    return AppSettings()         在项目根目录创建 .env 文件,将 MaaS 的 API Key、API 地址和模型名称填入:DATABASE_URL=sqlite+aiosqlite:///./ai_meeting.dbREDIS_URL=redis://localhost:6379/0MAAS_API_KEY=<你的华为云MaaS API Key>MAAS_API_URL=https://api.modelarts-maas.com/v2/chat/completionsMAAS_MODEL=deepseek-v4-flashAPP_NAME=会议智脑DEBUG=trueJWT_SECRET=meeting-brain-jwt-secret-2026   3.2 核心逻辑——调用华为云 MaaS 大模型生成摘要      这是本案例的核心代码。process_meeting 函数实现多级降级策略:优先调用 MaaS API,失败时降级到本地规则引擎。同时支持 Redis 缓存(可选,连接失败自动跳过)。         System Prompt 设计——明确指定英文字段名和 JSON 输出格式,避免模型返回中文键名:SYSTEM_PROMPT = """你是一个严谨的会议纪要专家。请处理输入的会议记录并输出JSON。规则:- summary:不超过150字,仅包含最终结论,不重复会议过程- key_decisions:只提取有明确结论或投票通过的事项,最多5条- tasks:仅当原文明确提及"某人负责某事"或"需要在某时间前完成"时才提取,严禁臆造- 日期格式统一为 YYYY-MM-DD,如果原文没有年份则默认为当前年份- 如果原文信息不足,对应字段返回空列表或空字符串,不要编造输出必须是合法JSON,严格使用以下英文字段名(禁止使用中文字段名):{  "summary": "一句话摘要",  "key_decisions": ["决策1", "决策2"],  "tasks": [    {"description": "任务描述", "assignee": "责任人", "deadline": "YYYY-MM-DD", "priority": "high/mid/low"}  ]}"""         MaaS API 调用——使用 httpx.AsyncClient 异步调用,指数退避重试(最多3次,仅对超时/连接错误重试),超时时间90秒:async def _call_maas_api(record_text: str) -> dict:    settings = get_settings()    headers = {        "Authorization": f"Bearer {settings.MAAS_API_KEY}",        "Content-Type": "application/json",    }    body = _build_request_body(record_text)    for attempt in range(1, MAX_RETRIES + 1):        try:            async with httpx.AsyncClient(timeout=90) as client:                resp = await client.post(settings.MAAS_API_URL, headers=headers, json=body)            if resp.status_code != 200:                raise AppException(502, f"MaaS 接口返回错误码: {resp.status_code}")            content = resp.json()["choices"][0]["message"]["content"]            start, end = content.find("{"), content.rfind("}") + 1            parsed = json.loads(content[start:end])            # 兼容中文键名            if "摘要" in parsed and "summary" not in parsed:                parsed["summary"] = parsed.pop("摘要")            if "关键决策" in parsed and "key_decisions" not in parsed:                parsed["key_decisions"] = parsed.pop("关键决策")            if "任务清单" in parsed and "tasks" not in parsed:                parsed["tasks"] = parsed.pop("任务清单")            raw_tasks = parsed.get("tasks") or parsed.get("task_list") or parsed.get("action_items") or []            normalized_tasks = []            for t in raw_tasks:                if isinstance(t, dict):                    nt = {                        "description": t.get("description") or t.get("task") or t.get("任务") or "",                        "assignee": t.get("assignee") or t.get("person") or t.get("负责人") or "",                        "deadline": t.get("deadline") or t.get("due_date") or t.get("截止日期") or "",                        "priority": t.get("priority") or "mid",                    }                    normalized_tasks.append(nt)                elif isinstance(t, str):                    m = re.match(r"^([\u4e00-\u9fa5]{2,4})[::]\s*(.+)$", t)                    if m:                        assignee, desc = m.group(1), m.group(2)                        normalized_tasks.append({"description": desc, "assignee": assignee, "deadline": "", "priority": "mid"})            parsed["tasks"] = normalized_tasks            return parsed        except (httpx.TimeoutException, httpx.ConnectError):            wait = 2 ** attempt            await asyncio.sleep(wait)    raise AppException(502, "MaaS 调用失败")         多级降级与缓存——完整的 process_meeting 流程:async def process_meeting(record_text: str) -> dict:    if not record_text or not record_text.strip():        return {"summary": "", "key_decisions": [], "tasks": []}    settings = get_settings()    if not settings.MAAS_API_KEY:        return _local_summarize(record_text)    redis_client = await _get_redis()    try:        if redis_client:            cached = await redis_client.get(_cache_key(record_text))            if cached:                return json.loads(cached)        try:            result = await _call_maas_api(record_text)        except Exception:            result = _fallback_result(record_text)        if redis_client:            await redis_client.set(_cache_key(record_text), json.dumps(result, ensure_ascii=False), ex=7*24*3600)        return result    finally:        if redis_client:            await redis_client.close()3.3 会议上传与 AI 处理联动   会议上传 API 在创建记录后,自动调用 process_meeting 进行 AI 处理,将生成的摘要、决策写入 Meeting 记录,并将提取的任务批量创建为 Task 记录:class MeetingService:    def __init__(self, db: AsyncSession):        self.db = db    async def upload_meeting(self, title, record_text, tags=None):        meeting = Meeting(title=title, record_text=record_text, status=MeetingStatus.pending, tags=tags)        self.db.add(meeting)        await self.db.flush()        if record_text and record_text.strip():            await self._process_meeting_content(meeting)        return meeting.id    async def _process_meeting_content(self, meeting):        try:            result = await process_meeting(meeting.record_text)            meeting.summary = result.get("summary", "")            meeting.key_decisions = result.get("key_decisions", [])            meeting.status = MeetingStatus.processed            for task_data in result.get("tasks", []):                task = Task(                    meeting_id=meeting.id,                    description=task_data.get("description", ""),                    assignee=task_data.get("assignee", ""),                    deadline=self._parse_date(task_data.get("deadline")),                    priority=self._parse_priority(task_data.get("priority")),                    status=TaskStatus.todo,                )                self.db.add(task)            await self.db.flush()        except Exception as exc:            logger.error(f"会议处理失败,保持pending状态: {exc}")3.4 数据库会话管理——SQLite 异步适配   SQLite 适配关键点:WAL 模式支持并发读、外键约束、不使用连接池。get_db() 通过 yield 实现请求级会话,自动 commit/rollback:from sqlalchemy.ext.asyncio import create_async_engine, async_sessionmaker, AsyncSessionfrom sqlalchemy import eventsettings = get_settings()_is_sqlite = settings.DATABASE_URL.startswith("sqlite")engine = create_async_engine(settings.DATABASE_URL, echo=settings.DEBUG)if _is_sqlite:    @event.listens_for(engine.sync_engine, "connect")    def _set_sqlite_pragma(dbapi_conn, connection_record):        cursor = dbapi_conn.cursor()        cursor.execute("PRAGMA journal_mode=WAL")        cursor.execute("PRAGMA foreign_keys=ON")        cursor.close()AsyncSessionLocal = async_sessionmaker(bind=engine, class_=AsyncSession, expire_on_commit=False)async def get_db() -> AsyncSession:    async with AsyncSessionLocal() as session:        try:            yield session            await session.commit()        except Exception:            await session.rollback()            raise3.5 前端 Vite 代理配置   开发环境将 /api 请求代理到后端 8000 端口:import { defineConfig } from 'vite'import vue from '@vitejs/plugin-vue'export default defineConfig({  plugins: [vue()],  server: {    proxy: {      '/api': { target: 'http://localhost:8000', changeOrigin: true },      '/health': { target: 'http://localhost:8000', changeOrigin: true },    },  },})4)运行调试   步骤1:安装后端依赖pip install -r requirements.txt   步骤2:安装前端依赖cd frontendnpm installcd ..   步骤3:初始化数据库python init_db.py   执行成功后输出:数据库表创建完成示例数据初始化完成!2个用户 + 3个会议 + 10项任务  管理员: admin / admin123  普通用户: demo / demo123     步骤4:启动后端服务uvicorn app.main:app --reload --port 8000   启动后访问 http://localhost:8000/docs 可查看自动生成的 OpenAPI 交互式文档:     步骤5:启动前端开发服务器cd frontendnpm run dev   启动后访问 http://localhost:5173,进入登录页面:     步骤6:登录并体验完整功能   使用 admin / admin123 登录,进入数据总览页面:     点击左侧菜单"上传会议",粘贴会议记录文本,点击"提交会议记录":     上传成功后点击"查看详情",查看 AI 自动生成的摘要、关键决策和任务清单:     切换到"任务看板"页面,拖拽卡片切换任务状态:     切换到"任务甘特图"页面,查看任务时间线:     切换到"风险检测"页面,点击"立即检测":  4 、释放资源本案例使用本地 SQLite 数据库和可选 Redis,不涉及华为云付费资源的持续占用。如需释放:• 删除本地 ai_meeting.db 文件即可清除所有数据• 如使用了华为云 MaaS Tokens 代金券,代金券到期后自动失效,无需手动释放5 、扩展资料说明• 想了解更多关于华为云 MaaS 大模型服务的可以访问:https://support.huaweicloud.com/productdesc-maas/maas_01_0001.html• 想了解更多关于 FastAPI 框架的可以访问:https://fastapi.tiangolo.com/• 想了解更多关于 Vue 3 组合式 API 的可以访问:https://cn.vuejs.org/guide/introduction.html• 想了解更多关于 Element Plus 组件库的可以访问:https://element-plus.org/zh-CN/ 
  • [高校训练营] 基于华为云码道与 ModelArts MaaS 的原创智能论文阅读学习助手PaperLens
    基于华为云码道与 ModelArts MaaS 的原创智能论文阅读学习助手PaperLens案例类型:AI 应用开发 / 智能阅读 / 开发者工具实践适用对象:高校学生、科研入门者、需要精读英文论文的个人用户在线体验:http://101.245.81.114代码仓库:falconousZhang/PaperLens_final参考体例:华为云开发者空间实战案例1. 案例介绍1.1 项目背景在阅读英文科研论文时,初学者经常遇到以下问题:PDF 排版复杂,正文、公式、图表与双栏文本之间缺乏清晰的阅读引导;论文中包含大量专业术语和长句,逐句翻译耗时,简单机翻又难以解释原理;阅读过程中产生的高亮、笔记和问题分散在不同工具中,难以形成连续的学习记录;通用大模型不了解当前论文上下文,容易给出脱离原文、缺少依据的回答;传统审稿工具更偏向评价论文质量,并不完全适合个人“读懂论文、掌握方法”的目标。PaperLens 因此被设计为一款 AI 驱动的个人论文阅读学习助手。系统以原始 PDF 为阅读主体,在不破坏论文版式的前提下,将总结、翻译、选中文字解释、论文问答、高亮、笔记、批判性阅读和学习报告导出整合到同一个工作台中。1.2 建设目标项目的核心目标不是替代用户阅读,而是降低进入论文内容的门槛,并让 AI 的每一次回答都尽量与论文原文建立联系。具体目标包括:保留原始 PDF 排版,提供逐页阅读体验;支持页面总结、全文翻译和选中文字解释;建立论文级多轮问答,让模型结合全文和历史对话回答;支持原文高亮与笔记,并按论文、页码进行管理;提供用户注册登录、数据隔离和管理员治理能力;将学习解释、笔记、批判性阅读等内容汇总导出为 Markdown、PDF 或 DOCX;使用低成本华为云资源完成可访问、可演示的部署。1.3 案例成果PaperLens 已形成从论文上传到学习资料沉淀的完整闭环:注册/登录 ↓ 上传 PDF → 文本与版式解析 → 进入逐页阅读工作台 ↓ ↓ 论文库管理 总结 / 翻译 / 选中文字解释 ↓ ↓ 阅读进度 多轮论文问答 ↓ ↓ 高亮与笔记 ← 原文定位与交互 → 批判性阅读 └───────────────┬───────────────┘ ↓ 学习报告导出图 1 PaperLens 论文库:集中展示论文解析状态、阅读进度、高亮与笔记数量,并支持继续阅读和论文管理。项目已部署在华为云 ECS,使用华为云 ModelArts Studio(MaaS)提供真实大模型推理能力,并通过 Docker Compose 运行前端、后端和 PostgreSQL。2. 整体解决方案2.1 方案概述PaperLens 采用前后端分离架构。浏览器负责 PDF 页面展示、文本选择和学习交互;后端负责用户权限、论文解析、任务状态、模型调用、数据持久化和报告生成。大模型能力通过统一的 LLMClient 抽象接入,当前实际部署使用华为云 ModelArts Studio(MaaS)的对话模型服务。系统遵循三个设计原则:原文优先:左侧始终展示原始 PDF 页面,AI 结果作为辅助信息显示在右侧;来源可追溯:解析时记录页码、字符区间和文本块位置,学习内容可以重新定位到原文;任务可恢复:耗时操作以任务状态保存,页面刷新后可以恢复轮询,不依赖一次 HTTP 连接持续到模型返回。2.2 技术选型层次技术或服务作用前端Vue 3、TypeScript、Vite、Pinia、Vue Router、Axios阅读工作台、状态管理、路由保护和 API 调用后端Python、FastAPI、Pydantic、SQLAlchemyREST API、业务服务、参数校验和数据访问数据库PostgreSQL 16、Alembic用户、论文、页面、问答、解释、笔记、任务和审计数据PDF 处理PyMuPDF、pdfplumber页面渲染、正文提取、文本块定位和表格识别大模型华为云 ModelArts Studio(MaaS)、GLM-5.2总结、翻译、选中文字解释、论文问答和批判性阅读报告ReportLab、python-docxMarkdown、PDF、DOCX 学习报告生成部署华为云 ECS、VPC、安全组、弹性公网 IP、Docker Compose、Nginx单机容器化部署与公网访问研发辅助华为云码道(CodeArts)代码智能体需求理解、跨文件编码、测试设计、问题定位和部署调试2.3 开发环境与云资源准备本案例将“开发工具”和“运行资源”明确分开。码道、Rules 与 Skills 只在研发阶段使用,不会随应用一起部署;真正运行 PaperLens 时只需要前端、后端、数据库、文件卷和 MaaS 服务。类别本案例配置说明本地开发Windows、Git、Docker Desktop、Node.js、Python编码、容器联调和定向验收智能研发华为云码道(CodeArts)代码智能体、项目级 Rules、开发 Skills需求设计、编码、测试资产与问题定位大模型服务ModelArts Studio(MaaS)兼容对话接口由统一 LLMClient 调用,密钥仅通过环境变量注入云服务器华为云 ECS,Ubuntu 22.04,2 vCPU、4 GiB、40 GiB小规模实习项目的单机部署网络VPC、子网、安全组、弹性公网 IP,5 Mbit/s公网只开放 Web 入口和受限 SSH容器运行Docker Engine、Docker Compose运行 Nginx、FastAPI 和 PostgreSQL为控制成本,当前实际部署没有单独购买 RDS、OBS、ELB 或 Kubernetes。数据库与文件使用 ECS 上的 Docker 持久卷;项目保留向 RDS 和 OBS 演进的接口与部署资料,但案例不会把“已经设计”描述成“已经购买并运行”。3. 系统架构设计3.1 逻辑架构3.2 分层设计表现层前端采用 Vue 3 + TypeScript。核心页面包括登录注册、论文库、上传页面、论文阅读工作台、批判性阅读结果、报告导出和管理员控制台。论文阅读工作台采用左右分栏布局:左侧按页显示原始 PDF 图像,并叠加可选择的透明文本层;右侧在“学习解释、论文问答、学习记录”之间切换;用户选择原文后,可以直接创建黄色高亮、绿色笔记或发起通俗解释;点击历史解释时,系统自动跳转到对应页并高亮来源文本。接口层FastAPI 对外提供统一的 /api/v1 接口,按领域拆分为认证、论文、任务、学习解释、问答、论文库、学习记录、导出和管理员接口。Pydantic 负责输入输出边界,统一异常处理避免将数据库语句、文件路径或上游响应泄露给前端。业务层业务逻辑集中在 Service 层:pdf_parser:正文、章节、文本块、表格和 Evidence 解析;learning_service:页面总结、翻译与选中文字解释;qa_service、qa_retriever:论文级多轮问答和证据检索;highlight_service、note_service:高亮、笔记与原文锚点;review_service:批判性阅读;export_service、report_converter:学习报告组织与格式转换;admin_service:用户治理、内容元数据查询和审计。数据层PostgreSQL 保存结构化业务数据,Docker Volume 保存 PDF、页面图像和导出报告。数据库迁移由 Alembic 管理,容器启动时先执行迁移,再启动后端服务。3.3 核心数据流论文上传与解析用户上传 PDF,后端校验扩展名、文件头、大小和文件哈希;文件写入受控存储目录,创建论文记录和解析任务;PyMuPDF 提取页面正文、页面尺寸和文本块坐标;pdfplumber 尝试提取表格,表格失败不影响正文解析;系统生成页面、章节、文本分块和 Evidence 数据;论文状态更新为 PARSED,前端进入阅读工作台。学习解释用户选择总结、翻译,或在 PDF 文本层中选择一段原文;后端根据页码、字符区间和论文归属校验来源;系统构造带有明确边界的 Prompt,并调用 MaaS;模型输出经过结构校验和清洗后持久化;前端轮询任务状态,并将结果与对应页和选区关联。论文问答首次提问时,后端读取论文全文,在长度预算内构造论文上下文;后续提问同时附加最近的历史问答。检索模块优先识别问题中的页码、表号、图号等显式引用,再结合文本相关性选择候选证据。问答记录保存在会话中,用户可以切换、滚动查看或删除历史会话。3.4 华为云部署架构本案例定位为小规模实习项目,因此优先选择低成本、易维护的单机方案,而不是引入复杂的微服务集群。部署中只将 Nginx 的 80 端口发布到公网,后端 8000 和数据库 5432 仅在 Docker 私有网络中访问。数据库和文件目录使用持久卷,容器设置健康检查与 restart: unless-stopped。当前演示环境使用 HTTP;正式生产环境应增加域名、HTTPS 证书并启用 Secure Cookie。3.5 工程目录设计项目采用按前端、后端、部署和设计资料分区的单仓库结构。核心目录如下:PaperLens/ ├── backend/ │ ├── paperlens/ │ │ ├── api/ # FastAPI 路由与认证边界 │ │ ├── core/ # 配置、安全、错误和可观测性 │ │ ├── models/ # SQLAlchemy 业务模型 │ │ ├── schemas/ # Pydantic 请求与响应契约 │ │ └── services/ # 解析、解释、问答、记录和导出服务 │ ├── alembic/ # 数据库迁移链 │ └── tests/ # 后端测试资产 ├── frontend/ │ ├── src/api/ # API 客户端 │ ├── src/components/ # 阅读工作台组件 │ ├── src/stores/ # Pinia 状态 │ └── src/views/ # 登录、论文库、阅读、管理等页面 ├── deploy/huawei/ # 单 ECS 与生产化部署配置 ├── ProjectDocs/ # 需求、架构、页面、测试和 SDD 设计资料 ├── docker-compose.yml # 本地开发编排 └── README.md这种结构使码道能够先从设计资料理解约束,再定位到对应领域的路由、Schema、Service、模型和前端页面,减少把业务逻辑堆进单个文件的情况。3.6 核心数据模型PaperLens 的数据模型围绕“用户—论文—页面内容—学习行为”展开:数据域核心实体设计要点认证users、auth_sessions、password_reset_tokens角色、状态、刷新令牌轮换和密码重置论文papers、paper_pages、paper_sections、paper_chunks论文归属、解析状态、逐页正文和章节结构原文定位evidences、paper_tables页码、引用文本、字符区间、边界框和表格结构学习解释learning_explanations、learning_citations模式、范围、任务状态、来源引用和失败恢复论文问答paper_qa_conversations、paper_qa_turns、paper_qa_citations多轮顺序、幂等请求、上下文哈希和证据绑定学习记录paper_library_entries、paper_highlights、paper_notes阅读进度、黄色高亮、绿色笔记和原文锚点扩展分析analysis_tasks、review_results、metric_records、experiment_results批判性阅读、指标与实验理解导出与治理export_reports、admin_audit_logs报告状态、文件信息和管理员不可变审计任务型实体统一使用 PENDING → RUNNING → SUCCEEDED/FAILED 状态机。模型调用前结束数据库事务,模型返回后再用新事务写入结果,避免在外部网络等待期间长期持有连接或行锁。4. 使用华为云码道(CodeArts)代码智能体辅助开发与调试4.1 使用方式PaperLens 的功能跨度较大,涉及前端交互、后端 API、数据库迁移、PDF 处理、大模型调用和云端部署。项目使用华为云码道(CodeArts)代码智能体辅助理解代码库、拆解需求、生成跨文件代码、补充测试以及定位运行故障。项目没有采用“一次性生成整个系统”的方式,而是将开发过程拆成可验证的小阶段:明确用户目标 ↓ 形成单轮任务提示词和边界 ↓ 码道理解代码库并完成跨文件实现 ↓ 集中进行定向测试、构建或实际操作验收 ↓ 根据日志和页面现象定位问题 ↓ 码道完成同轮修正 ↓ 进入下一功能阶段4.2 Rules 与 Skills 工程化约束为了让智能体在长期迭代中保持一致,项目为码道配置了项目级规则和技能工作流,主要覆盖:需求细化与架构设计;页面原型和交互约束;前后端测试设计;功能详细设计与任务拆解;Sprint 进度管理;Bug 修复记录。每次给码道的任务都会说明目标、允许修改的范围、禁止事项、接口契约、数据一致性要求和验收方式。相比只描述“实现某功能”,这种结构化提示词能够降低跨文件修改遗漏、重复造轮子和无关重构的概率。4.3 提示词管理与迭代方法PaperLens 没有把码道提示词当作一次性聊天内容,而是为每个开发阶段保留任务编号、目标、约束、验收标准和后续状态。项目共形成 P1~P8.4 的 32 轮阶段提示词归档,使需求变化、实现边界和技术决策能够回溯。一条可执行的码道提示词通常包含以下结构:# 码道下一阶段提示词:<阶段编号与名称> ## 任务目标 - 本轮只解决什么问题 - 完成后用户能获得什么能力 - 与既有功能的关系 ## 开始前边界与真实基线 - 必读的设计文档和真实代码 - 当前迁移、接口、容器和功能状态 - 必须保护的用户数据与现有修改 - 禁止读取的密钥、令牌和环境信息 ## 设计与实现要求 - 数据模型、状态机和迁移规则 - API 请求/响应与错误语义 - Service、前端交互和安全边界 - 并发、幂等、事务和失败恢复 ## 测试资产与验收 - 只编写少量关键测试资产 - 码道不运行测试、构建、迁移或 Docker 命令 - 集中验收阶段执行定向测试、关键烟测和前端构建 ## 完成定义 - 允许修改的文件 - 必须同步的设计与 Sprint 文档 - 实际完成项、未完成项和风险必须如实报告提示词也随项目实践逐步演进:早期更强调从零搭建和运行验证;中期增加数据模型、API 契约、并发和安全约束;后期为了提高效率,码道只负责编写或更新少量测试资产,不在实现轮次运行耗时测试,测试执行统一放到集中验收阶段。4.4 代表性码道提示词节选以下内容选自项目实际提示词归档。为适合作为案例展示,省略了较长的文件清单、历史统计值和重复性约束,但保留了当轮的目标、关键边界与完成定义。提示词一:建立可运行工程骨架使用场景:项目初期先统一技术选型和数据契约,避免前后端、数据库和设计文档各自演进。你现在负责继续开发 D:\shixi\PaperLens 项目。 本轮目标不是一次性完成整个系统,而是完成“规格修正 + 可运行工程骨架”, 为后续端到端 MVP 开发建立稳定基础。 一、必须采用的 MVP 决策 1. 前端使用 Vue 3 + TypeScript + Vite + Pinia + Vue Router。 2. 后端使用 FastAPI + SQLAlchemy + Alembic。 3. 本地和部署均使用 PostgreSQL,不使用 SQLite。 4. Evidence 必须记录 page_number、quoted_text、bbox、char_start、 char_end、section_id 和 chunk_id,保证前端后续能够定位原文。 5. 上传统一使用 multipart 流式上传,最大 50 MB。 6. 后台任务进度统一使用 HTTP 轮询,暂不引入 WebSocket。 7. MVP 只支持可提取文本的 PDF,OCR 放入后续版本。 8. LLM 必须通过统一 LLMClient 调用,默认提供 MockLLMClient。 二、本轮交付 - 创建 backend、frontend、docker-compose.yml、.env.example 和 README。 - 后端实现健康检查、配置、数据库连接、ORM、首个迁移和统一错误结构。 - 前端实现基础路由、Pinia、首页、健康检查及后端不可用提示。 - Compose 只包含 PostgreSQL、backend 和 frontend。 三、边界 - 不写入真实密钥,不初始化或提交 Git。 - 不引入 Celery、Redis、Nginx、FAISS 或真实云服务。 - 不生成大量空接口或只有 pass 的占位代码。 - 本轮到“工程骨架可以启动、模型和契约自洽”为止, 不继续实现 PDF 解析和真实 LLM 功能。落地结果:码道完成了 FastAPI、Vue、PostgreSQL 与 Docker Compose 的基础工程,并建立了后续一直沿用的 Evidence 定位字段和 LLMClient 抽象。提示词二:接入华为云 ModelArts MaaS使用场景:在 Mock 模型链路已经可用后,增加真实华为云模型适配器,同时保证本地开发不依赖云端密钥。# P3.3 华为云 MaaS 真实生成式模型适配器 ## 任务目标 在不改变现有审阅 API、数据库模型和前端的前提下, 把 LLMClient 从“只有 Mock 实现”扩展为可配置的 HuaweiMaaSLLMClient。 默认本地和测试仍使用 MockLLMClient。 ## 实现边界 1. 复用现有 httpx,不新增第三方模型 SDK、requests 或重试库。 2. 华为 MaaS 适配器使用标准 chat/completions 请求结构。 3. endpoint、model、API Key、连接超时和读取超时全部来自 Settings。 4. API Key 使用安全类型保存,不得出现在日志、异常、响应或 repr 中。 5. 不修改公开 API、ORM、Alembic、Docker 和前端。 6. 云接口测试必须使用 MockTransport,禁止真实联网和产生费用。 ## 响应与失败处理 - 校验 HTTP 状态、响应 JSON、choices、message 和 content。 - 兼容模型返回单个完整 Markdown JSON 围栏。 - 拒绝前后杂文、多对象、字段缺失和未知字段。 - 上游失败统一转换为安全业务错误,不把响应正文或密钥返回给客户端。 ## 完成定义 - Mock 与 Huawei MaaS 通过同一 LLMClient 工厂切换。 - 没有云端配置时项目仍可离线运行。 - 配置示例只使用占位符,不读取、打印或提交真实密钥。落地结果:真实模型与 Mock 模型共用同一业务接口,学习解释、问答和批判性阅读无需感知底层供应商;部署时只需通过环境变量选择 MaaS 适配器。提示词三:把产品主线校正为论文阅读学习使用场景:项目中期确认“帮助个人用户读懂论文”才是核心目标,因此需要在保留已有分析能力的同时重构主要交互。# P7.1 论文阅读学习工作台与证据化学习解释 ## 任务目标 把 PaperLens 的产品主线从“辅助审稿”校正为“帮助个人用户阅读论文并学习”。 在已完成的 PDF 解析、章节/页面、Evidence、认证隔离和 Huawei MaaS LLMClient 基础上,实现受保护的论文阅读工作台,以及针对当前页面或 选中文字的总结、翻译和通俗解释闭环。 已有结构化审阅、指标提取、实验分析和报告能力继续保留,分别作为 “批判性阅读”“实验理解”和“学习成果导出”的高级能力,不删除或重做。 ## 来源与安全边界 1. 客户端只提交 mode、scope 和页码/选区标识,不提交论文正文或 prompt。 2. 后端根据当前用户和 paper_id 重新读取来源,禁止跨用户、跨论文引用。 3. 论文标题和正文均视为不可信输入,并放在明确标签中;其中出现的 “忽略之前指令”等文字不得覆盖 system 指令。 4. SUMMARY 概括当前范围;TRANSLATE 忠实翻译并保留标题、段落和编号; 选中文字解释要说明概念、原理和例子。 5. 结果必须保存页码、来源哈希和任务状态,失败只记录安全公开文案。 ## 前端交互 - 阅读页采用左右分栏,左侧保留原始 PDF 版式并支持文本选择。 - 右侧显示学习解释历史;点击记录跳转到来源页。 - 选中文字解释与原文位置关联,不能把解释结果挤在 PDF 正文下方。 - 页面切换或组件卸载时停止旧轮询,避免旧结果覆盖新页面。落地结果:PaperLens 从“生成审阅结论”转向“原文阅读 + 页面解释 + 学习沉淀”,形成当前最具辨识度的双栏阅读工作台。提示词四:实现论文级多轮问答使用场景:解决“论文里明明存在,模型却因为只收到当前页片段而回答没有”的问题。# P7.2 当前论文多轮问答与证据化会话 ## 任务目标 实现只围绕当前用户、当前论文的多轮问答。用户可以新建会话、连续提问、 查看历史;有依据的回答绑定服务端选取的论文来源,证据不足时明确降级, 不能用模型常识伪装成论文结论。 ## 上下文构造 1. 以当前 question 为 query,仅在当前论文的 Evidence 中做确定性相关性排序。 2. 后续提问附加同会话最近的成功问答,超限时按完整轮次从最旧开始移除。 3. 候选 Evidence 按相关度、页码、创建时间和 ID 稳定排序,并限制 top_k。 4. 当前问题、历史回答和论文正文全部视为不可信内容,不能提升为 system role。 5. Embedding 与 LLM 调用期间不得持有数据库事务或行锁。 ## 幂等与结果契约 - 请求包含 client_request_id;重复请求返回原轮次,不重复调用模型。 - 同一会话只允许一个 PENDING/RUNNING 轮次。 - 成功回答保存 answer、grounded 和来源引用;证据不足时 grounded=false。 - 模型只返回一个严格 JSON 对象,拒绝额外解释、未知字段和跨论文引用。 ## 前端交互 - 右侧使用类似即时通信软件的消息时间线。 - 会话历史和消息区域可独立滚动,输入区固定在底部。 - 支持新建、切换和删除会话,轮询在终态立即停止。落地结果:系统形成论文级会话、轮次、上下文预算和幂等机制。真实论文验证中发现仅依赖少量 Evidence 会漏掉跨页图表后,后续迭代又将策略调整为“首次提问按预算提供全文基础上下文,后续附加历史,并优先识别页码、表号和图号”,体现了设计根据实际效果继续修正的过程。提示词五:准备华为云部署与安全收口使用场景:开发轮次结束后,为 ECS 部署、备份恢复和后续云资源演进准备可复用资产。# P8.4 华为云部署、备份恢复与综合安全验收 ## 任务目标 在既有论文阅读学习、登录注册、管理员、任务恢复和限流能力基础上, 补齐华为云部署配置、备份恢复说明和安全清单,使项目达到 “代码与部署资料完整,等待真实云环境验收”的状态。 ## 真实性要求 1. 不实际购买、创建、修改或删除华为云资源。 2. 不把“部署资产已完成”写成“真实云上已经部署”。 3. 示例只能使用占位符,禁止读取或写入 API Key、AK/SK、JWT Secret、 数据库密码、真实 IP、域名和证书私钥。 4. 码道只编写代码、少量测试资产、部署配置和文档, 不运行测试、构建、迁移、Docker、HTTP 或真实云服务命令。 ## 部署资产 - 提供 deploy/huawei 下的环境示例、Compose、Nginx、部署和回滚说明。 - 后端和数据库不直接暴露公网;只由 Nginx 代理同源 /api/。 - 容器使用非 root、只读文件系统、tmpfs、no-new-privileges、 healthcheck、资源上限和 restart policy。 - Secret 通过受限环境文件或 secret 文件注入,entrypoint 不打印内容。 - 给出 VPC、安全组、ECS、MaaS、健康检查和小额验证的人工配置顺序。 ## 完成定义 区分“代码与部署资产已实现”“离线验收尚未执行” 和“真实华为云资源尚未创建/验证”三种状态,不夸大完成度。落地结果:项目形成单 ECS 演示编排和面向生产化演进的配置资料;真实部署时又根据小规模需求选择 PostgreSQL 与文件卷同机运行,避免为了案例展示购买不必要资源。4.5 码道参与的主要开发阶段阶段码道辅助内容形成的结果工程骨架分析前后端技术栈,生成 FastAPI、Vue、PostgreSQL、Docker 基础结构可运行的前后端与数据库环境PDF 解析实现上传校验、页面解析、章节识别、文本块坐标和 Evidence 生成从 PDF 到可阅读、可定位数据的链路大模型接入抽象 LLMClient,实现 Mock 与 Huawei MaaS 适配器本地离线开发与云端真实模型可切换阅读工作台跨文件实现 PDF 页面、透明文本层、左右分栏和选区工具条保留原版式的交互式阅读体验学习解释设计总结、翻译、选中文字解释的 Prompt、状态机和历史记录面向学习场景的 AI 辅助阅读能力论文问答设计会话、轮次、全文上下文、历史预算和检索策略支持论文内连续提问用户与管理实现 JWT、刷新令牌、用户隔离、管理员角色和审计完整登录注册与管理闭环报告导出组织解释、高亮、笔记和批判性阅读内容Markdown、PDF、DOCX 学习报告云端部署分析 Docker、Nginx、卷权限和 MaaS 日志在小规格华为云 ECS 上稳定运行4.6 码道辅助调试实例实例一:测试数据误写开发库早期测试虽然创建了测试数据库,但应用在模块导入时已经初始化了指向开发库的数据库连接,导致部分测试仍可能写入开发库。码道根据数据库记录变化和初始化顺序分析问题,协助调整为延迟配置数据库 Engine,并增加测试库名称守卫、迁移失败即终止和测试残留检查。解决后,测试环境明确使用 paperlens_test,避免自动化测试污染真实论文数据。实例二:真实 MaaS 输出格式不稳定Mock 模型始终返回标准 JSON,但真实模型可能返回 Markdown 代码围栏、额外解释或字段缺失。码道协助增加严格的响应解析、围栏兼容、字段校验和安全失败状态;学习解释还使用独立的较长读取超时,避免长页翻译被普通问答的超时配置提前终止。实例三:Docker 容器在 ECS 上反复重启部署时 Nginx 采用只读文件系统,但默认尝试在 /var/cache/nginx 创建临时目录,导致容器因权限不足反复重启。码道根据容器日志定位到临时目录问题,将相关目录调整到 /tmp,并通过受限 tmpfs 提供可写空间。后端文件卷也曾因宿主卷所有权不匹配导致上传失败,随后增加一次性的 storage-init 服务,在后端启动前修正目录所有者和权限。实例四:公网 HTTP 下论文问答误报网络失败浏览器在普通 HTTP 环境下不能保证提供 crypto.randomUUID()。前端在创建会话后生成幂等请求 ID 时抛出本地异常,因此服务器只看到会话被创建和删除,没有收到真正的问题请求。码道根据前后端访问日志定位到请求链中断位置,增加基于 getRandomValues 的 UUID v4 回退逻辑,并区分本地运行异常和真实网络异常。这些问题说明,代码智能体的价值不仅是生成代码,还包括结合代码库、日志、运行环境和数据状态完成工程化定位。5. 功能解决方案设计5.1 原版式 PDF 阅读系统不将 PDF 正文简单转换成连续纯文本,而是为每一页生成页面图像,同时输出带坐标的文本层。页面图像保证视觉排版与原论文一致,透明文本层负责文字选择、字符偏移计算和高亮交互。这种设计兼顾了两个目标:用户看到的是原论文版式、图片、公式和表格;系统仍能知道用户选中了哪段文字,并把操作绑定到页码和字符区间。图 2 论文阅读工作台:左侧按页保留原始 PDF 版式,右侧统一承载学习解释、论文问答和学习记录。5.2 页面级学习解释“总结”和“翻译”按页生成并保留历史:总结要求覆盖当前页的各级标题;如果一个段落延续到下一页,可读取有限的下一页上下文补全含义;翻译要求保留标题层级和正文段落,不将公式、编号和专有名词随意改写;选中文字解释只处理用户选择的原文,重点说明概念、原理和例子。所有解释按页排序。点击历史记录可跳转到来源页;选中文字解释打开时,对应原文保持蓝色高亮。图 3 页面完整翻译:在保留标题、作者信息和正文层次的基础上,对当前页内容进行中文翻译。图 4 选中文字解释:左侧原文保持蓝色定位高亮,右侧从概念、原理和示例角度给出通俗说明。5.3 论文级多轮问答论文问答采用类似即时通信软件的对话界面。系统保存完整会话历史,输入区固定在底部,消息区域可独立滚动。为了减少“论文里明明有,模型却回答没有”的情况,后端不只发送当前页摘要,而是在首次提问时组装论文全文上下文;后续轮次再附加历史问答,并对超长内容执行可预测的长度预算。对页码、图号、表号等问题,检索器给予显式引用更高优先级。图 5 论文级多轮问答:用户可以围绕指定页码、表格或方法连续追问,系统保留会话历史并结合论文内容回答。5.4 高亮和笔记用户可以直接在 PDF 上选择文字:高亮以黄色保存;笔记以绿色标记,并保存笔记正文;选中文字解释使用蓝色定位;学习记录只展示当前页的高亮和笔记。记录同时保存原文、页码、字符起止位置和来源哈希。当论文内容或解析结果发生变化时,系统可以识别来源不一致,避免错误定位。图 6 高亮与笔记:黄色标记用于原文高亮,绿色标记关联学习笔记,右侧仅展示当前页的学习记录。5.5 用户、权限与管理员系统系统支持注册、登录、刷新令牌、退出、修改密码、忘记密码和个人资料。密码使用 Argon2 哈希;访问令牌采用 JWT,刷新令牌使用 HttpOnly Cookie,并具有轮换和重放检测机制。所有论文、解释、问答和学习记录均按 user_id 隔离。管理员可以查看系统概况、管理用户状态和角色、只读查看跨用户内容元数据,关键操作写入不可变审计记录。5.6 学习报告导出报告不再限定为“审阅报告”。即使论文没有执行批判性阅读,只要存在学习解释、高亮或笔记,也可以生成学习报告。报告按页组织内容,并可选择是否加入批判性阅读、指标或实验信息,最终导出为 Markdown、PDF 或 DOCX。图 7 学习报告导出:支持 PDF、DOCX 和 Markdown,固定汇总学习解释、高亮摘录和学习笔记,并可按需加入扩展分析。6. 核心技术难点与解决思路6.1 PDF 视觉版式与文本交互难以兼得难点:直接展示 PDF 可以保留版式,但难以稳定获取选中文字的字符位置;只展示解析文本又会破坏双栏、图表和公式布局。解决思路:采用“页面图像 + SVG 透明文本层 + 解析文本索引”的三层结构。图像负责视觉,文本层负责浏览器选择,后端标准化文本负责字符区间与学习记录。6.2 解析结果存在不确定性难点:不同 PDF 的字体、编码、文本顺序和表格结构差异很大,单个表格解析异常可能导致整个事务失败。解决思路:对正文、章节、表格和 Evidence 分阶段处理;表格写入使用嵌套事务或降级策略,使局部失败不影响论文正文;对扫描版 PDF 明确返回不支持 OCR,而不是生成不可用结果。6.3 大模型回答必须与论文上下文绑定难点:如果只传当前页或少量 Evidence,模型可能无法理解跨页图表;如果直接无限制传全文,又会超过上下文或增加费用。解决思路:采用“全文基础上下文 + 当前页优先 + 显式页码/图表引用检索 + 历史轮次预算”的组合策略。系统保存上下文哈希和请求幂等键,避免同一问题被重复提交。6.4 模型输出和网络调用不稳定难点:真实模型可能返回围栏文本、非标准字段或较长推理内容;长页翻译比普通问答耗时更长。解决思路:统一 LLMClient 接口,设置连接与读取超时边界;不同任务可以覆盖单次读取超时;模型结果经过严格 Pydantic 校验,失败时写入安全的任务状态,不将上游响应和密钥返回给用户。6.5 异步任务与页面状态一致性难点:解析、解释、问答和导出都不是瞬时操作。快速切换论文或页面时,旧请求可能晚于新请求返回并覆盖界面。解决思路:后端采用持久化任务状态和原子认领,前端采用受控轮询、代次标识和组件卸载清理。刷新页面后重新查询活动任务,终态立即停止轮询。6.6 小规格 ECS 上的资源与可靠性难点:2 vCPU、4 GiB 内存同时运行镜像构建、数据库、后端和前端时容易出现内存压力;公网拉取 Docker Hub 镜像也可能超时。解决思路:配置交换分区和容器资源上限;使用多阶段构建缩小运行镜像;通过华为云 SWR 镜像加速拉取基础镜像;只运行单后端实例和小连接池,避免为实习项目引入 Redis、Celery、Kubernetes 等额外组件。7. 安全与可靠性设计真实 API Key、数据库密码和 JWT Secret 通过环境文件注入,不进入代码仓库;上传文件校验后缀、PDF magic、大小和存储路径,防止路径穿越;数据查询统一校验资源所有者,管理员接口使用独立权限保护;日志只记录请求 ID、阶段和安全错误分类,不记录论文全文、令牌或 MaaS 响应正文;后端与数据库不直接暴露公网端口;容器启用 no-new-privileges,前端使用只读文件系统;提供 live/ready 健康检查、启动恢复和容器自动重启;自动化测试使用独立测试数据库,并在测试前后检查数据残留。8. 项目实施过程8.1 分阶段建设项目采用逐阶段增量开发,每一阶段都对应独立提示词、设计更新和可验收结果。阶段主要任务阶段出口P1FastAPI、Vue、PostgreSQL、Docker 工程骨架首页与健康检查可运行,迁移链建立P2PDF 上传、解析、章节、页面、文本块、表格和 Evidence论文可从文件转换为结构化、可定位内容P3MockLLM、Embedding、Huawei MaaS、结构化结果前端真实模型与离线模型可以切换P4指标抽取、实验数据统计和模型运行配置模型理解与确定性计算分离P5实验文件导入、校验、比较和可视化论文实验结果可结构化分析P6Markdown、PDF、DOCX 报告分析结果可以形成文件交付P7阅读工作台、学习解释、多轮问答、高亮和笔记产品主线转为个人论文阅读学习P8登录注册、管理员、审计、恢复、限流、部署与安全形成完整用户系统并具备云端运行条件其中 P7 是产品方向最重要的一次调整。项目没有删除已经实现的审阅、指标和实验功能,而是把它们移动为“批判性阅读”和“实验理解”等高级入口,主路径改为上传论文后直接进入逐页阅读工作台。8.2 设计文档与任务追踪码道在编码前先同步以下设计层:需求细化:确认用户目标、功能范围、非目标和冲突决策;架构设计:明确前后端边界、外部 MaaS、任务与存储关系;数据模型:定义实体、外键、状态机、索引和迁移安全;API 设计:固定请求字段、响应结构、权限和错误语义;页面设计:固定路由、页面状态和交互行为;测试设计:只保留正常路径、关键失败和必要恢复场景;SDD 与 Sprint:把需求映射到具体设计、文件和任务状态。这种做法解决了长周期智能体开发中常见的“上一轮约束在下一轮丢失”问题。提示词不再重复粘贴整个项目,而是引用稳定设计资料,再补充本轮真实基线和差异要求。8.3 集中验收策略为了避免码道在每个实现轮次反复执行耗时的全量测试,项目后期采用“实现与验收分离”策略:码道负责更新必要测试资产,但提示词明确禁止运行测试、构建、迁移往返、Docker 重建和 HTTP 烟测;实现轮次完成后,先检查实际改动范围和接口契约;后端默认只运行受影响模块的定向测试;前端变更运行相关 Vitest 和一次生产构建;只保留一条关键业务烟测,例如“上传 PDF → 解析 → 进入阅读页”;认证、迁移链、共享基础设施或最终发布才执行更完整的回归。单个新功能通常只设计 1 个正常用例、1 个重要失败用例,以及在确有并发或恢复风险时增加 1 个对应场景。该策略更符合个人实习项目的成本与风险水平。8.4 华为云 ECS 部署过程部署采用单机 Compose,核心步骤如下:创建 VPC、子网、安全组、弹性公网 IP 和 Ubuntu 22.04 ECS;安全组开放 80,并将 22 端口来源限制为当前管理 IP;安装 Docker Engine 与 Compose,配置华为云 SWR 镜像加速;将代码发布包上传到 /opt/paperlens,检查校验和后解压;创建权限为 600 的部署环境文件,交互式写入数据库密码、JWT Secret 和 MaaS Key;使用 docker-compose.single.yml 构建并启动服务;检查容器状态、前端健康检查和后端 readiness;在浏览器完成注册、上传论文、学习解释和论文问答验证。示例命令中的配置均使用占位符,不包含真实凭据:cd /opt/paperlens chmod 600 deploy/huawei/.env.single docker compose \ --env-file deploy/huawei/.env.single \ -f deploy/huawei/docker-compose.single.yml \ up -d --build docker compose \ --env-file deploy/huawei/.env.single \ -f deploy/huawei/docker-compose.single.yml \ ps -a curl -fsS http://127.0.0.1/healthz curl -fsS http://127.0.0.1/api/v1/health/ready服务以 detached 模式运行,因此关闭本地 PowerShell 或 SSH 会话不会停止容器。ECS 重启后,Docker 服务与 Compose 的重启策略负责恢复应用。8.5 部署期问题闭环现象定位依据修正Docker Hub 拉取超时docker pull 访问官方 Registry 超时配置华为云 SWR 镜像加速并重启 DockerNginx 容器持续重启日志显示只读目录无法创建临时文件临时目录迁移到 /tmp,通过受限 tmpfs 提供写入PDF 上传失败后端日志显示持久卷目录权限不足启动前由一次性初始化服务修正卷所有权管理员升级 SQL 失败psql 变量替换与引号组合错误改用明确参数边界并先只读查询用户 ID论文问答前端报网络失败后端只有会话请求,没有问题请求为非安全 HTTP 环境增加 UUID v4 回退实现长页翻译偶发失败MaaS 请求耗时超过通用读取超时为学习解释配置独立、有限的读取超时部署验收以真实页面操作为准,不仅依赖容器显示 healthy。只有注册登录、论文上传解析、MaaS 学习解释、论文问答和管理员入口均完成小额验证,才认为案例具备可演示性。9. 应用效果与价值PaperLens 将“看 PDF、查术语、做笔记、问模型、整理报告”从多个割裂工具合并为一个连续流程。对个人学习场景而言,它带来的价值主要体现在:降低英文论文和专业概念的理解门槛;保持 AI 结果与当前论文、页码和原文选区的联系;让多轮问答、解释历史、高亮和笔记可以长期保存;通过华为云 MaaS 获得真实模型能力,同时保留 Mock 模型便于离线开发;通过码道代码智能体提升跨前后端开发和故障定位效率;使用单台小规格 ECS 即可完成课程设计、实习成果或个人演示部署。10. 局限与后续规划当前版本面向小规模个人使用,仍有以下边界:暂不支持扫描版论文 OCR;语义检索尚未使用持久化向量数据库;后台任务仍采用进程内执行器,不适合多实例横向扩展;单机 PostgreSQL 和本地文件卷需要定期备份;后续可根据实际用户量逐步引入 OBS、RDS、HTTPS、任务队列、pgvector 和多模态论文理解,但不在小规模案例阶段提前增加系统复杂度。11. 总结PaperLens 展示了如何将华为云码道(CodeArts)代码智能体、ModelArts Studio(MaaS)与常见 Web 技术结合,构建一套可实际部署的智能论文阅读学习应用。在研发侧,码道帮助项目完成需求拆解、跨文件编码、测试设计和部署故障定位;在运行侧,MaaS 提供总结、翻译、解释和问答能力;在基础设施侧,华为云 ECS 提供轻量、可控的容器运行环境。最终方案既满足个人学习项目的成本边界,也保留了向云数据库、对象存储和更可靠任务架构演进的空间。12. 参考资料华为云开发者空间实战案例参考页面华为云码道(CodeArts)代码智能体产品功能华为云码道(CodeArts)内置智能体用户指南ModelArts Studio(MaaS)API 调用规范华为云弹性云服务器 ECS 产品介绍
  • [交流吐槽] 套餐额度太少,计费不合理,使用将近一个月了,按需付费也没有缓存命中部分的单独计费,成本太高,准备换平台了
    套餐额度太少,计费不合理,使用将近一个月了,按需付费也没有缓存命中部分的单独计费,成本太高,准备换平台了 个人认为目前这个额度和费率,对于编程Agent而言非常不合理。   
  • [交流吐槽] Agent模式选择与Token高效使用技巧
    Agent模式选择与Token高效使用技巧在AI编程助手中,合理选择工作模式并养成高效的交互习惯,是平衡开发效率与成本的关键。本文将系统性地解析Ask、Plan、Agent三种模式的区别,并提供一套从模式选择到日常习惯的Token优化策略。一、 三种核心模式:定位与区别Ask、Plan、Agent模式在交互方式、任务处理逻辑和资源消耗上存在系统性差异,理解其定位是高效使用的前提。特性Ask(问答模式)Plan(计划模式)Agent(智能体模式)交互方式对话式,单轮请求-响应计划-批准-执行的多步交互目标驱动,全自动执行控制粒度细粒度,精确控制代码修改中粒度,可审查并调整执行计划粗粒度,只定义最终目标任务复杂度简单、原子性任务(如解释代码、写工具函数)中等至复杂的多步骤任务(如跨文件重构)非常复杂,需系统思维的任务(如实现完整功能)透明度高(直接看到代码变化)非常高(先审阅计划,后看执行)较低(像一个自主运行的黑盒)Token消耗低。单次交互,上下文依赖有限。中。生成计划和执行步骤需要额外Tokens,但避免了Agent的盲目试错。高。多轮迭代导致上下文滚动积累,Input Token占主导。Token消耗深度分析进行问题探索分析时从Agent模式切换到Ask模式下进行,能显著节约Tokens,Ask模式节约Tokens的原因在于其底层机制:单次交互:Ask模式通常针对单一问题生成回答,完成一轮对话后任务即结束,不会保留复杂的任务状态来回传递。有限上下文:它主要依赖当前文件或您选中的代码片段进行分析,避免了加载大量无关的项目文件信息。无迭代开销:不涉及复杂的“思考-行动-观察”循环,不会在每轮迭代中都反复携带完整的历史对话上下文。相比之下,Plan和Agent模式的Token消耗,尤其是Input Token的占比会显著更高。Agent模式是Token消耗的“大户”,它会像真正的程序员一样自主工作,进行多轮思考、编码、测试和调试,可能会有大量的“盲目行动”带来的高额试错成本。关键在于,每轮迭代它都可能将之前的完整上下文(包括思考过程、代码变更、错误信息等)重新作为输入,导致Input Token快速累积,占据总消耗的主导地位。二、 模式切换策略:梯度式开发以节约Tokens遵循“由简到繁,按需切换”的原则,可以构建一个既高效又经济的开发流程。第一阶:优先使用 Ask 模式进行探索和澄清场景:当您对问题本身或技术方案还不清晰时。做法:先用Ask模式提问,例如:“解释一下这个API的工作原理” 或 “为这个功能设计几种实现方案并分析利弊”。效果:以最小代价厘清思路,避免直接使用高级模式因目标模糊而产生大量无效迭代。第二阶:复杂或高风险任务升级到 Plan 模式场景:需要进行跨文件重构、添加复杂功能或框架迁移等。做法:使用Plan模式,让它先给出详细的步骤计划。您可以在执行前审查和调整,确保大方向正确。效果:Plan模式的透明度避免了Agent模式“盲目行动”可能带来的高额试错成本,实现了成本与风险的控制。第三阶:目标明确且琐碎的任务交付给 Agent 模式场景:实现一个定义清晰的完整功能(如“添加用户登录页面”),或修复一个原因不明的复杂Bug。做法:直接使用Agent模式,给出高级目标即可。效果:用较高的Token消耗换取您的时间解放,适合您不想关心实现细节的标准化任务。总结:Ask模式是最高效的“侦察兵”,Plan模式是可靠的“规划师”,Agent模式则是强大的“施工队”。在编程任务中,明智的做法是先派“侦察兵”探路,再让“规划师”绘制蓝图,最后才决定是否投入“施工队”进行大规模作业。三、 进阶Token节约习惯:从“习惯”到“精通”除了模式选择,日常的交互习惯对Token消耗的影响同样巨大。以下技巧由浅入深,能帮助您进一步优化成本。习惯适用人群设置成本节省效果1. 明智选择模型所有人1分钟习惯1.8倍至9倍/每次调用2. 精简输入文件所有人0分钟习惯每次请求高达80%3. 任务会话隔离所有人0分钟习惯长会话中30-50%4. 提问简短具体所有人0分钟习惯20-40%5. 定期压缩会话CLI用户0分钟习惯后续消息约40%6. 使用全局指令文件CLI用户10分钟每会话消除200-500个Token7. 压缩指令文件CLI用户5分钟每会话上下文Token约46%8. 使用项目级指令开发者5分钟每会话消除300-800个Token9. 配置ignore文件开发者10分钟文件查询时输入Token40-60%10. 启用响应压缩CLI用户2分钟输出Token65-75%习惯详解明智选择模型:不要默认使用最强大的模型。对于简单的问答和Agent任务,使用高性价比模型;对于复杂编码,使用中高级模型。仅在处理极其困难的任务时才召唤顶级模型。精简输入文件:避免附加整个代码库或巨大的文件。只提供完成任务所必需的最小代码片段。这能直接减少Input Token的数量。任务会话隔离:对于不相关的任务,开启新的聊天会话。避免在一个长会话中混合多个主题,这会累积不相关的上下文,导致每次请求都携带大量“历史包袱”。提问简短具体:清晰、简洁的指令能让AI更准确地理解您的意图,减少生成无关内容的风险,从而节约Input和Output Tokens。定期压缩会话:在CLI中,大约每20条消息使用一次/compact命令。这会总结并压缩历史对话,显著减少后续消息中携带的上下文长度。使用全局/项目级指令:通过全局指令文件(如instructions.md)或项目级指令来定义您的偏好、编码风格和常用规则。这避免了在每个会话中重复输入这些信息。配置ignore文件:类似于.gitignore,此文件可以指定哪些文件或目录在AI进行项目级查询时被忽略,如node_modules、dist等,从而大幅减少扫描的文件量。启用响应压缩:在CLI中启用响应压缩功能,可以显著缩短AI返回内容的长度,直接降低Output Token的消耗。养成好的习惯习惯 1:提问简短且具体提问时要简短且具体,避免模糊表达或超过当前问题覆盖范围,对AI而言表达越明确越好。将此添加到你的提示词中作用“用一句话”强制给出简短回答“只写代码,不解释”从回复中去除解释性文字“仅列出”跳过描述性段落“在 file1/file2/file3.ts 中”将范围限制在一个范围内“3 个要点”明确限制回复长度低效示例:“我有一个项目,你是否可以查看所有文件,理解它是如何工作的,或许还能提一些改进建议,并解释整个代码库中可能的安全问题……”高效示例:“用 3 个要点总结 file1/file2/file3.ts 中的xx流程。”习惯 2:引用具体文件,而非所有文件始终指明希望助手查看的具体文件、函数或行号。除非确实需要,否则绝不要说“整个项目”或“所有内容”。“查看我的项目并找出所有 Bug” = 助手尝试读取每个文件 = 消耗海量 Token。“检查 file1/file2/file3.ts 中的空指针 Bug” = 一个文件,一个问题 = 节省 95% 的 Token。习惯 3:当你想要简短答案时,明确要求简短回答助手默认会提供详细的解释。除非你明确说明,否则它不知道你想要一个简洁的答案。“这个函数是做什么的?最多两句话。”“修复第 xx 行的 Bug。只给出代码。”“这个方法正确吗?是/否,并给出一个理由。”习惯 4:为每个新任务开启新对话一个任务 = 一次对话。当你完成一个任务或切换主题时,开启一个全新的对话。不要在一个长的会话中处理多个不相关的任务。对话中的每条消息都会与之前所有的消息一起作为上下文重新发送。在经过 10 轮左右对话后,每提出一个新问题,都需要为重新处理整个历史记录付费——即使这些历史记录已经完全无关。习惯 5:对于简单任务,使用常规聊天模式而非智能体Agent模式智能体模式的成本显著高于常规聊天模式——由于累积的上下文,其每一步的成本可能是常规问答的 10 倍左右。使用智能体模式的情况使用常规聊天模式的情况重构整个认证模块修复第 xx 行的 Bug为整个功能添加单元测试为这个函数写一个测试从一个框架迁移到另一个框架向我展示如何使用这个 API从零开始构建一个新功能解释这段代码是如何工作的提示:如果智能体模式运行超过 15 步且没有进展,请停止它,不要再让智能体继续尝试迭代了。每一次失败的尝试仍然会消耗Tokens。习惯 6:对于复杂任务,先使用常规聊天模式探索澄清,然后使用Plan模式规划可行的操作步骤,最后再使用智能体Agent模式“施工”避免直接使用Agent模式,没有清晰可行的任务规划时,Agent模式可能会有大量的“盲目行动”带来的高额试错成本。总结在Agent中实现Token高效利用是一个多维度的策略:核心策略:采用梯度式模式切换,从Ask到Plan再到Agent,步步为营。日常习惯:养成精简输入、隔离任务、选择合适模型等基础好习惯。进阶技巧:利用指令文件、ignore配置和会话压缩等工具进行深度优化。通过综合运用以上方法,您将能够在享受AI编程助手带来的巨大便利的同时,有效控制其使用成本,实现效率与经济的双赢。
  • [OpenClaw体验] OpenClaw体验案例:股票分析助手--一句话把金融专家带回家(含一句话提示词)
    前往华为云Openclaw部署与配置:华为云一键部署OpenClaw-华为云,配置完成后,复制下方指令,一句话即可体验,模型生成有随机性,期待你做出的不同效果通过 clawhub 寻找 multi search engine 和 stock analysis 两个技能skill并安装,使用中国镜像站 https://cn.clawhub-mirror.com页面效果展示:龙虾开始自动安装技能skill(联网搜索+股票分析)技能安装完毕安装完成后对话框输入:帮我用multi search engine 和 stock analysis这两个skill详细分析一下茅台股票。更多实时行情、盘面分析、基本面、风险提示等,一句话即可体验,期待你的养虾之旅!