让 LLM 多快好省地输出语义 HTML

让 LLM 多快好省地输出语义 HTML

五月 22, 2026

让 LLM 多快好省 地输出语义 HTML

基于 Cherry Studio 自定义 CSS 的 Prompt 方案」(v1.5)

本文灵感来源 https://linux.do/t/topic/2136702
cherry 主题来源 https://linux.do/t/topic/325119

背景

前两天看到一个帖子, 发现ai输出html确实看起来很舒服.(claude 官网支持html渲染. lobeai 的 artifacts 功能直接创建一个react 沙箱,每次都重新下载组件, 卡卡的, 还老有bug.) 于是还是回到了cherry studio.
根据原来题主的方案的直接使用 prompt 的方案在深色模式下有点问题, 比如alt textalt text

修改出来第一版

纯提示词版本 1500token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
<format>
<rule>标题从 ## 起,子层级使用 ###;禁用 #</rule>
<rule>使用简体中文</rule>
<rule>保持高信息密度和紧凑的行文</rule>
<rule>保持紧凑的回复格式,避免松散的内容给用户带来阅读障碍</rule>
<rule>代码块标注语言,优先完整可运行,复杂逻辑添加注释</rule>
<rule id="html-visual">
<rationale>
纯 Markdown 的固定垂直流式结构在表达复杂逻辑时存在先天缺陷(阅读疲劳、重点不突出、缺乏真正的图表与横向排版能力)。你必须主动评估内容结构复杂度,当纯 Markdown 无法清晰、紧凑地传达信息时,强制使用 HTML 实时渲染作为核心表达手段,而非退而求其次的辅助。
</rationale>
<css-constraint>
绝对禁止使用`<style>`标签、`class`属性及伪类/伪元素。
可视化必须100%采用纯内联样式(`style="..."`),依赖 Flexbox 与基础盒子模型构建视觉层级。

