芯图相册照片大模型分类的后端技术架构

摘要

V2接口采用三层分层架构(基础服务层/Provider层/业务层),提供图像分类、颜色识别、构图分析、图像编辑、文本生成5大功能。统一缓存架构支持多模型结果集合和批量查询。位置服务实现智能降级(本地DB→外部API→v1查询)和中国/海外坐标自动路由。技术栈:FastAPI + MySQL + 全异步架构,支持多提供商(阿里云/OpenAI/Claude/Deepseek)。


一、大模型服务分层架构

1.1 架构概览

V2接口采用分架构设计,实现了清晰的职责分离和统一的接口抽象:

在这里插入图片描述

1.2 基础服务层 (Base Service Layer)

文件位置: app/services/llm/base_service.py

核心职责:

  • 统一的错误处理和分类
  • 自动重试机制(指数退避)
  • 超时控制
  • 统一的日志记录
  • 错误类型枚举和转换

关键特性:

  • 错误类型分类:
    • 可重试错误: NETWORK_ERROR, SERVER_ERROR, RATE_LIMIT_ERROR, FORMAT_ERROR
    • 不可重试错误: INPUT_ERROR, AUTH_ERROR, BUSINESS_ERROR
  • 重试策略: 最大重试3次,指数退避延迟(1s, 2s, 3s)
  • 超时控制: 根据任务类型配置超时时间(分类30s,编辑60s)

核心类:

class BaseLLMService(ABC):
    """基础LLM服务抽象类"""
    - call_with_retry()  # 带重试机制的API调用
    - _parse_error()     # 错误解析和分类

1.3 Provider层 (Provider Layer)

文件位置: app/services/llm/providers.py

核心职责:

  • 实现不同提供商的API调用逻辑
  • 统一接口抽象,屏蔽提供商差异
  • 提供商特定的错误码转换

支持的提供商:

  1. AliyunProvider (阿里云通义千问)

    • 分类模型: qwen-vl-plus
    • 编辑模型: qwen-image-edit
    • 文本生成: qwen-turbo, qwen-plus, qwen-max
    • API: DashScope SDK
  2. OpenAIProvider

    • 分类模型: gpt-4-vision-preview, gpt-4o
    • 编辑模型: 不支持
    • 文本生成: gpt-4, gpt-3.5-turbo
    • API: OpenAI SDK
  3. ClaudeProvider

    • 分类模型: claude-3-opus, claude-3-sonnet, claude-3-haiku
    • 编辑模型: 不支持
    • 文本生成: claude-3-opus, claude-3-sonnet
    • API: Anthropic SDK
  4. DeepseekProvider

    • 分类模型: 不支持
    • 编辑模型: 不支持
    • 文本生成: deepseek-chat
    • API: 兼容OpenAI格式

核心接口:

class LLMProvider(BaseLLMService):
    """LLM提供商基类"""
    @abstractmethod
    async def _call_classification()  # 分类任务实现
    
    @abstractmethod
    async def _call_image_edit()      # 图像编辑任务实现

1.4 业务层 (Business Layer)

文件位置: app/services/llm/llm_service.py

核心职责:

  • 统一的业务接口入口
  • 自动选择提供商和模型
  • 集成统一缓存架构
  • 响应解析和格式化
  • 任务类型路由(分类/编辑)

核心方法:

