znlgis 博客

GIS开发与技术分享

第十八章:Web 界面与 API 服务

18.1 概述

GeoPipeAgent 提供了一套完整的 Web 可视化界面,包含:

  • 前端:Vue 3 + TypeScript + Vite,可视化流水线编辑器 + LLM 对话助手
  • 后端:FastAPI + Python,提供 REST API + SSE 流式响应
  • 任务队列:Redis + RQ(Python Redis Queue),支持长时任务异步执行
  • 国际化:中英文双语界面(i18n)
浏览器 (Vue 3)
    ↕ HTTP / SSE
FastAPI 后端 (Python)
    ↕ OpenAI 兼容 API          ← LLM 服务(DeepSeek/GPT-4 等)
    ↕ Redis RQ 任务队列
RQ Worker(后台执行流水线)

18.2 启动 Web 服务

方法 1:Docker Compose(推荐)

# 1. 配置环境变量
cp .env.example .env
vim .env    # 填写 LLM_API_KEY 等

# 2. 启动所有服务
docker compose up -d

# 3. 检查服务状态
docker compose ps

访问地址:

  • 前端 UI:http://localhost:3000
  • 后端 API:http://localhost:8000
  • API 文档:http://localhost:8000/docs

方法 2:本地开发模式

# 安装依赖
pip install -e ".[web]"
pip install -r web/backend/requirements.txt
cd web/frontend && npm install

# 启动 Redis(需单独安装)
redis-server &

# 启动后端 API 服务
cd web/backend
uvicorn main:app --host 0.0.0.0 --port 8000 --reload

# 启动 RQ Worker(新终端)
cd web/backend
python -m rq worker geopipe

# 启动前端开发服务器(新终端)
cd web/frontend
npm run dev

18.3 前端功能模块

前端采用 Vue 3 Composition API + Pinia 状态管理 + Vue Router,包含以下主要视图:

18.3.1 流水线编辑器(PipelineEditor.vue)

可视化流水线编辑器是 Web UI 的核心功能:

主要组件

  • FlowCanvas:基于 VueFlow/ReactFlow 的流程图画布,支持拖拽节点
  • StepNode:步骤节点组件,显示步骤 ID、类型、状态
  • NodePalette:步骤选择面板,列出所有可用步骤类别和步骤
  • StepConfigPanel:选中节点的参数配置面板

主要功能

  • 从节点面板拖拽步骤到画布
  • 拖拽连线建立步骤间的数据流连接
  • 点击节点打开参数配置面板
  • 实时 YAML 预览(与画布双向同步)
  • 一键执行流水线,实时显示执行进度

18.3.2 LLM 对话助手(LlmChat.vue)

内嵌 AI 对话界面:

主要组件

  • ChatWindow:对话窗口,支持 Markdown 渲染
  • MessageBubble:消息气泡(用户消息 / AI 回复)

主要功能

  • 用自然语言描述 GIS 分析需求
  • AI 自动生成 YAML 流水线(基于 Skill 文件)
  • 生成的流水线可一键导入编辑器
  • 对话历史持久化存储

交互示例

用户:帮我分析城市公园的 500 米步行可达范围,并找出范围内的居住小区

AI:我来为你生成一个公园可达性分析流水线:

[生成 YAML 按钮]

name: 公园步行可达性分析
...(YAML 内容)

这个流水线包含:
1. 读取公园和居住小区数据
2. 生成公园 500 米缓冲区
3. 查找缓冲区内的居住小区
4. 保存结果

18.3.3 模板库(TemplateGallery.vue)

预置流水线模板,一键使用:

  • 缓冲区分析
  • 叠加分析
  • 批量格式转换
  • 数据质检(矢量/栅格)
  • 等高线提取
  • 空间统计

点击模板即可在编辑器中打开,修改参数后执行。

18.3.4 Skill 管理(SkillManager.vue)

管理 AI 使用的 Skill 文件模块:

  • 查看当前加载的 Skill 模块列表
  • 启用/禁用特定步骤类别的 Skill
  • 上传自定义 Skill 文件(支持自定义步骤的 AI 能力扩展)

