langchain-learning-kit/docs/frontend-vue3/TASK_frontend-vue3.md

21 KiB
Raw Permalink Blame History

前端项目任务拆分文档 (TASK)

任务名称

frontend-vue3

任务依赖图

graph TD
    T1[T1: 初始化项目脚手架] --> T2[T2: 配置Axios客户端]
    T2 --> T3[T3: 封装模型管理API]
    T2 --> T4[T4: 封装知识库API]
    T2 --> T5[T5: 封装对话API]
    T2 --> T6[T6: 封装Agent API]

    T1 --> T7[T7: 配置路由]
    T7 --> T8[T8: 创建主布局]

    T3 --> T9[T9: 实现模型管理页]
    T4 --> T10[T10: 实现知识库管理页]
    T5 --> T11[T11: 实现对话列表页]
    T5 --> T12[T12: 实现聊天页面]
    T6 --> T13[T13: 实现Agent执行页]

    T8 --> T9
    T8 --> T10
    T8 --> T11
    T8 --> T12
    T8 --> T13

    T9 --> T14[T14: 集成测试]
    T10 --> T14
    T11 --> T14
    T12 --> T14
    T13 --> T14

    T14 --> T15[T15: 文档编写]

    style T1 fill:#e1f5fe
    style T2 fill:#fff3e0
    style T7 fill:#f3e5f5
    style T8 fill:#e8f5e9
    style T14 fill:#ffebee
    style T15 fill:#fff9c4

原子任务列表

T1: 初始化项目脚手架

优先级: P0阻塞 复杂度: 低 预估工时: 30分钟

输入契约:

  • 前置依赖: 无
  • 输入数据: 项目根目录路径
  • 环境依赖: Node.js 18+, npm/pnpm