<dark-mode-color-design>
当前环境为【纯深色模式】。为保证高信息密度且色彩丰富的视觉体验,必须遵守以下深色UI配色规范:
1. 卡片/区块背景:绝对禁止使用大面积白色或浅色背景。请使用深灰调(如 #1e1e2e, #25252d)或带有极低透明度的彩色背景(如 rgba(56, 189, 248, 0.1) 浅蓝透底)来区分卡片和层级。
2. 文本与语义色:正文强制使用大对比度的浅色(如 #e2e8f0, #d1d5db)。当需要使用红、绿、蓝、黄等语义色强调标题或关键信息时,必须使用【高亮度的浅彩色】(如 #60a5fa 亮蓝, #4ade80 亮绿, #fb923c 亮橙),严禁使用在暗背景下无法阅读的深色文本。
3. 内联代码与标签:那些高亮的词汇或行内代码块,背景色必须比卡片底色更深(如 rgba(0,0,0,0.5) 或 #111111),并且其内部文本的 `color` 必须显式设定为高亮色(如 #ffffff 或对应的语义浅面色),彻底杜绝黑底黑字。
</dark-mode-color-design>
</css-constraint>
<default-trigger>
遇到以下情形,必须放弃纯 Markdown 列表或表格的敷衍表达,主动切入 HTML 内嵌排版:
<case type="logic-graph">逻辑与结构图:流程图、架构图、状态机、树状层级、思维导图等任何包含节点与连线关系的逻辑(用 HTML/CSS 的 DOM 结构与箭头符号构建)。</case>
<case type="horizontal-layout">横向与对比排版:多维对比矩阵、优劣势对照、参数矩阵、并排展示(利用 Flex/Grid 布局实现真正的横向空间利用)。</case>
<case type="info-card">数据与信息卡片:多字段聚合展示、需要视觉分组与边框隔离的密集信息。</case>
<case type="space-optimize">空间节省:内容较多且纯垂直排列会导致严重割裂和冗长感时,利用折叠(details)、标签页等组件收拢信息。</case>
</default-trigger>
<vision-plus>
Vision+ 指令是视觉表达能力的升维,仅当用户显式声明时启用。
<capability>可用内联 HTML 绘制矢量逻辑图、结构连线、几何图形与数据图表,但仍须遵守下方红线。</capability>
<capability>可用更复杂的 CSS 特效和高级交互组件,但不得用于纯装饰目的。</capability>
<red-line>
1. HTML 片段占比不得喧宾夺主
2. 每个可视化片段必须服务于具体的信息表达需求。
3. 绝对禁止输出 !DOCTYPE/html/head/body 全量页面框架;禁止将整段回复包裹于单一 HTML 块。
4. 图形仅限:流程图、架构图、状态机、树状层级、对比矩阵、数据图表。禁止:装饰性插画、氛围图、风景、图标装饰。
5. 在采用html表达时,请同时考虑Token效率与效果的取舍,及渲染难度和错误率,不要过度设计造成效果失衡。
6. 过于复杂的html可视化内容需慎重考虑。
</red-line>
</vision-plus>
<boundary>
<constraint>永远仅输出自包含片段:只输出 div, style, script 等局部渲染标签,绝对禁止输出 !DOCTYPE, html, head, body 等全量页面框架结构,本末倒置将导致直接判错。</constraint>
<constraint>无缝嵌入正文流:HTML 片段必须像一段加粗或列表一样,自然穿插在 Markdown 文本之间,文字解释与可视化元素相互配合,禁止整段回复全量包裹于一个巨大 HTML 块中。</constraint>
</boundary>
</rule>
</format>
<require>
更积极的使用html-visual为用户提供更好的回复质量和效果
</require>

then

优化着优化着发现, Cherry Studio 可以自定义 CSS. (Cherry Studio CSS 全局注入, 注入到应用DOM的全局样式表)
顺着这个思路, 我们可以在 sysprompt 里说明只做格式的映射,外层由 cherry 的 CSS 接管样式。同时这样可以省点token(:

方案

核心思想: 语义和样式彻底分离, pormpt里说明只做格式的映射: 遇到 X 信息类型,用 Y 语义标签.

提示词 600token
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
<format lang="zh-CN">
<principle>
回复 = 语义化 HTML 片段。将所有内容包裹在 <div class="reply">...</div> 中,
使用预定义 class 描述信息结构;禁止在标签上写任何 style 属性,也禁止输出十六进制色值。
视觉样式由宿主环境的 CSS 统一管理,你只负责"标对语义"。
</principle>

<semantic-mapping>
· 章节标题 → <h2>/<h3>
· 段落散文 → <p>
· 并列卡片组 → <div class="grid grid-2|grid-3"> + <div class="card card-b|g|o|r|p">
· 横向对比 → <div class="row"> + <div class="col card card-x">
· 术语-释义 → <dl><dt>...</dt><dd>...</dd></dl>
· 参数/对比矩阵 → <table><thead><tbody>
· 可折叠细节 → <details><summary>...</summary>...</details>
· 步骤流程 → <ol><li>
· 状态标签 → <span class="badge badge-b|g|o|r">
· 关键术语高亮 → <mark>
· 键盘按键 → <kbd>
· 提示/警告/技巧 → <div class="note|warn|tip">
· 行内代码/代码块 → <code> / <pre><code class="language-xxx">
</semantic-mapping>

<forbid>
1. 禁止 <!DOCTYPE>/<html>/<head>/<body>/<style> 标签。
2. 禁止 style="..." 内联属性。
3. 禁止硬编码色值(#xxx、rgb(...) 等)。
4. 禁止自创 class 名,仅使用 semantic-mapping 中定义的类。
5. 禁止 <br><br> 造间距,用语义标签分块。
6. 禁止省略 <div class="reply"> 外壳。
</forbid>

<anti-pattern>
❌ 仅输出 ## 标题 + 列表 + 偶尔 div 卡片(这是 Markdown 装饰版,不是真 HTML)
✅ 正确姿态:先判断信息类型 → 查 semantic-mapping → 选对应标签
</anti-pattern>

<fallback>
极简回答(纯线性叙述 ≤ 3 句话)可省略外壳,直接 <p>...</p>
</fallback>

<other-rules>
· 简体中文;高信息密度;代码块必须标注语言并优先可运行。
</other-rules>
</format>
css 样式.
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
/* ═══════════════════════════════════════════════════════════
主题来源 https://linux.do/t/topic/325119, 可以换自己喜欢的
深烟雨主题 · Cherry Studio 主题美化 + LLM 回复容器样式
配色基调:墨青 / 雨灰 / 苔绿 / 琥珀
═══════════════════════════════════════════════════════════ */

/* ─── PART 1 · 应用 UI 美化 ─────────────────────────────── */

:root {
--color-black-soft: #1a2429;
--color-white-soft: #f5f7f6;
}

/* 深色:深烟雨 */
body[theme-mode="dark"] {
--color-background: #1a2429; /* 主背景 - 墨青 */
--color-background-soft: #243038; /* 次背景 - 雨灰 */
--color-background-mute: #1f2a31; /* 静默 - 沉雾 */
--navbar-background: #131c20; /* 导航 - 最深 */
--chat-background: #1a2429;
--chat-background-user: #1e3a3f; /* 用户 - 青苔 */
--chat-background-assistant: #243038;
}

body[theme-mode="dark"] #content-container {
background-color: #1a2429 !important;
}
body[theme-mode="dark"] #content-container #messages {
background-color: #1a2429;
}

/* 输入框 */
body[theme-mode="dark"] .inputbar-container {
background-color: #243038;
border: 1px solid #2f3b43;
border-radius: 10px;
}

/* 思考区文字 */
body[theme-mode="dark"] .ant-collapse-content-box .markdown {
color: #94a3b8;
}

/* 全局行内代码 */
body[theme-mode="dark"] code {
background-color: #0f1518;
color: #f59e0b;
}
body[theme-mode="dark"] pre code {
color: #cbd5e1;
background: transparent;
}

/* 浅色:清雨(备用) */
body[theme-mode="light"] {
--color-background: #E8F0F2;
--color-background-soft: #DBE7EB;
--color-background-mute: #D1E0E5;
--navbar-background: #E3EDF0;
--chat-background: #EDF4F6;
--chat-background-user: #E8F0F2;
--chat-background-assistant: #DBE7EB;
--color-white: #EDF4F6;
}
body[theme-mode="light"] #content-container {
background-color: #EDF4F6 !important;
}

/* ─── PART 2 · LLM 回复容器语义类 ────────────────────────── */

body[theme-mode="dark"] {
--llm-card: #243038; /* 卡片底 */
--llm-sunken: #0f1518; /* 凹陷底(代码、徽章) */
--llm-fg: #d6dde2; /* 主文字 - 雾白 */
--llm-muted: #8a9aa3; /* 次文字 - 烟灰 */
--llm-border: #2f3b43; /* 边框 */

/* 语义色:低饱和、与青底协调 */
--llm-c-b: #7dd3fc; /* 青蓝 - 标题/信息 */
--llm-c-g: #86d9b9; /* 松绿 - 成功/术语 */
--llm-c-o: #f5b76e; /* 琥珀 - 警告/代码 */
--llm-c-r: #f08a8a; /* 珊瑚 - 错误 */
--llm-c-p: #c4b5fd; /* 紫藤 - 副标题 */
}

body[theme-mode="light"] {
--llm-card: #ffffff;
--llm-sunken: #DBE7EB;
--llm-fg: #1e293b;
--llm-muted: #64748b;
--llm-border: #B8CDD3;
--llm-c-b: #0369a1;
--llm-c-g: #047857;
--llm-c-o: #b45309;
--llm-c-r: #b91c1c;
--llm-c-p: #6d28d9;
}

/* 主容器 */
.reply { color: var(--llm-fg); line-height: 1.65; }
.reply h2, .reply h3 { color: var(--llm-c-b); margin: 1em 0 .4em; }
.reply h2 { font-size: 1.15em; border-bottom: 1px solid var(--llm-border); padding-bottom: 4px; }
.reply h3 { font-size: 1em; color: var(--llm-c-p); }
.reply p { margin: .5em 0; }

/* 内联元素 */
.reply mark {
background: rgba(245,183,110,.18);
color: var(--llm-c-o);
padding: 0 4px;
border-radius: 3px;
}
.reply kbd {
background: var(--llm-sunken);
border: 1px solid var(--llm-border);
border-radius: 3px;
padding: 1px 6px;
font-size: .85em;
color: var(--llm-fg);
}

/* 表格 */
.reply table { border-collapse: collapse; width: 100%; margin: 8px 0; }
.reply th, .reply td { border: 1px solid var(--llm-border); padding: 6px 10px; text-align: left; }
.reply th { background: rgba(125,211,252,.08); color: var(--llm-c-b); }

/* 术语列表 */
.reply dl { display: grid; grid-template-columns: max-content 1fr; gap: 4px 14px; }
.reply dt { color: var(--llm-c-g); font-weight: 600; }

/* 折叠区 */
.reply details {
background: var(--llm-card);
border: 1px solid var(--llm-border);
border-radius: 6px;
padding: 8px 12px;
margin: 6px 0;
}
.reply summary { cursor: pointer; color: var(--llm-c-b); font-weight: 600; }

/* 布局系统 */
.reply .row { display: flex; gap: 12px; flex-wrap: wrap; margin: 10px 0; }
.reply .col { flex: 1; min-width: 240px; }
.reply .grid { display: grid; gap: 12px; margin: 10px 0; }
.reply .grid-2 { grid-template-columns: repeat(2, 1fr); }
.reply .grid-3 { grid-template-columns: repeat(3, 1fr); }

/* 卡片 */
.reply .card {
background: var(--llm-card);
border: 1px solid var(--llm-border);
border-radius: 6px;
padding: 12px 14px;
}
.reply .card-b { border-top: 3px solid var(--llm-c-b); }
.reply .card-g { border-top: 3px solid var(--llm-c-g); }
.reply .card-o { border-top: 3px solid var(--llm-c-o); }
.reply .card-r { border-top: 3px solid var(--llm-c-r); }
.reply .card-p { border-top: 3px solid var(--llm-c-p); }

/* 徽章 */
.reply .badge {
display: inline-block;
padding: 1px 8px;
border-radius: 10px;
font-size: .82em;
background: var(--llm-sunken);
}
.reply .badge-b { color: var(--llm-c-b); }
.reply .badge-g { color: var(--llm-c-g); }
.reply .badge-o { color: var(--llm-c-o); }
.reply .badge-r { color: var(--llm-c-r); }

/* 提示框 */
.reply .note {
border-left: 3px solid var(--llm-c-b);
background: rgba(125,211,252,.07);
padding: 10px 14px;
border-radius: 4px;
margin: 8px 0;
}
.reply .warn {
border-left: 3px solid var(--llm-c-o);
background: rgba(245,183,110,.07);
padding: 10px 14px;
border-radius: 4px;
margin: 8px 0;
}
.reply .tip {
border-left: 3px solid var(--llm-c-g);
background: rgba(134,217,185,.07);
padding: 10px 14px;
border-radius: 4px;
margin: 8px 0;
}
一些主题
1
2
3
4
5
6
7
8
📦Cherry Studio 主题库
github.com/boilcy/cherrycss

🎨 中国风主题集
linux.do/t/topic/325119/129

🎯 Claude 仿制主题
github.com/igeekbb/Cherry-Studio-Claude-theme

最后的效果展示

alt text
alt text