当前位置: 首页 > news >正文

如何快速画UML

以前毕业设计画 UML 图累的要死。。。

最近在学习一个项目,做数据模型的时候使用 AI 绘制 UML 图来理清楚数据模型之间的关系。以下是步骤

1、代码

示例如下,代码来自于datawhale的 hello-agents 项目

"""数据模型定义"""from typing import List, Optional, Union
from pydantic import BaseModel, Field, field_validator
from datetime import date# ============ 请求模型 ============class TripRequest(BaseModel):"""旅行规划请求"""city: str = Field(..., description="目的地城市", example="北京")start_date: str = Field(..., description="开始日期 YYYY-MM-DD", example="2025-06-01")end_date: str = Field(..., description="结束日期 YYYY-MM-DD", example="2025-06-03")travel_days: int = Field(..., description="旅行天数", ge=1, le=30, example=3)transportation: str = Field(..., description="交通方式", example="公共交通")accommodation: str = Field(..., description="住宿偏好", example="经济型酒店")preferences: List[str] = Field(default=[], description="旅行偏好标签", example=["历史文化", "美食"])free_text_input: Optional[str] = Field(default="", description="额外要求", example="希望多安排一些博物馆")class Config:json_schema_extra = {"example": {"city": "北京","start_date": "2025-06-01","end_date": "2025-06-03","travel_days": 3,"transportation": "公共交通","accommodation": "经济型酒店","preferences": ["历史文化", "美食"],"free_text_input": "希望多安排一些博物馆"}}class POISearchRequest(BaseModel):"""POI搜索请求"""keywords: str = Field(..., description="搜索关键词", example="故宫")city: str = Field(..., description="城市", example="北京")citylimit: bool = Field(default=True, description="是否限制在城市范围内")class RouteRequest(BaseModel):"""路线规划请求"""origin_address: str = Field(..., description="起点地址", example="北京市朝阳区阜通东大街6号")destination_address: str = Field(..., description="终点地址", example="北京市海淀区上地十街10号")origin_city: Optional[str] = Field(default=None, description="起点城市")destination_city: Optional[str] = Field(default=None, description="终点城市")route_type: str = Field(default="walking", description="路线类型: walking/driving/transit")# ============ 响应模型 ============class Location(BaseModel):"""地理位置"""longitude: float = Field(..., description="经度")latitude: float = Field(..., description="纬度")class Attraction(BaseModel):"""景点信息"""name: str = Field(..., description="景点名称")address: str = Field(..., description="地址")location: Location = Field(..., description="经纬度坐标")visit_duration: int = Field(..., description="建议游览时间(分钟)",gt=0)description: str = Field(..., description="景点描述")category: Optional[str] = Field(default="景点", description="景点类别")rating: Optional[float] = Field(default=None, description="评分")photos: Optional[List[str]] = Field(default_factory=list, description="景点图片URL列表")poi_id: Optional[str] = Field(default="", description="POI ID")image_url: Optional[str] = Field(default=None, description="图片URL")ticket_price: int = Field(default=0, description="门票价格(元)")class Meal(BaseModel):"""餐饮信息"""type: str = Field(..., description="餐饮类型: breakfast/lunch/dinner/snack")name: str = Field(..., description="餐饮名称")address: Optional[str] = Field(default=None, description="地址")location: Optional[Location] = Field(default=None, description="经纬度坐标")description: Optional[str] = Field(default=None, description="描述")estimated_cost: int = Field(default=0, description="预估费用(元)")class Hotel(BaseModel):"""酒店信息"""name: str = Field(..., description="酒店名称")address: str = Field(default="", description="酒店地址")location: Optional[Location] = Field(default=None, description="酒店位置")price_range: str = Field(default="", description="价格范围")rating: str = Field(default="", description="评分")distance: str = Field(default="", description="距离景点距离")type: str = Field(default="", description="酒店类型")estimated_cost: int = Field(default=0, description="预估费用(元/晚)")class DayPlan(BaseModel):"""单日行程"""date: str = Field(..., description="日期 YYYY-MM-DD")day_index: int = Field(..., description="第几天(从0开始)")description: str = Field(..., description="当日行程描述")transportation: str = Field(..., description="交通方式")accommodation: str = Field(..., description="住宿")hotel: Optional[Hotel] = Field(default=None, description="推荐酒店")attractions: List[Attraction] = Field(default=[], description="景点列表")meals: List[Meal] = Field(default=[], description="餐饮列表")class WeatherInfo(BaseModel):"""天气信息"""date: str = Field(..., description="日期 YYYY-MM-DD")day_weather: str = Field(default="", description="白天天气")night_weather: str = Field(default="", description="夜间天气")day_temp: Union[int, str] = Field(default=0, description="白天温度")night_temp: Union[int, str] = Field(default=0, description="夜间温度")wind_direction: str = Field(default="", description="风向")wind_power: str = Field(default="", description="风力")@field_validator('day_temp', 'night_temp', mode='before')@classmethoddef parse_temperature(cls, v):"""解析温度,移除°C等单位"""if isinstance(v, str):# 移除°C, ℃等单位符号v = v.replace('°C', '').replace('℃', '').replace('°', '').strip()try:return int(v)except ValueError:return 0return vclass Budget(BaseModel):"""预算信息"""total_attractions: int = Field(default=0, description="景点门票总费用")total_hotels: int = Field(default=0, description="酒店总费用")total_meals: int = Field(default=0, description="餐饮总费用")total_transportation: int = Field(default=0, description="交通总费用")total: int = Field(default=0, description="总费用")class TripPlan(BaseModel):"""旅行计划"""city: str = Field(..., description="目的地城市")start_date: str = Field(..., description="开始日期")end_date: str = Field(..., description="结束日期")days: List[DayPlan] = Field(..., description="每日行程")weather_info: List[WeatherInfo] = Field(default=[], description="天气信息")overall_suggestions: str = Field(..., description="总体建议")budget: Optional[Budget] = Field(default=None, description="预算信息")class TripPlanResponse(BaseModel):"""旅行计划响应"""success: bool = Field(..., description="是否成功")message: str = Field(default="", description="消息")data: Optional[TripPlan] = Field(default=None, description="旅行计划数据")class POIInfo(BaseModel):"""POI信息"""id: str = Field(..., description="POI ID")name: str = Field(..., description="名称")type: str = Field(..., description="类型")address: str = Field(..., description="地址")location: Location = Field(..., description="经纬度坐标")tel: Optional[str] = Field(default=None, description="电话")class POISearchResponse(BaseModel):"""POI搜索响应"""success: bool = Field(..., description="是否成功")message: str = Field(default="", description="消息")data: List[POIInfo] = Field(default=[], description="POI列表")class RouteInfo(BaseModel):"""路线信息"""distance: float = Field(..., description="距离(米)")duration: int = Field(..., description="时间(秒)")route_type: str = Field(..., description="路线类型")description: str = Field(..., description="路线描述")class RouteResponse(BaseModel):"""路线规划响应"""success: bool = Field(..., description="是否成功")message: str = Field(default="", description="消息")data: Optional[RouteInfo] = Field(default=None, description="路线信息")class WeatherResponse(BaseModel):"""天气查询响应"""success: bool = Field(..., description="是否成功")message: str = Field(default="", description="消息")data: List[WeatherInfo] = Field(default=[], description="天气信息")# ============ 错误响应 ============class ErrorResponse(BaseModel):"""错误响应"""success: bool = Field(default=False, description="是否成功")message: str = Field(..., description="错误消息")error_code: Optional[str] = Field(default=None, description="错误代码")

