# LLMSEOTagMeta **Repository Path**: chenjim/LLM-SEO-Tag-Meta ## Basic Information - **Project Name**: LLMSEOTagMeta - **Description**: typecho 插件:每发布一篇文章,插件自动调 LLM 生成一段 SEO 描述。自动给每篇文章打标签。评估每篇文章得质量。 - **Primary Language**: Unknown - **License**: Not specified - **Default Branch**: main - **Homepage**: None - **GVP Project**: No ## Statistics - **Stars**: 0 - **Forks**: 0 - **Created**: 2026-07-08 - **Last Updated**: 2026-07-22 ## Categories & Tags **Categories**: Uncategorized **Tags**: None ## README # LLM SEO Tag Meta — 用 AI 给你的 Typecho 博客做 SEO > 本文首发地址 写博客这几年,一直有个头疼的问题:**标签**。 刚开博客那会儿,每篇文章都认真打标签,写描述。时间一长就懈怠了——发布按钮一点,标题扔上去就完事,哪还记得补 description 和标签。日积月累,文章几百篇,标签没几个,搜索结果页的描述也常年空缺。 试过手动整理,坚持了两天就放弃了。几百篇文章,一篇篇翻、写标签、写描述,这活不是人干的。 所以有了这个插件。当前版本支持:面板按文章质量、有无标签、有无Meta筛选文章,自动同步文章状态、批量TAG/Meta增强 SEO/GEO。 市面上 Typecho 的 SEO 插件不少,但基本只做静态优化——改改 title、加加 keywords、生成个 sitemap。**没有用 LLM 做内容理解的**。而标签和描述恰恰是最需要语义理解的事:读懂文章才能写出好描述,理解内容才能推荐准标签。这事 LLM 最擅长,所以把两件事合并到一个插件里。 ## 它能干什么 **自动生成 SEO 描述。** 每发布一篇文章,插件自动调 LLM 生成一段 SEO 描述(下限 100 字,引导 100-180 字),直接写进文章的自定义字段。前台自动输出到 ``,搜索结果展示的时候就有内容了。也支持手动触发——编辑页有个「AI 生成描述」按钮,点一下就行。 **标签补充 + 质量评估。** 插件扫描你所有已发布的文章,对每篇读标题和正文,看你现有的标签库,推荐 4-7 个标签(优先复用已有标签,必要时创建新标签),给当前标签质量打分:high / medium / low,顺手把关系写进 `typecho_relationships`。后台有个批量面板,进度条、实时日志、暂停继续、失败重试都有。几百篇文章跑一轮也就几分钟。 ## 怎么用 **安装。** 把仓库放到 Typecho 插件目录: ```bash cd data/usr/plugins/ git clone https://gitee.com/chenjim/LLM-SEO-Tag-Meta LLMSEOTagMeta ``` 然后进 Typecho 后台 → 插件 → 启用,配置 API Key 即可。 **配置。** 打开设置页面,配好 LLM API(默认指向 DeepSeek,兼容任意 OpenAI 接口): - **API Endpoint** — 你用的模型服务地址 - **API Key** — 从服务商获取的密钥 - **Model** — 模型名 建议用 `deepseek-v4-flash` 或同类快速模型,单次生成耗时基本在 1-3 秒内。默认发布时自动生成描述+异步子进程模式,不阻塞发布流程。想改成手动也行,在设置里选一下。 **批量处理。** 后台菜单「LLM SEO Tag Meta」进面板,统一文章列表页面: 1. **筛选 + 批量操作** — 按标签/Meta/质量 筛选文章,勾选后批量生成标签或描述 2. **单篇操作** — 每行有生成标签和 Meta 的独立按钮,质量 badge 直接显示在标题旁 3. **自动同步 + 配置校验** — 进入面板自动同步文章状态,顶部 info bar 一键校验 API 配置 **截图。** ![后台面板](https://blog-chenjim.oss-cn-shanghai.aliyuncs.com/2026/202607112308934.png-blog) *后台面板:文章列表、筛选、批量操作* ![设置页](https://blog-chenjim.oss-cn-shanghai.aliyuncs.com/2026/202607112309211.png-blog) *设置页:API 配置与 Meta/标签参数* **测试。** ```bash docker compose exec -T typecho php /app/usr/plugins/LLMSEOTagMeta/test_plugin.php ``` 45 个集成测试用例覆盖语法、表单、清洗、JSON 解析、parseFlatTags、BLOCKLIST、数据库操作、插件激活。 ## 设计与实现 **目录结构。** ``` LLMSEOTagMeta/ ├── Plugin.php # 插件入口:激活、配置、Hook 注册、Action 注册 ├── Action.php # Action 路由:统一处理 ?do=xxx 请求(10 个端点) ├── panel.php # 后台单页面板:info bar + 统计 + 筛选 + 文章列表 + 批量操作 + 分页 ├── worker.php # 异步子进程入口(CLI,可选) ├── lib/ │ ├── LLMClient.php # OpenAI 兼容 Chat API 封装(cURL + 重试) │ ├── ContentCleaner.php # HTML/Markdown 清洗 + 多字节截断 │ ├── MetaDescService.php # Meta 描述生成、字段读写、前台输出 │ ├── TagService.php # 标签推荐、标签创建、关系写入、质量评估 │ ├── TaskService.php # 批量任务状态、统计、断点续跑 │ └── JsonHelper.php # LLM JSON 解析辅助 └── assets/ ├── admin.js # 后台 AJAX、分页、批量队列、质量 badge └── admin.css # 单页布局样式 ``` `Plugin.php` 只做注册和分发,不承载复杂业务。`MetaDescService` 和 `TagService` 分别处理两个业务域,`LLMClient`/`ContentCleaner` 被两者共享。 **数据库。** Meta 描述存储在 `typecho_fields`,字段名 `seo_description_llm`;标签使用 Typecho 原生 `typecho_metas` + `typecho_relationships`;任务状态存在自定义表 `typecho_seo_tag_meta_status`,`tag_status` 和 `meta_status` 两列分别跟踪,枚举值 `pending/processing/done/skipped/failed`。所有 SQL 兼容 SQLite / MySQL。 **Hook 与 Action。** | Hook | 触发 | 用途 | |---|---|---| | `finishPublish` | 文章发布 | 自动生成 Meta 描述(auto 模式) | | `write-post.php:bottom` | 编辑页 | 注入"AI 生成描述"按钮 | | `admin/header.php` (filter) | 后台所有页 | 注入 CSS/JS | | `headerOptions` (filter) | 前台页面 | 输出 `` | | `getDefaultFieldItems` (filter) | 编辑页 | 注入 `seo_description_llm` 字段 | 发布时自动生成条件:旧状态非 `publish`、新状态为 `publish`、`meta_mode=auto`、字段不存在、正文非空、API 配置有效。不阻塞发布流程。 Action 统一端点 `/action/llm-seo-tag-meta`: | do | 说明 | 权限 | |---|---|---| | `generate_meta` | 单篇生成 Meta 描述 | editor+ | | `generate_tags` | 单篇生成标签 | administrator | | `batch_generate_meta` | 批量生成 Meta | administrator | | `enhance_tags` | 批量增强标签 | administrator | | `stats` | 获取统计 | administrator | | `sync_posts` | 同步文章到状态表 | administrator | | `reset_tag_status` | 重置标签状态 | administrator | | `reset_meta_status` | 重置 Meta 状态 | administrator | | `validate_config` | 校验 API 配置 | administrator | | `get_meta_posts` | 文章列表分页查询(支持 tag/meta/quality 筛选) | administrator | **核心模块。** *LLMClient* 是统一的 OpenAI 兼容 Chat API 封装,核心方法 `chat(array $messages, array $options): array`。响应兼容 `choices[0].message.content`、`choices[0].text`、`data.content`,并将 `reasoning_content` 作为 content 为空的回退。连接超时默认 5 秒,请求总超时默认 120 秒;HTTP 429 / 500 / 502 / 503 / 504 可重试,400 / 401 / 403 不重试,重试间隔 1 秒。应用层重试由各 Service 控制。 *MetaDescService* 生成流程:校验 → 清洗正文 → 截取 → 渲染 Prompt → 调 LLM → 后处理(去前缀、去 reasoning 前缀)。`meta_retry_count + 1` 次尝试,LLM 返回为空、后处理为空或字数低于 `meta_min_chars`(默认 100 字)时自动重试。下限 100 字硬校验+重试,上限由 Prompt 软引导(100-180 字),不硬截断。 *TagService* 增强流程:校验 → 清洗 → 截取 → 加载现有标签库 → 渲染 Prompt → 调 LLM → JSON 解析 → BLOCKLIST 过滤 → 创建/复用标签 → 清空旧关系 → 写入新关系 → 更新标签计数 → 更新状态表。`tag_range` 控制标签数量(默认 4-7),代码层按上限硬截断。slug 生成:去空格 → 转小写 → 非字母数字中文替换为 `-` → 合并连续 `-`。常量 `BLOCKLIST_TAGS` 剔除描述性泛词,中文如教程/指南/经验等,英文如 tutorial/guide/api/data 等。`parseFlatTags` 兜底:LLM 返回逗号/换行分隔的文本列表时自动解析为标签数组,不报错。 **版本兼容。** 支持 Typecho 1.2+。本插件使用 namespace 风格钩子注册 `\Typecho\Plugin::factory('Widget\\Contents\\Post\\Edit')`;Typecho 1.3 无 `leftJoin()`,改用 `join()` + `Db::LEFT_JOIN`;`PluginInterface` 接口名在 1.3 为 `\Typecho\Plugin\PluginInterface`;`admin/header` 钩子在 1.3 变为 filter 类型;`addPanel()` 索引推荐用 `1`(控制台下)。 **安全。** 所有 POST 请求校验 Typecho CSRF token,缺失或无效返回 403;editor 可单篇生成 Meta,administrator 可批量/配置/标签操作;administrator 可操作全部文章,editor 仅限自己的文章;日志不记录 API Key、完整正文、完整 Prompt;不依赖 `Referer` 或 `X-Requested-With` 替代 token;停用插件不会删除状态表、自定义字段、标签关系,回滚后数据可直接复用。 **Prompt 模板。** Prompt 内嵌在 `Plugin.php::defaultMetaPrompt()` 和 `defaultTagPrompt()` 中,不暴露给用户编辑。Meta 描述 Prompt 使用 `{title}`、`{content}`、`{tags}` 变量;标签增强使用 `{title}`、`{content}`、`{existing_tags}`、`{tag_range}`。两者均发送 `system message`:直接输出 JSON/文字,不做任何推理分析。 ## 技术栈 - Typecho 1.2+ / PHP 8.2+ - SQLite(兼容 MySQL) - cURL 直调 OpenAI 兼容 API,无多余依赖 - 异步子进程可选,`exec()` 启动独立 PHP 进程,不阻塞 Web 请求