class LLMService:
    """统一LLM服务类"""
    
    # 1. 图像分类(内容分类 + 背景颜色)
    async def classify_image(
        image_bytes: bytes,
        prompt: Optional[str] = None,
        model_key: Optional[str] = None,
        max_tokens: Optional[int] = None
    ) -> dict
    # 返回: {category, confidence, description, background_color}
    
    # 2. 颜色分类(只识别背景颜色)
    async def classify_color(
        image_bytes: bytes,
        prompt: Optional[str] = None,
        use_cache: bool = True
    ) -> dict
    # 返回: {success, content: JSON字符串, from_cache}
    # content包含: {background_color, confidence}
    
    # 3. 构图分析(识别构图方式并给出专业点评)
    async def analyze_composition(
        image_bytes: bytes,
        prompt: Optional[str] = None,
        use_cache: bool = True
    ) -> dict
    # 返回: {success, content: JSON字符串, from_cache}
    # content包含: {composition_type, confidence, subject_position, 
    #                visual_balance, spatial_layout, lines_and_shapes,
    #                strengths, suggestions, score, detailed_analysis}
    
    # 4. 图像编辑
    async def edit_image(
        image_bytes: bytes,
        prompt: str,
        edit_type: str = "enhance",
        model_key: Optional[str] = None
    ) -> dict
    # 返回: {success, result_url, from_cache}
    
    # 5. 文本生成
    async def generate_text(
        prompt: str,
        model_key: Optional[str] = None,
        max_tokens: Optional[int] = None
    ) -> dict
    # 返回: {success, content, from_cache}
    
    # 6. 缓存查询
    async def check_cache(
        image_hash: str,
        prompt: str,
        model_key: Optional[str] = None
    ) -> Optional[dict]

业务功能说明:

  • LLMService 是唯一的业务服务层,提供5大核心业务功能:

    1. 图像分类 (classify_image) - 内容分类(9类)+ 背景颜色识别
    2. 颜色分类 (classify_color) - 专门识别照片主色调/背景颜色
    3. 构图分析 (analyze_composition) - 分析照片构图方式,给出专业点评和建议
    4. 图像编辑 (edit_image) - 图像增强、背景替换、风格转换等
    5. 文本生成 (generate_text) - 基于文本提示词生成文本内容
  • API路由层调用 LLMService 的相应方法,它们不是平级关系

  • 所有业务功能都集成统一缓存架构,支持自定义prompt

模型配置管理 (app/services/llm/model_config.py):

  • 任务类型枚举: CLASSIFICATION, IMAGE_EDIT, TEXT_GENERATION
  • 提供商枚举: ALIYUN, OPENAI, CLAUDE, DEEPSEEK
  • 自动模型选择: 根据提供商和任务类型自动选择默认模型
  • 模型验证: 验证模型是否支持指定任务类型

二、统一缓存架构

2.1 缓存设计

文件位置: app/services/unified_llm_cache.py

数据库表: llm_inference_cache_v2

缓存键设计:

  • 主键: (prompt_hash, image_hash) 组合
  • prompt_hash: SHA-256(prompt) - 64字符
  • image_hash: SHA-256(image_bytes) - 64字符

缓存值结构 (JSON格式):

{
  "aliyun:qwen-vl-plus": {
    "result": {
      "category": "pets",
      "confidence": 0.95,
      "description": "...",
      "background_color": null
    },
    "status": "success",
    "hit_count": 225,
    "created_at": "2025-10-10T15:50:16",
    "model_used": "qwen-vl-plus",
    "service_type": "classification"
  },
  "aliyun:qwen-image-edit": {
    "result": "https://...",  // 编辑后的图片URL
    "status": "success",
    "hit_count": 10,
    "created_at": "2025-10-10T16:00:00",
    "model_used": "qwen-image-edit",
    "service_type": "image_edit"
  }
}

核心特性:

  1. 多模型结果集合: 一个图片+提示词组合可以缓存多个模型的结果
  2. 模型键格式: provider:model_idprovider:model_id:version
  3. 命中计数: 自动统计缓存命中次数
  4. 批量查询: 支持批量查询多个图片的缓存结果

核心方法:

class UnifiedLLMCacheService:
    async def get_cached_result(
        prompt: str,
        image_hash: str,
        model_key: Optional[str] = None
    ) -> Optional[dict]
    
    async def batch_get_cached_results(
        prompt: str,
        image_hashes: List[str],
        model_key: Optional[str] = None
    ) -> Dict[str, dict]
    
    async def save_result(
        prompt: str,
        image_hash: str,
        model_key: str,
        result: dict,
        service_type: str
    ) -> bool