18.3.5 任务管理(TaskManager.vue)

管理后台异步任务:

  • 查看所有任务的状态(排队中/执行中/完成/失败)
  • 实时查看任务执行日志(SSE 推送)
  • 取消排队中的任务
  • 查看任务历史报告

18.3.6 对话历史(ConversationHistory.vue)

查看和管理历史 AI 对话:

  • 按时间列出历史对话
  • 搜索历史对话内容
  • 从历史对话中重新导入生成的流水线
  • 清理历史记录

18.4 后端 API 服务

项目结构

web/backend/
├── main.py                    # FastAPI 应用入口
├── config.py                  # LLM 配置管理(读取 .env)
├── models/
│   └── schemas.py             # Pydantic 数据模型(请求/响应)
├── routers/                   # API 路由
│   ├── pipeline.py            # 流水线操作 API
│   ├── llm.py                 # LLM 对话/生成 API
│   ├── export.py              # 导出 API
│   ├── skill.py               # Skill 模块管理 API
│   ├── template.py            # 流水线模板 API
│   └── task.py                # 后台任务管理 API
└── services/                  # 业务逻辑
    ├── llm_service.py         # OpenAI 兼容 LLM 服务
    ├── conversation_store.py  # 对话历史持久化
    ├── pipeline_service.py    # 流水线执行服务
    └── task_queue.py          # Redis RQ 任务队列

主要 API 端点