2、 输入大模型得到PlantUML 格式

把第一步的源代码输入到大模型中,让他将该数据模型转换成 PlantUML 格式,得到以下代码:

@startuml
' 设置样式:隐藏方法,只显示属性,让图表更清爽
hide methods
skinparam classAttributeIconSize 0
skinparam monochrome true' ============ 基础/通用模型 ============
class Location {+longitude: float+latitude: float
}' ============ 请求模型 ============
class TripRequest {+city: str+start_date: str+end_date: str+travel_days: int+transportation: str+accommodation: str+preferences: List[str]+free_text_input: Optional[str]
}class POISearchRequest {+keywords: str+city: str+citylimit: bool
}class RouteRequest {+origin_address: str+destination_address: str+origin_city: Optional[str]+destination_city: Optional[str]+route_type: str
}' ============ 业务实体模型 ============
class Attraction {+name: str+address: str+location: Location+visit_duration: int+description: str+category: Optional[str]+rating: Optional[float]+photos: Optional[List[str]]+poi_id: Optional[str]+image_url: Optional[str]+ticket_price: int
}class Meal {+type: str+name: str+address: Optional[str]+location: Optional[Location]+description: Optional[str]+estimated_cost: int
}class Hotel {+name: str+address: str+location: Optional[Location]+price_range: str+rating: str+distance: str+type: str+estimated_cost: int
}class DayPlan {+date: str+day_index: int+description: str+transportation: str+accommodation: str+hotel: Optional[Hotel]+attractions: List[Attraction]+meals: List[Meal]
}class WeatherInfo {+date: str+day_weather: str+night_weather: str+day_temp: Union[int, str]+night_temp: Union[int, str]+wind_direction: str+wind_power: str
}class Budget {+total_attractions: int+total_hotels: int+total_meals: int+total_transportation: int+total: int
}' ============ 核心响应模型 ============
class TripPlan {+city: str+start_date: str+end_date: str+days: List[DayPlan]+weather_info: List[WeatherInfo]+overall_suggestions: str+budget: Optional[Budget]
}class TripPlanResponse {+success: bool+message: str+data: Optional[TripPlan]
}' ============ POI 相关模型 ============
class POIInfo {+id: str+name: str+type: str+address: str+location: Location+tel: Optional[str]
}class POISearchResponse {+success: bool+message: str+data: List[POIInfo]
}' ============ 路线相关模型 ============
class RouteInfo {+distance: float+duration: int+route_type: str+description: str
}class RouteResponse {+success: bool+message: str+data: Optional[RouteInfo]
}' ============ 天气响应模型 ============
class WeatherResponse {+success: bool+message: str+data: List[WeatherInfo]
}' ============ 错误模型 ============
class ErrorResponse {+success: bool+message: str+error_code: Optional[str]
}' ============ 关系定义 ============' 核心行程组合关系
TripPlan "1" o-- "1..*" DayPlan : contains
TripPlan "1" o-- "0..1" Budget : contains
TripPlan "1" o-- "0..*" WeatherInfo : includes' 每日行程组合关系
DayPlan "1" o-- "0..1" Hotel : recommends
DayPlan "1" o-- "0..*" Attraction : visits
DayPlan "1" o-- "0..*" Meal : eats' 实体与地理位置的关系
Attraction "1" --> "1" Location : has
Meal "1" --> "0..1" Location : has
Hotel "1" --> "0..1" Location : has
POIInfo "1" --> "1" Location : has' 响应包装关系
TripPlanResponse "1" o-- "0..1" TripPlan : data
POISearchResponse "1" o-- "0..*" POIInfo : data
RouteResponse "1" o-- "0..1" RouteInfo : data
WeatherResponse "1" o-- "0..*" WeatherInfo : data@enduml