实现内容:

  1. 创建 frontend/ 文件夹
  2. 使用 Vite 初始化 Vue3 项目
  3. 安装核心依赖:
    npm create vite@latest frontend -- --template vue
    cd frontend
    npm install
    npm install vue-router axios element-plus @element-plus/icons-vue
    
  4. 配置 vite.config.js(别名 @、端口 5173
  5. 创建目录结构:
    src/
    ├── api/
    ├── components/
    ├── views/
    ├── router/
    ├── utils/
    ├── assets/
    └── styles/
    

输出契约:

  • 交付物: 可运行的 Vue3 项目骨架
  • 验收标准: npm run dev 启动成功,访问 localhost:5173 显示默认页面
  • 质量要求: 目录结构清晰,依赖版本锁定

后置任务: T2, T7


T2: 配置Axios客户端

优先级: P0阻塞 复杂度: 中 预估工时: 1小时

输入契约:

  • 前置依赖: T1
  • 输入数据: API Base URL (环境变量)
  • 环境依赖: Axios 已安装

实现内容:

  1. 创建 .env.development:
    VITE_API_BASE_URL=http://localhost:8000/api/v1
    
  2. 创建 src/api/client.js:
    import axios from 'axios'
    import { ElMessage } from 'element-plus'
    
    const client = axios.create({
      baseURL: import.meta.env.VITE_API_BASE_URL,
      timeout: 30000
    })
    
    // 请求拦截器
    client.interceptors.request.use(config => {
      return config
    })
    
    // 响应拦截器
    client.interceptors.response.use(
      response => response.data,
      error => {
        // 错误处理逻辑(详见设计文档)
        return Promise.reject(error)
      }
    )
    
    export default client
    
  3. 创建 src/utils/message.js(封装 ElMessage

输出契约:

  • 交付物: 配置完成的 Axios 实例
  • 验收标准:
    • 拦截器正确处理 4xx/5xx 错误
    • 环境变量正确读取
    • 网络错误显示提示
  • 质量要求: 错误提示用户友好,支持详细错误信息

后置任务: T3, T4, T5, T6


T3: 封装模型管理API

优先级: P1 复杂度: 低 预估工时: 30分钟

输入契约:

  • 前置依赖: T2
  • 接口文档: /models 相关接口
  • 环境依赖: Axios client

实现内容: 创建 src/api/models.js:

import client from './client'

export const modelAPI = {
  list(type) {
    return client.get('/models', { params: { type } })
  },

  create(data) {
    return client.post('/models', data)
  },

  getById(id) {
    return client.get(`/models/${id}`)
  },

  update(id, data) {
    return client.patch(`/models/${id}`, data)
  },

  delete(id) {
    return client.delete(`/models/${id}`)
  }
}

输出契约:

  • 交付物: 模型 API 封装模块
  • 验收标准: 所有方法签名与设计文档一致
  • 质量要求: 参数类型明确,返回 Promise

后置任务: T9


T4: 封装知识库API

优先级: P1 复杂度: 低 预估工时: 30分钟

输入契约:

  • 前置依赖: T2
  • 接口文档: /kb 相关接口

实现内容: 创建 src/api/kb.js:

import client from './client'

export const kbAPI = {
  list() {
    return client.get('/kb')
  },

  create(data) {
    return client.post('/kb', data)
  },

  getById(id) {
    return client.get(`/kb/${id}`)
  },

  delete(id) {
    return client.delete(`/kb/${id}`)
  },

  ingest(id, data) {
    return client.post(`/kb/${id}/ingest`, {
      ...data,
      background: true  // 固定为异步
    })
  },

  query(id, data) {
    return client.post(`/kb/${id}/query`, data)
  },

  getStatus(id) {
    return client.get(`/kb/${id}/status`)
  }
}

输出契约:

  • 交付物: 知识库 API 封装模块
  • 验收标准: 所有方法可正常调用
  • 质量要求: ingest 方法固定 background=true

后置任务: T10


T5: 封装对话API

优先级: P1 复杂度: 低 预估工时: 30分钟

输入契约:

  • 前置依赖: T2
  • 接口文档: /conversations 相关接口

实现内容: 创建 src/api/conversations.js:

import client from './client'

export const conversationAPI = {
  create(data) {
    return client.post('/conversations', data)
  },

  getById(id) {
    return client.get(`/conversations/${id}`)
  },

  delete(id) {
    return client.delete(`/conversations/${id}`)
  },

  getMessages(id, params) {
    return client.get(`/conversations/${id}/messages`, { params })
  },

  chat(id, data) {
    return client.post(`/conversations/${id}/chat`, data)
  }
}

输出契约:

  • 交付物: 对话 API 封装模块
  • 验收标准: 支持分页参数传递
  • 质量要求: getMessages 方法正确处理 limit/offset

后置任务: T11, T12


T6: 封装Agent API

优先级: P1 复杂度: 低 预估工时: 20分钟

输入契约:

  • 前置依赖: T2
  • 接口文档: /agent 相关接口

实现内容: 创建 src/api/agent.js:

import client from './client'

export const agentAPI = {
  execute(data) {
    return client.post('/agent/execute', data)
  },

  getLogs(agentId, params) {
    return client.get(`/agent/logs/${agentId}`, { params })
  }
}

输出契约:

  • 交付物: Agent API 封装模块
  • 验收标准: 方法可正常调用
  • 质量要求: 参数传递正确

后置任务: T13


T7: 配置路由

优先级: P0阻塞 复杂度: 低 预估工时: 30分钟

输入契约:

  • 前置依赖: T1
  • 路由设计: 参考设计文档

实现内容:

  1. 创建 src/router/index.js:
    import { createRouter, createWebHistory } from 'vue-router'
    
    const routes = [
      { path: '/', redirect: '/models' },
      { path: '/models', name: 'Models', component: () => import('@/views/Models.vue') },
      { path: '/knowledge-base', name: 'KnowledgeBase', component: () => import('@/views/KnowledgeBase.vue') },
      { path: '/conversations', name: 'Conversations', component: () => import('@/views/Conversations.vue') },
      { path: '/conversations/:id/chat', name: 'Chat', component: () => import('@/views/Chat.vue'), props: true },
      { path: '/agent', name: 'Agent', component: () => import('@/views/Agent.vue') }
    ]
    
    export default createRouter({
      history: createWebHistory(),
      routes
    })
    
  2. main.js 中注册路由
  3. App.vue 中添加 <router-view />

输出契约:

  • 交付物: 路由配置文件
  • 验收标准: 路由可正常跳转(临时创建空白页面组件)
  • 质量要求: 懒加载配置正确props 传递配置正确

后置任务: T8


T8: 创建主布局

优先级: P0阻塞 复杂度: 中 预估工时: 1小时

输入契约:

  • 前置依赖: T7
  • 设计稿: 参考设计文档布局

实现内容:

  1. 修改 App.vue:
    <template>
      <el-container style="height: 100vh">
        <el-aside width="200px">
          <el-menu :default-active="$route.path" router>
            <el-menu-item index="/models">
              <el-icon><Setting /></el-icon>
              <span>模型管理</span>
            </el-menu-item>
            <el-menu-item index="/knowledge-base">
              <el-icon><Document /></el-icon>
              <span>知识库</span>
            </el-menu-item>
            <el-menu-item index="/conversations">
              <el-icon><ChatDotRound /></el-icon>
              <span>对话</span>
            </el-menu-item>
            <el-menu-item index="/agent">
              <el-icon><Tools /></el-icon>
              <span>Agent</span>
            </el-menu-item>
          </el-menu>
        </el-aside>
        <el-main>
          <router-view />
        </el-main>
      </el-container>
    </template>
    
  2. main.js 中引入 Element Plus 样式
  3. 创建全局样式 src/styles/global.css

输出契约:

  • 交付物: 主布局组件
  • 验收标准:
    • 左侧菜单可正常导航
    • 当前路由高亮显示
    • 响应式布局正常
  • 质量要求: 样式简洁,图标清晰

后置任务: T9, T10, T11, T12, T13


T9: 实现模型管理页

优先级: P1 复杂度: 中 预估工时: 2小时

输入契约:

  • 前置依赖: T3, T8
  • API: modelAPI
  • UI 组件: Element Plus

实现内容: 创建 src/views/Models.vue:

  1. 模型列表表格ID, 名称, 类型, 状态, 默认, 操作)
  2. 类型筛选Select: 全部/LLM/Embedding
  3. 创建模型弹窗表单name, type, config, is_default
  4. 编辑功能复用表单PATCH 更新)
  5. 删除确认ElMessageBox
  6. 加载状态ElLoading