流水线相关(/api/pipeline

方法 路径 说明
POST /api/pipeline/validate 校验 YAML 流水线
POST /api/pipeline/run 同步执行流水线(小任务)
POST /api/pipeline/run/async 异步执行流水线(大任务,返回 task_id)
GET /api/pipeline/steps 获取所有步骤列表
GET /api/pipeline/steps/{step_id} 获取步骤详情
GET /api/pipeline/backends 获取后端状态

LLM 相关(/api/llm

方法 路径 说明
POST /api/llm/chat 发送对话消息,流式返回(SSE)
POST /api/llm/generate 根据需求描述生成流水线
POST /api/llm/analyze 分析流水线结果报告
GET /api/llm/conversations 获取对话历史列表
DELETE /api/llm/conversations/{id} 删除指定对话

任务管理(/api/task

方法 路径 说明
GET /api/task/{task_id} 获取任务状态
GET /api/task/{task_id}/logs 获取任务日志(SSE 流式推送)
DELETE /api/task/{task_id} 取消任务
GET /api/task/ 获取所有任务列表

Skill 管理(/api/skill

方法 路径 说明
GET /api/skill/modules 获取 Skill 模块列表
PUT /api/skill/modules/{module} 启用/禁用 Skill 模块
POST /api/skill/upload 上传自定义 Skill 文件

API 使用示例

执行流水线(同步)

import requests

response = requests.post(
    "http://localhost:8000/api/pipeline/run",
    json={
        "yaml": """
name: 缓冲区分析
steps:
  - id: load
    use: io.read_vector
    params:
      path: data/roads.geojson
  - id: buffer
    use: vector.buffer
    params:
      input: $load
      distance: 500
  - id: save
    use: io.write_vector
    params:
      input: $buffer
      path: output/result.geojson
""",
        "variables": {
            "input_path": "data/roads.geojson"
        }
    }
)
report = response.json()
print(f"状态:{report['pipeline']['status']}")

与 LLM 对话(SSE 流式返回)

import requests
import json

with requests.post(
    "http://localhost:8000/api/llm/chat",
    json={
        "message": "帮我写一个缓冲区分析流水线",
        "conversation_id": "session-001"
    },
    stream=True
) as response:
    for line in response.iter_lines():
        if line.startswith(b"data: "):
            data = json.loads(line[6:])
            print(data.get("content", ""), end="", flush=True)

异步执行大任务

import requests
import time

# 提交异步任务
submit_response = requests.post(
    "http://localhost:8000/api/pipeline/run/async",
    json={"yaml": large_pipeline_yaml}
)
task_id = submit_response.json()["task_id"]

# 轮询任务状态
while True:
    status_response = requests.get(f"http://localhost:8000/api/task/{task_id}")
    status = status_response.json()
    
    if status["status"] == "completed":
        print("任务完成!")
        print(status["result"])
        break
    elif status["status"] == "failed":
        print(f"任务失败:{status['error']}")
        break
    else:
        print(f"执行中... ({status.get('progress', 0)}%)")
        time.sleep(2)

18.5 后端服务配置(config.py)

# web/backend/config.py
from pydantic_settings import BaseSettings

class Settings(BaseSettings):
    # LLM 配置
    llm_api_key: str = ""
    llm_base_url: str = "https://api.openai.com/v1"
    llm_model: str = "gpt-4o"
    
    # 服务端口
    backend_port: int = 8000
    frontend_port: int = 3000
    redis_port: int = 6379
    
    # Redis 连接
    redis_url: str = "redis://localhost:6379"
    
    class Config:
        env_file = ".env"

settings = Settings()

支持的 LLM 服务(任何 OpenAI 兼容 API):

服务 LLM_BASE_URL 推荐模型
OpenAI https://api.openai.com/v1 gpt-4o
DeepSeek https://api.deepseek.com/v1 deepseek-chat / deepseek-reasoner
Ollama(本地) http://localhost:11434/v1 llama3.1:70b
通义千问 https://dashscope.aliyuncs.com/compatible-mode/v1 qwen-max

18.6 Docker 服务架构

# docker-compose.yml 中的四个服务

services:
  frontend:         # Nginx 静态文件服务器
    image: nginx    # 托管 Vue 3 构建产物
    ports: ["3000:80"]
  
  backend:          # FastAPI + GDAL
    build: ./web/backend
    # 基于 ghcr.io/osgeo/gdal:ubuntu-small-3.8.4 镜像
    # 内置 GDAL 3.8.4 + Python 3.11
    ports: ["8000:8000"]
    env_file: .env
    volumes:
      - ./data:/app/data    # 挂载本地数据目录
      - ./output:/app/output
  
  redis:            # Redis 7(任务队列后端)
    image: redis:7-alpine
    ports: ["6379:6379"]
  
  worker:           # RQ 后台任务处理工作进程
    build: ./web/backend
    command: python -m rq worker geopipe
    # 与 backend 共享镜像,但执行 RQ Worker 命令

数据目录挂载

docker-compose.yml 中,data/output/ 目录被挂载到容器中:

# 将数据文件放入 data/ 目录
cp my-data.shp data/

# 执行流水线(通过 Web UI 或 API)
# 流水线 YAML 中使用 data/my-data.shp 路径

# 结果文件会出现在 output/ 目录
ls output/

18.7 前端测试

# 单元测试(Vitest)
cd web/frontend
npm run test

# E2E 测试(Playwright)
npm run test:e2e

18.8 后端测试

# 后端 API 测试(pytest)
pip install -r web/backend/requirements.txt
pytest web/backend/tests/ -v

测试覆盖:

  • 56 个 API 测试(pipeline/llm/task/skill/template 接口)
  • 流水线执行集成测试
  • LLM 服务 Mock 测试

18.9 小结

本章介绍了 GeoPipeAgent 的 Web 界面与 API 服务:

前端(Vue 3)

  • 流水线编辑器(可视化拖拽 + YAML 双向同步)
  • LLM 对话助手(SSE 流式输出)
  • 模板库、Skill 管理、任务管理、对话历史

后端(FastAPI)

  • 流水线 API(同步/异步执行)
  • LLM API(对话/生成/分析)
  • 任务管理 API(Redis RQ)
  • Skill 管理 API

部署:Docker Compose 一键启动 4 个服务(前端/后端/Redis/Worker)

下一章将介绍如何开发自定义步骤和扩展 GeoPipeAgent 的能力。