3、绘图

将得到的PlantUML 语言复制到 drawio 绘图软件里,立马出图

image

然后就可以得到自己的 UML 图:

image

http://www.jsqmd.com/news/734298/

相关文章:

  • 告别截图OCR!用AHK脚本一键抓取通达信股票代码(附WinSpy工具使用心得)
  • BuilderBot:基于Node.js的跨平台对话机器人框架构建指南
  • 构建可靠网络连接:从WireGuard到Tailscale的现代组网实践指南
  • 高效掌握Google OR-Tools:从基础到实战的完整优化指南
  • Unity角色残影效果:用SkinnedMeshRenderer.BakeMesh实现,附完整C#代码与性能优化建议
  • 银河麒麟V10上,麒麟天御V4.0.0客户端三种安装方式保姆级实测(含软件源配置避坑)
  • Day11-Java
  • 冒险岛WZ文件终极解析工具:3个步骤快速掌握WzComparerR2完整使用指南
  • 如何永久保存你的微信记忆:WeChatMsg完整指南
  • OpenClaw Mission Control:构建低成本、高可用的多智能体自动化系统
  • 如何在Photoshop中直接使用AI绘画:Comfy-Photoshop-SD插件完全指南
  • 保姆级教程:用TensorFlow 1.15复现CNN+LSTM睡眠分期模型(附Sleep-EDF/MASS数据集处理)
  • 别再乱装了!AutoDock4、Vina1.2.5和PyMOL2.6的黄金组合安装避坑指南(解决闪退/报错)
  • 保姆级教程:在Ubuntu 22.04上搞定JSBSim与AirSim的无人机仿真联调(附常见错误修复)
  • YOLOv8姿态估计实战:除了跌倒,还能用关键点做什么?(附5个创意项目思路)
  • 为OpenClaw智能体工作流配置Taotoken统一API入口
  • 多智能体协作架构搜索与优化技术解析
  • Java集成Dify AI:dify-java-client架构解析与生产实践指南
  • 从野外炮点到最终成像:一条地震道数据在SEG-Y文件里的完整“旅程”与关键字段解读
  • DLSS Swapper:游戏性能优化的智能管家,三步解决DLSS版本管理难题
  • 强化学习在机器人灵巧操作中的挑战与解决方案
  • MoE架构在多语言大模型K-EXAONE中的实践与优化
  • SANA-Video:高效视频生成技术解析与应用
  • 用LightGBM搞定电力负荷预测:从数据清洗到模型调参的完整Python实战
  • Allegro 17.4 约束管理器实战:从单网络到差分对的完整设置流程(附避坑点)
  • Cover65蓝牙双模PCB到手后别急着插轴!这10个新手必看的组装与测试步骤(附防烧板指南)
  • Kylin Cube构建效率翻倍指南:全量 vs 增量,你的业务场景到底该选哪个?
  • GA4063频谱分析仪性能评测与应用指南
  • SwiftUI + AVFoundation实战:5步封装一个可复用的视频播放控制组件
  • 2026成都设计工作室诚信排行榜TOP,成都设计工作推荐严选本地靠谱团队 - 推荐官