# plog_gen **Repository Path**: itbj00/plog_gen ## Basic Information - **Project Name**: plog_gen - **Description**: 把手机拍摄的一次旅行的全部照片,导入到电脑(支持jpg / png / webp/heic 等多种格式,含子目录),放进一个文件夹。之后导入到本工具plog gen,其会根据照片中的 EXIF 信息整理行程、分类、调用AI接口写描述,最终渲染成一篇精美的 HTML 手帐或者长图,方便发布到博客或者社交媒体。 - **Primary Language**: Unknown - **License**: Apache-2.0 - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 1 - **Forks**: 1 - **Created**: 2026-10-10 - **Last Updated**: 2026-10-10 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # Plog Gen 项目文档 把手机拍摄的一次旅行的全部照片,导入到电脑(支持jpg / png / webp/heic 等多种格式,含子目录),放进一个文件夹。之后导入到本工具plog gen,其会根据照片中的 EXIF 信息整理行程、分类、调用AI接口写描述,最终渲染成一篇精美的 HTML 手帐或者长图,方便发布到博客或者社交媒体。 **设计原则:** 批量读取照片中的EXIF信息(时间、坐标、相机参数);AI大模型只做看图描述和文案创作。**原始文件夹中的照片不会被更改!** **注意:** 1. 本工具使用依赖手机拍摄的照片中带有经纬度坐标信息、时间信息,目前大部分手机均已支持其功能 2. 高德AMAP的API需要自行配置,用于根据照片EXIF里面的经纬度逆编码(坐标 → 地名),在 `.env` 里面配置 3. AI接口API需要自行配置,用于识别照片并生成描述,在`.env`里面配置 --- ## 项目背景 旅行结束面对几百张照片,整理行程、写文案、排版很耗时,有时候自己都不知道这张照片是**啥时候**、**在哪里**拍摄的。本工具把这条**工作流自动化**,同时每个节点都可以人工进行审核和调整: ``` → 导入 → 解析 EXIF(时间 / GPS / 相机参数) → 清洗(重复 / 过糊 / 过小) → 聚类(按照时间或者位置进行分类,包括逆地理编码) → 精选(选出代表图) → 描述(AI识图并描述) → 渲染生成手帐 ``` ## 快速开始 ```bash cd plog_gen pip install -r requirements.txt copy .env.example .env ``` 在 `.env` 中填入 `AI_API_KEY`(国内景点更准可再填 `AMAP_KEY`),然后: ```bash python run.py ``` ``` 浏览器打开 http://127.0.0.1:8000 ⚠️ app 目录下的 config.py 第 49 行代码。 ``` 未配置 `AI_API_Key` 也能运行,只是【描述】界面会生成不含文案的骨架 JSON 供手工填写。 --- ## 目录结构 ```bash plog_gen/ ├── run.py # 启动入口:加载配置并启动 uvicorn(默认 127.0.0.1:8765) ├── requirements.txt # Python 依赖清单 ├── .env.example # 环境变量模板(AI Key、高德 Key) ├── .gitignore ├── README.md # 简要说明 │ ├── app/ # 后端(FastAPI) │ ├── __init__.py │ ├── config.py # 配置:读取 .env,定义数据目录 data/projects、端口等 │ ├── models.py # Pydantic 数据模型:Photo / Cluster / Project / PlogDoc / JobStatus │ ├── store.py # 项目进度实时保存到本地,用于关闭后读取 │ ├── main.py # FastAPI 应用:全部后台 API │ │ │ │ │ ├── pipeline/ # 具体工作流相关 │ │ ├── __init__.py │ │ ├── exif.py # 递归扫描图片、解析 EXIF:拍摄时间/GPS/拍摄设备/镜头/ISO/光圈/快门/焦距 │ │ │ │ │ ├── clean.py # 清洗:aHash 感知哈希查重、拉普拉斯方差判模糊,清除重复、低质量照片 │ │ │ │ │ ├── cluster.py # 聚类:按时间排序后用「时间间隔 + 球面距离(haversine)」切分, │ │ │ │ │ ├── geocode.py # 逆地理编码:优先高德(配 AMAP_KEY),否则 Nominatim; │ │ │ │ │ └── heroes.py # 精选代表图 │ │ │ ├── agent/ # AI大模型相关 │ │ ├── __init__.py │ │ └── openai.py # DeepSeek 集成: │ │ # - describe_cluster_photos:Vision 模型看代表图,输出场景/氛围 JSON │ │ # - skeleton_plog:无 Key 时的骨架 JSON │ │ # - generate_plog:文本模型 + function calling(submit_plog) │ │ # 产出 { trip_summary, daily_plog } 叙事 JSON,含兜底回填 │ │ │ └── render/ # 渲染层 │ ├── __init__.py │ ├── html.py # 用 Jinja2 渲染并写出 output/plog.html │ │ │ ├── cards.py # 基于clusters分类生成长图 │ │ │ └── plog.html # 手帐模板:杂志风封面 + 每日章节(标题/文案/亮点标签/照片墙/Tips) │ ├── static/ # 前端相关 │ ├── index.html # 页面骨架:顶部品牌、步骤导航条、主区域、进度条、Toast、script嵌入app.js │ ├── styles.css # 全部样式(暖纸色系、卡片、网格、弹窗等) │ └── app.js # 前端逻辑 │ └── data/ # 本地项目缓存相关,运行时生成(已 gitignore) ├── geocode_cache.json # 逆地理缓存 └── projects// # 每个项目的工作目录 ├── project.json # 项目全量状态(照片、聚类、叙事 JSON、当前步骤) ├── thumbs/ # 缩略图(网页显示) ├── clusters/ # 每个聚类一个代表图文件夹(可直接在资源管理器里增删) └── output/ # 渲染产物:plog.html + images/ ``` ## 配置项(`.env`) | 变量 | 默认 | 说明 | | ----------------- | ------------------------------ | ------------------------------------------------------------ | | `AI_API_KEY` | 空 | 需要AI描述就需要填写 | | `AI_BASE_URL` | `https://api.deepseek.com` | 默认使用deepseek API,因为性价比,[Deepseek API平台](https://api.deepseek.com) | | `AI_TEXT_MODEL` | `deepseek-v4-flash` | 叙事模型 | | `AI_VISION_MODEL` | `deepseek-v4-flash-vision-exp` | 看图模型 | | `AMAP_KEY` | 空 | 高德 Web 服务 Key,国内逆地理更准,[高德开放平台](https://lbs.amap.com/) | | `HOST` / `PORT` | `127.0.0.1` / `8765` | 服务监听地址 |