核心逻辑:

const modelList = ref([])
const loading = ref(false)
const dialogVisible = ref(false)
const formData = ref({})
const typeFilter = ref('')

const fetchModels = async () => {
  loading.value = true
  try {
    modelList.value = await modelAPI.list(typeFilter.value)
  } finally {
    loading.value = false
  }
}

const handleCreate = async () => {
  await formRef.value.validate()
  await modelAPI.create(formData.value)
  ElMessage.success('创建成功')
  dialogVisible.value = false
  fetchModels()
}

const handleDelete = async (id) => {
  await ElMessageBox.confirm('确认删除?')
  await modelAPI.delete(id)
  ElMessage.success('删除成功')
  fetchModels()
}

输出契约:

  • 交付物: 模型管理页面组件
  • 验收标准:
    • CRUD 操作全部可用
    • 表单验证正确
    • 错误提示显示
  • 质量要求: 用户体验流畅,代码结构清晰

后置任务: T14


T10: 实现知识库管理页

优先级: P1 复杂度: 高 预估工时: 3小时

输入契约:

  • 前置依赖: T4, T8
  • API: kbAPI, modelAPI获取 embedding 列表)

实现内容: 创建 src/views/KnowledgeBase.vue:

  1. 知识库列表ID, 名称, 描述, 文档数, 操作)
  2. 创建知识库表单
  3. 文档摄取弹窗:
    • 动态添加/删除文档行
    • 每行title, content (textarea), source, metadata (JSON)
    • Embedding 模型选择(从模型列表获取 type=embedding
    • 提交后显示成功提示(不追踪状态)
  4. 查询弹窗:
    • 查询文本输入
    • k 值选择1-10
    • Embedding 模型选择
    • 结果展示(卡片形式,显示 content + score
  5. 状态查看(显示文档数、索引状态)
  6. 删除知识库

核心逻辑:

const kbList = ref([])
const documents = ref([{ title: '', content: '', source: '', metadata: {} }])
const embeddingModels = ref([])
const queryResults = ref([])

const addDocument = () => {
  documents.value.push({ title: '', content: '', source: '', metadata: {} })
}

const handleIngest = async () => {
  await kbAPI.ingest(currentKbId.value, {
    documents: documents.value,
    embedding_name: selectedEmbedding.value
  })
  ElMessage.success('文档摄取任务已提交')
  ingestDialogVisible.value = false
}

const handleQuery = async () => {
  queryResults.value = await kbAPI.query(currentKbId.value, {
    query: queryForm.value.query,
    k: queryForm.value.k,
    embedding_name: selectedEmbedding.value
  })
}

输出契约:

  • 交付物: 知识库管理页面组件
  • 验收标准:
    • 可动态添加多个文档
    • 摄取提交成功显示提示
    • 查询返回结果正确展示
    • 状态信息准确显示
  • 质量要求: 表单复杂但易用,查询结果清晰

后置任务: T14


T11: 实现对话列表页

优先级: P1 复杂度: 低 预估工时: 1小时

输入契约:

  • 前置依赖: T5, T8
  • API: conversationAPI

实现内容: 创建 src/views/Conversations.vue:

  1. 会话列表表格ID, 标题, 用户ID, 创建时间, 操作)
  2. 创建会话表单user_id, title
  3. "进入聊天"按钮(跳转到 /conversations/:id/chat
  4. 删除会话(确认弹窗)

核心逻辑:

const conversationList = ref([])

const fetchConversations = async () => {
  conversationList.value = await conversationAPI.list()
}

const handleCreate = async () => {
  const newConv = await conversationAPI.create(formData.value)
  ElMessage.success('创建成功')
  fetchConversations()
  // 可选:自动跳转到聊天页
  router.push(`/conversations/${newConv.id}/chat`)
}

const enterChat = (id) => {
  router.push(`/conversations/${id}/chat`)
}

输出契约:

  • 交付物: 对话列表页面组件
  • 验收标准:
    • 列表正确展示
    • 创建会话成功
    • 跳转聊天页正常
  • 质量要求: 交互简洁明了

后置任务: T14


T12: 实现聊天页面

优先级: P1 复杂度: 高 预估工时: 3小时

输入契约:

  • 前置依赖: T5, T8
  • API: conversationAPI, kbAPI, modelAPI
  • 路由参数: conversation_id

实现内容: 创建 src/views/Chat.vue:

  1. 顶部配置栏:
    • RAG 开关Switch
    • 知识库选择(显示在 RAG 启用时)
    • LLM 选择
  2. 消息区域:
    • 消息列表(用户/助手气泡)
    • 显示来源信息sources
    • "加载更多"按钮(分页)
    • 自动滚动到底部
  3. 输入区域:
    • 文本输入框(支持 Enter 发送)
    • 发送按钮
  4. 分页加载逻辑:
    • 初始 limit=50, offset=0
    • 点击"加载更多" offset+=50

核心逻辑:

const conversationId = ref(route.params.id)
const messages = ref([])
const inputText = ref('')
const useRag = ref(true)
const selectedKbId = ref(null)
const selectedLlm = ref(null)
const pagination = ref({ limit: 50, offset: 0, hasMore: true })

const loadMessages = async (loadMore = false) => {
  const params = {
    limit: pagination.value.limit,
    offset: loadMore ? pagination.value.offset : 0
  }
  const newMessages = await conversationAPI.getMessages(conversationId.value, params)

  if (loadMore) {
    messages.value = [...newMessages, ...messages.value]
    pagination.value.offset += pagination.value.limit
  } else {
    messages.value = newMessages
  }

  pagination.value.hasMore = newMessages.length === pagination.value.limit
}

const sendMessage = async () => {
  const userMessage = { role: 'user', content: inputText.value }
  messages.value.push(userMessage)

  const response = await conversationAPI.chat(conversationId.value, {
    user_input: inputText.value,
    kb_id: useRag.value ? selectedKbId.value : null,
    llm_name: selectedLlm.value,
    use_rag: useRag.value
  })

  messages.value.push(response)
  inputText.value = ''
  scrollToBottom()
}

const scrollToBottom = () => {
  nextTick(() => {
    messageArea.value.scrollTop = messageArea.value.scrollHeight
  })
}

输出契约:

  • 交付物: 聊天页面组件
  • 验收标准:
    • 消息正确展示(用户/助手区分)
    • 分页加载正常
    • RAG 切换生效
    • 来源信息显示
    • 自动滚动到底部
  • 质量要求: 聊天体验流畅UI 友好

后置任务: T14


T13: 实现Agent执行页

优先级: P1 复杂度: 中 预估工时: 2小时

输入契约:

  • 前置依赖: T6, T8
  • API: agentAPI, kbAPI, modelAPI

实现内容: 创建 src/views/Agent.vue:

  1. 任务输入区:
    • 任务描述Textarea
    • 知识库选择(可选)
    • LLM 选择
    • 执行按钮
  2. 结果展示区:
    • 执行状态(成功/失败)
    • 输出结果Card 显示)
    • Agent ID 展示
  3. 日志展示区(自动加载):
    • 工具调用日志表格
    • 列:工具名称、输入、输出、时间
    • 支持展开查看详细 JSON

核心逻辑:

const taskInput = ref('')
const selectedKbId = ref(null)
const selectedLlm = ref(null)
const executionResult = ref(null)
const toolCallLogs = ref([])
const executing = ref(false)

const handleExecute = async () => {
  executing.value = true
  try {
    const result = await agentAPI.execute({
      task: taskInput.value,
      kb_id: selectedKbId.value,
      llm_name: selectedLlm.value
    })

    executionResult.value = result

    // 自动加载日志
    if (result.agent_id) {
      const logs = await agentAPI.getLogs(result.agent_id)
      toolCallLogs.value = logs.tool_calls
    }
  } finally {
    executing.value = false
  }
}

输出契约:

  • 交付物: Agent 执行页面组件
  • 验收标准:
    • 任务执行成功
    • 结果正确展示
    • 日志自动加载并显示
    • 加载状态显示
  • 质量要求: 日志信息清晰JSON 展示友好

后置任务: T14


T14: 集成测试

优先级: P0 复杂度: 中 预估工时: 2小时

输入契约:

  • 前置依赖: T9, T10, T11, T12, T13
  • 环境依赖: 后端服务运行在 localhost:8000

实现内容:

  1. 功能测试:

    • 创建 LLM 模型配置
    • 创建 Embedding 模型配置
    • 创建知识库
    • 摄取测试文档
    • 查询知识库
    • 创建会话
    • 发送消息(启用/禁用 RAG
    • 执行 Agent 任务
    • 查看 Agent 日志
  2. 边界测试:

    • 表单验证(空值、格式错误)
    • 网络错误处理(关闭后端)
    • 404 错误(不存在的 ID
    • 分页边界offset 超出范围)
  3. 用户体验测试:

    • Loading 状态显示
    • 成功/失败提示
    • 路由跳转流畅
    • 响应式布局

测试清单:

  • 模型管理所有操作
  • 知识库所有操作
  • 对话所有操作
  • Agent 执行和日志
  • 错误场景处理
  • 用户体验验证

输出契约:

  • 交付物: 测试报告(记录在 ACCEPTANCE 文档)
  • 验收标准: 所有核心流程通过
  • 质量要求: 发现的问题及时修复

后置任务: T15


T15: 文档编写

优先级: P1 复杂度: 低 预估工时: 1小时

输入契约:

  • 前置依赖: T14
  • 项目信息: package.json, 环境配置

实现内容:

  1. 创建 frontend/README.md:

    # LangChain Learning Kit - 前端
    
    ## 技术栈
    - Vue 3 + Vite
    - Element Plus
    - Axios + Vue Router
    
    ## 环境要求
    - Node.js 18+
    - npm 9+
    
    ## 快速开始
    \`\`\`bash
    # 安装依赖
    npm install
    
    # 启动开发服务器
    npm run dev
    
    # 构建生产包
    npm run build
    \`\`\`
    
    ## 环境配置
    创建 `.env.development`:
    \`\`\`
    VITE_API_BASE_URL=http://localhost:8000/api/v1
    \`\`\`
    
    ## 功能说明
    - 模型管理:/models
    - 知识库:/knowledge-base
    - 对话:/conversations
    - Agent/agent
    
    ## 注意事项
    - 确保后端服务运行在 localhost:8000
    - 浏览器访问 http://localhost:5173
    
  2. 创建 .env.example:

    VITE_API_BASE_URL=http://localhost:8000/api/v1
    
  3. 更新 .gitignore:

    .env.local
    dist/
    node_modules/
    

输出契约:

  • 交付物: README.md, .env.example
  • 验收标准: 文档清晰,新用户可按文档启动项目
  • 质量要求: 说明完整,格式规范

后置任务: 无(最后任务)


任务执行顺序

第一批(并行)

  • T1: 初始化项目脚手架

第二批(并行)

  • T2: 配置 Axios 客户端
  • T7: 配置路由

第三批(并行)

  • T3: 封装模型管理 API
  • T4: 封装知识库 API
  • T5: 封装对话 API
  • T6: 封装 Agent API
  • T8: 创建主布局

第四批(并行)

  • T9: 实现模型管理页
  • T10: 实现知识库管理页
  • T11: 实现对话列表页
  • T12: 实现聊天页面
  • T13: 实现 Agent 执行页

第五批(串行)

  • T14: 集成测试
  • T15: 文档编写

风险控制

任务风险

  1. T10 复杂度高: 文档摄取多字段,可能需要更多时间

    • 缓解:预留缓冲时间,优先实现核心功能
  2. T12 分页逻辑: offset/limit 边界处理

    • 缓解:参考设计文档,做好边界检查
  3. T14 后端依赖: 需要后端服务正常运行

    • 缓解:提前验证后端 API 可用性

时间风险

  • 总预估工时: 约 16 小时
  • 建议工期: 2-3 个工作日
  • 缓冲时间: 预留 20% 用于调试和优化

任务拆分完成,等待审批。