2.2 缓存流程

分类服务缓存流程:

1. 客户端请求 → 2. 计算image_hash和prompt_hash
3. 查询缓存 → 4. 命中?返回结果 : 调用LLM
5. 保存结果到缓存 → 6. 返回结果

批量缓存查询流程:

1. 客户端批量请求(image_hashes列表)
2. 批量查询缓存(IN查询)
3. 返回命中结果字典 {image_hash: cached_result}
4. 未命中的图片继续调用LLM

三、业务层图像智能接口

LLMService 提供5大核心业务功能,所有功能都集成统一缓存架构:

3.1 图像分类 (classify_image)

功能: 图像内容分类 + 背景颜色识别

API路径: /api/v1/classify/*

接口列表:

  1. 单个缓存查询

    • POST /api/v1/classify/check-cache
    • 请求: {image_hash: str}
    • 响应: {cached: bool, data: ClassificationData}
  2. 批量缓存查询

    • POST /api/v1/classify/batch-check-cache
    • 请求: {image_hashes: List[str]}
    • 响应: {items: List[CacheItem], cached_count: int}
  3. 单个图片分类

    • POST /api/v1/classify
    • 请求: multipart/form-data (image文件)
    • 响应: {category, confidence, description, background_color}
  4. 批量图片分类

    • POST /api/v1/classify/batch
    • 请求: multipart/form-data (images列表,最多20张)
    • 响应: {results: List[ClassificationData]}

分类类别 (9类):

  • social_activities - 社交活动
  • pets - 宠物萌照
  • single_person - 单人照片
  • foods - 美食记录
  • travel_scenery - 旅行风景
  • screenshot - 手机截图
  • idcard - 证件照
  • qrcode - 二维码
  • other - 其它

技术特性:

  • 支持自定义prompt(可选)
  • 自动缓存管理
  • 二维码快速检测(pyzbar)
  • 本地推理降级(可选)

3.2 颜色分类 (classify_color)

功能: 专门识别照片主色调/背景颜色

方法: llm_service.classify_color()

返回结果:

{
  "success": true,
  "content": "{\"background_color\": \"蓝色\", \"confidence\": 0.95}",
  "from_cache": false
}

技术特性:

  • 使用专门的颜色分类prompt
  • 集成统一缓存架构
  • 支持自定义prompt
  • 返回JSON格式的颜色信息

背景颜色类别 (10种):

  • 橙色、蓝色、红色、绿色、紫色
  • 粉色、黄色、灰色、黑色、白色

3.3 构图分析 (analyze_composition)

功能: 分析照片构图方式,给出专业点评和建议

方法: llm_service.analyze_composition()

返回结果:

{
  "success": true,
  "content": "{\"composition_type\": \"rule_of_thirds\", \"confidence\": 0.92, \"subject_position\": {...}, \"visual_balance\": {...}, \"spatial_layout\": {...}, \"lines_and_shapes\": {...}, \"strengths\": [...], \"suggestions\": [...], \"score\": 8.5, \"detailed_analysis\": \"...\"}",
  "from_cache": false
}

分析维度:

  • composition_type - 构图类型(如:三分法、中心构图、对称构图等)
  • subject_position - 主体位置
  • visual_balance - 视觉平衡
  • spatial_layout - 空间布局
  • lines_and_shapes - 线条与形状
  • strengths - 优点列表
  • suggestions - 改进建议
  • score - 构图评分(0-10分)
  • detailed_analysis - 详细分析文本

技术特性:

  • 使用专门的构图分析prompt
  • 集成统一缓存架构
  • 支持自定义prompt
  • 返回专业的构图分析JSON

3.4 图像编辑 (edit_image)

功能: 图像增强、背景替换、风格转换等

3.2 图像编辑接口

API路径: /api/v2/image-edit/*

接口列表:

  1. 批量图像编辑(异步任务)

    • POST /api/v2/image-edit/batch
    • 请求: multipart/form-data (images列表, prompt, edit_type)
    • 响应: {task_id: str, status: "pending"}
  2. 查询任务状态

    • GET /api/v2/image-edit/task/{task_id}
    • 响应: {status, progress, results: List[ImageEditResult]}

编辑类型 (edit_type):

  • enhance - 图像增强(默认)
  • remove_background - 移除背景
  • change_background - 更换背景
  • style_transfer - 风格转换

技术特性:

  • 异步任务处理(后台处理大量图片)
  • 任务状态跟踪(pending/processing/completed/failed)
  • 七牛云OSS存储(编辑后的图片)
  • 积分扣减(每次编辑扣减积分)
  • 统一缓存集成

业务流程:

1. 客户端提交任务 → 2. 创建异步任务记录
3. 后台处理图片 → 4. 调用LLM编辑接口
5. 上传结果到OSS → 6. 更新任务状态
7. 客户端轮询状态 → 8. 获取结果URL

3.5 文本生成 (generate_text)

功能: 基于文本提示词生成文本内容

方法: llm_service.generate_text()

参数:

  • prompt - 用户提示词(必需)
  • system_prompt - 系统提示词(可选)
  • max_tokens - 最大token数(可选,默认2000)
  • temperature - 温度参数(0-2,默认0.7)

返回结果:

{
  "success": true,
  "content": "生成的文本内容...",
  "from_cache": false
}

技术特性:

  • 默认使用Deepseek模型(如果配置了DEEPSEEK_API_KEY)
  • 支持其他提供商的文本生成模型(OpenAI、Claude、阿里云)
  • 不使用缓存(文本生成每次都是新内容)
  • 支持自定义系统提示词
  • 支持温度参数控制生成随机性

支持的模型:

  • Deepseek: deepseek-chat
  • 阿里云: qwen-turbo, qwen-plus, qwen-max
  • OpenAI: gpt-4, gpt-3.5-turbo
  • Claude: claude-3-opus, claude-3-sonnet

四、位置服务

4.1 架构概览

API路径: /api/v2/location/*

核心文件:

  • app/api/location_v2.py - API路由层
  • app/services/geocoding_client.py - 地理编码客户端

数据库表:

  • global_cities_v2 - 城市数据表(本地缓存)
  • city_name_mapping - 中英文名称映射表
  • api_call_stats - API调用统计表

4.2 业务流程

查询流程:

1. 接收坐标请求
   ↓
2. 本地数据库查询(3km范围内)
   ├─ 命中 → 验证和规范化 → 返回结果
   └─ 未命中 ↓
3. 判断坐标位置(中国/海外)
   ├─ 中国坐标 → 调用高德API
   └─ 海外坐标 → 调用Nominatim API
   ↓
4. API成功?
   ├─ 是 → 验证和规范化 → 保存到本地数据库 → 返回结果
   └─ 否 ↓
5. 降级到v1查询逻辑(全局城市数据库)
   ├─ 成功 → 返回结果
   └─ 失败 → 返回未知位置

4.3 技术栈

外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传

后端框架:

  • FastAPI - 异步Web框架
  • uvicorn - ASGI服务器(用于运行FastAPI应用)
  • aiomysql - 异步MySQL驱动
  • httpx - 异步HTTP客户端

数据库:

  • MySQL 8.0 - 存储城市数据和缓存
  • 连接池管理(pool_size=10, max_overflow=5)

地理计算:

  • Haversine公式 - 计算两点间距离
  • 坐标范围判断 - 判断是否在中国境内

4.4 外部接口

1. 高德地图API (中国坐标)

  • 接口: https://restapi.amap.com/v3/geocode/regeo
  • 用途: 中国境内坐标的逆地理编码
  • 频率限制: 30次/秒(使用Semaphore限制为25次/秒)
  • 返回字段:
    • formatted_address - 格式化地址
    • addressComponent - 地址组件(省市区)
    • adcode - 行政区划代码
    • citycode - 城市代码

2. Nominatim API (海外坐标)

  • 接口: https://www.xintuzhaopian.com/reverse (Cloudflare Worker代理)
  • 用途: 海外坐标的逆地理编码
  • 频率限制: 1次/秒(使用Lock控制)
  • 返回字段:
    • display_name - 显示名称
    • address - 地址组件
    • country_code - 国家代码
    • lat, lon - 坐标

3. GeoNames数据库 (降级查询)

  • 数据源: global_cities_v2
  • 用途: API失败时的降级查询
  • 查询方式: 使用Haversine公式查找最近城市

4.5 数据规范化

验证和规范化函数: validate_and_normalize_location()

规范化规则:

  1. name_en 和 name_zh:

    • 如果 name_zh 有值,使用 name_zh 填充 name_en
    • 如果 name_zh 为空但 name_en 有值,使用 name_en 填充 name_zh
    • 如果两者都为空,设置 name_en="Unknown", name_zh="未知位置"
  2. country_code:

    • 使用实际返回的值
    • 如果未返回,整个位置信息回退到 “unknown”
  3. province:

    • 中国位置: 如果 province 缺失,数据视为错误,回退到 “unknown”
    • 海外位置: 可以使用较低级别的行政区划作为替代(state/region)
  4. 整体验证:

    • 如果 name_enprovincecountry_code 任一无法确定,整个位置视为 “unknown”

未知位置创建: create_unknown_location()

CityInfoV2(
    id=0,
    name_en="Unknown",
    name_zh="未知位置",
    latitude=latitude,
    longitude=longitude,
    country_code="UN",
    province="Unknown",
    data_source="unknown",
    distance_km=0.0
)

4.6 API接口

1. 批量查询最近城市

  • POST /api/v2/location/nearest-cities
  • 请求: {coordinates: List[Coordinate]}
  • 响应: {results: List[CityQueryResult], success_count, failed_count}
  • 限制: 最多500个坐标

2. 统计信息

  • GET /api/v2/location/stats
  • 响应: {total_cities, cities_with_chinese, api_calls_today, ...}

响应模型:

class CityInfoV2:
    id: int
    name_en: str
    name_zh: Optional[str]
    latitude: float
    longitude: float
    country_code: str
    province: Optional[str]
    city: Optional[str]
    district: Optional[str]
    data_source: str  # local/gaode/nominatim/fallback/unknown
    distance_km: float
    api_adcode: Optional[str]
    api_city_id: Optional[str]

4.7 性能优化

并发控制:

  • 高德API: Semaphore(25) - 限制并发请求数
  • Nominatim API: Lock + 时间控制 - 限制请求频率(1次/秒)

批量查询优化:

  • 使用 asyncio.gather() 并行处理多个坐标
  • 本地数据库批量查询(IN查询)
  • 外部API并发调用(受频率限制控制)

缓存策略:

  • 本地数据库缓存(3km范围内)
  • API结果自动保存到本地数据库
  • 减少重复API调用

日志记录:

  • API调用统计(成功/失败)
  • 查询耗时统计
  • 数据来源追踪(local/gaode/nominatim/fallback)

五、技术亮点总结

5.1 架构设计

  • ✅ 三层架构清晰分离(基础服务/Provider/业务层)
  • ✅ 统一的接口抽象,易于扩展新提供商
  • ✅ 统一的错误处理和重试机制

5.2 缓存架构

  • ✅ 多模型结果集合存储
  • ✅ 批量查询优化
  • ✅ 自动命中计数

5.3 位置服务

  • ✅ 智能降级策略(本地DB → 外部API → v1查询)
  • ✅ 数据规范化保证数据质量
  • ✅ 并发控制和频率限制
  • ✅ 中国/海外坐标自动路由

5.4 性能优化

  • ✅ 全异步架构(FastAPI + aiomysql + httpx)
  • ✅ 连接池管理
  • ✅ 批量处理支持
  • ✅ 智能缓存策略

5.5 可扩展性

  • ✅ 易于添加新的大模型提供商
  • ✅ 易于添加新的任务类型
  • ✅ 配置化的模型选择
  • ✅ 统一的缓存接口

六、数据库设计

6.1 大模型缓存表

表名: llm_inference_cache_v2

字段:

  • prompt_hash VARCHAR(64) - 提示词哈希(主键)
  • image_hash VARCHAR(64) - 图片哈希(主键)
  • model_results JSON - 多模型结果集合
  • hit_count INT - 命中次数
  • created_at DATETIME - 创建时间
  • last_hit_at DATETIME - 最后命中时间

索引:

  • PRIMARY KEY (prompt_hash, image_hash)
  • INDEX idx_image_hash (image_hash)
  • INDEX idx_last_hit_at (last_hit_at)

6.2 位置数据表

表名: global_cities_v2

字段:

  • id INT - 主键
  • name_en VARCHAR(255) - 英文名称
  • latitude DECIMAL(10,7) - 纬度
  • longitude DECIMAL(10,7) - 经度
  • country_code VARCHAR(2) - 国家代码
  • province VARCHAR(255) - 省份/州
  • city VARCHAR(255) - 城市
  • district VARCHAR(255) - 区县
  • data_source VARCHAR(50) - 数据来源
  • api_adcode VARCHAR(20) - 高德行政区划代码
  • api_city_id VARCHAR(50) - API城市ID

索引:

  • PRIMARY KEY (id)
  • INDEX idx_location (latitude, longitude)
  • INDEX idx_country (country_code)

表名: city_name_mapping

字段:

  • city_id INT - 城市ID(外键)
  • name_zh VARCHAR(255) - 中文名称
  • name_en VARCHAR(255) - 英文名称

索引:

  • PRIMARY KEY (city_id)
  • INDEX idx_name_zh (name_zh)

七、配置管理

7.1 环境变量配置

大模型配置 (.env):

LLM_PROVIDER=aliyun  # aliyun/openai/claude/deepseek
LLM_MODEL_CLASSIFICATION=  # 可选,默认使用提供商默认模型
LLM_MODEL_IMAGE_EDIT=  # 可选
LLM_TIMEOUT_CLASSIFICATION=30  # 分类任务超时(秒)
LLM_TIMEOUT_IMAGE_EDIT=60  # 编辑任务超时(秒)

位置服务配置 (.env):

GAODE_API_KEY=xxx  # 高德API密钥
GAODE_API_URL=https://restapi.amap.com/v3/geocode/regeo
NOMINATIM_API_URL=https://www.xintuzhaopian.com/reverse
NOMINATIM_RATE_LIMIT=1.0  # Nominatim频率限制(秒)

数据库配置 (.env):

MYSQL_HOST=localhost
MYSQL_PORT=3306
MYSQL_USER=root
MYSQL_DATABASE=image_classifier
MYSQL_POOL_SIZE=10
MYSQL_MAX_OVERFLOW=5

7.2 密钥管理

敏感信息 (.env.secrets):

  • LLM_API_KEY - 大模型API密钥
  • MYSQL_PASSWORD - 数据库密码
  • GAODE_API_KEY - 高德API密钥
  • DEEPSEEK_API_KEY - Deepseek API密钥(如使用)

八、总结

V2接口技术方案实现了:

  1. 清晰的分层架构 - 基础服务层、Provider层、业务层职责明确
  2. 统一的缓存架构 - 支持多模型结果集合,批量查询优化
  3. 完整的图像智能接口 - 分类和编辑功能,支持自定义prompt
  4. 智能的位置服务 - 多级降级策略,数据规范化,并发控制
  5. 高性能和可扩展性 - 全异步架构,连接池管理,易于扩展

该方案为图像智能处理和位置服务提供了稳定、高效、可扩展的技术基础。

Logo

有“AI”的1024 = 2048,欢迎大家加入2048 AI社区

更多推荐