ARCHITECTURE_NEW_MODULES.html 63 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154
  1. <!DOCTYPE html>
  2. <html lang="zh-CN">
  3. <head>
  4. <meta charset="UTF-8">
  5. <meta name="viewport" content="width=device-width, initial-scale=1.0">
  6. <title>auto_put_ad_mini · 新建子系统架构</title>
  7. <link rel="preconnect" href="https://fonts.googleapis.com">
  8. <link rel="preconnect" href="https://fonts.gstatic.com" crossorigin>
  9. <link href="https://fonts.googleapis.com/css2?family=Newsreader:opsz,wght,SOFT@6..72,300..800,0..100&family=IBM+Plex+Sans:wght@300;400;500;600&family=JetBrains+Mono:wght@400;500&family=Noto+Sans+SC:wght@300;400;500&family=Noto+Serif+SC:wght@300;400;500&display=swap" rel="stylesheet">
  10. <style>
  11. :root {
  12. --paper: #F2EDE3;
  13. --paper-warm: #EFE8DA;
  14. --paper-line: #D4CDB8;
  15. --ink: #0F1F2E;
  16. --ink-2: #2D3D52;
  17. --ink-3: #4A5870;
  18. --ink-mute: #7A8294;
  19. --accent: #C75D3F;
  20. --accent-soft: #E8C7B5;
  21. --moss: #5C7A52;
  22. --gold: #B8902F;
  23. --serif: "Newsreader", "Noto Serif SC", Georgia, serif;
  24. --sans: "IBM Plex Sans", "Noto Sans SC", system-ui, sans-serif;
  25. --mono: "JetBrains Mono", monospace;
  26. }
  27. * { box-sizing: border-box; margin: 0; padding: 0; }
  28. body {
  29. background: var(--paper);
  30. color: var(--ink);
  31. font-family: var(--sans);
  32. line-height: 1.55;
  33. min-height: 100vh;
  34. background-image:
  35. repeating-linear-gradient(0deg, transparent 0, transparent 39px, var(--paper-line) 39px, var(--paper-line) 40px),
  36. repeating-linear-gradient(90deg, transparent 0, transparent 39px, var(--paper-line) 39px, var(--paper-line) 40px);
  37. background-blend-mode: multiply;
  38. position: relative;
  39. }
  40. body::before {
  41. content: "";
  42. position: fixed; inset: 0;
  43. pointer-events: none;
  44. opacity: 0.5;
  45. background-image: url("data:image/svg+xml,%3Csvg xmlns='http://www.w3.org/2000/svg' width='200' height='200'%3E%3Cfilter id='n'%3E%3CfeTurbulence type='fractalNoise' baseFrequency='0.85' /%3E%3CfeColorMatrix values='0 0 0 0 0.06 0 0 0 0 0.12 0 0 0 0 0.18 0 0 0 0.04 0'/%3E%3C/filter%3E%3Crect width='100%25' height='100%25' filter='url(%23n)'/%3E%3C/svg%3E");
  46. mix-blend-mode: multiply;
  47. z-index: 1;
  48. }
  49. main {
  50. position: relative; z-index: 2;
  51. max-width: 1320px;
  52. margin: 0 auto;
  53. padding: 56px 48px 64px;
  54. }
  55. .head {
  56. display: flex;
  57. justify-content: space-between;
  58. align-items: baseline;
  59. margin-bottom: 16px;
  60. padding-bottom: 24px;
  61. border-bottom: 1px solid var(--ink);
  62. flex-wrap: wrap;
  63. gap: 24px;
  64. }
  65. .eyebrow {
  66. font-family: var(--mono);
  67. font-size: 11px;
  68. letter-spacing: 0.3em;
  69. color: var(--accent);
  70. margin-bottom: 12px;
  71. text-transform: uppercase;
  72. }
  73. h1 {
  74. font-family: var(--serif);
  75. font-size: clamp(40px, 5vw, 64px);
  76. font-weight: 300;
  77. line-height: 0.95;
  78. letter-spacing: -0.025em;
  79. font-variation-settings: "opsz" 64, "SOFT" 30;
  80. }
  81. h1 em {
  82. font-style: italic;
  83. color: var(--accent);
  84. font-variation-settings: "opsz" 64, "SOFT" 100;
  85. }
  86. h2 {
  87. font-family: var(--serif);
  88. font-size: 28px;
  89. font-weight: 400;
  90. font-variation-settings: "opsz" 28, "SOFT" 50;
  91. margin-top: 48px;
  92. margin-bottom: 8px;
  93. letter-spacing: -0.01em;
  94. color: var(--ink);
  95. }
  96. h2::before {
  97. content: "§";
  98. color: var(--accent);
  99. font-style: italic;
  100. margin-right: 12px;
  101. font-variation-settings: "opsz" 28, "SOFT" 100;
  102. }
  103. h3 {
  104. font-family: var(--mono);
  105. font-size: 11px;
  106. letter-spacing: 0.2em;
  107. color: var(--ink-mute);
  108. text-transform: uppercase;
  109. margin-top: 24px;
  110. margin-bottom: 8px;
  111. }
  112. .tagline {
  113. font-family: var(--mono);
  114. font-size: 11px;
  115. letter-spacing: 0.15em;
  116. color: var(--ink-mute);
  117. text-align: right;
  118. line-height: 1.7;
  119. }
  120. .subtitle {
  121. font-family: var(--serif);
  122. font-size: 18px;
  123. font-style: italic;
  124. color: var(--ink-2);
  125. font-weight: 300;
  126. margin: 16px 0 32px;
  127. font-variation-settings: "opsz" 18, "SOFT" 60;
  128. max-width: 920px;
  129. }
  130. .intro {
  131. font-size: 14.5px;
  132. color: var(--ink-2);
  133. max-width: 980px;
  134. margin-bottom: 16px;
  135. }
  136. .intro strong {
  137. color: var(--ink);
  138. font-weight: 500;
  139. }
  140. .intro code {
  141. font-family: var(--mono);
  142. font-size: 12.5px;
  143. background: var(--paper-warm);
  144. padding: 1px 5px;
  145. border: 1px solid var(--paper-line);
  146. border-radius: 2px;
  147. color: var(--accent);
  148. }
  149. .diagram-wrap {
  150. background: var(--paper-warm);
  151. border: 1px solid var(--ink);
  152. padding: 36px 24px 24px;
  153. margin: 24px 0 16px;
  154. position: relative;
  155. }
  156. .diagram-wrap[data-tag]::before {
  157. content: attr(data-tag);
  158. position: absolute;
  159. top: -12px;
  160. left: 24px;
  161. background: var(--paper);
  162. padding: 0 12px;
  163. font-family: var(--mono);
  164. font-size: 11px;
  165. letter-spacing: 0.2em;
  166. text-transform: uppercase;
  167. color: var(--ink-3);
  168. border: 1px solid var(--ink);
  169. height: 24px;
  170. display: flex;
  171. align-items: center;
  172. }
  173. svg.arch {
  174. display: block;
  175. width: 100%;
  176. height: auto;
  177. }
  178. svg.arch text {
  179. font-family: var(--sans);
  180. fill: var(--ink-2);
  181. font-size: 13px;
  182. }
  183. svg.arch .title {
  184. font-family: var(--serif);
  185. font-weight: 500;
  186. fill: var(--ink);
  187. font-size: 18px;
  188. font-variation-settings: "opsz" 18;
  189. }
  190. svg.arch .title-en {
  191. font-family: var(--mono);
  192. font-size: 10px;
  193. fill: var(--ink-mute);
  194. letter-spacing: 0.18em;
  195. text-transform: uppercase;
  196. }
  197. svg.arch .agent-label {
  198. font-family: var(--serif);
  199. font-style: italic;
  200. font-size: 14px;
  201. fill: var(--ink-2);
  202. font-variation-settings: "opsz" 14, "SOFT" 80;
  203. }
  204. svg.arch .body { font-size: 12px; fill: var(--ink-3); }
  205. svg.arch .body-strong { font-size: 12.5px; fill: var(--ink-2); font-weight: 500; }
  206. svg.arch .small { font-size: 10.5px; fill: var(--ink-mute); }
  207. svg.arch .mono { font-family: var(--mono); font-size: 11.5px; fill: var(--ink-2); }
  208. svg.arch .mono-mute { font-family: var(--mono); font-size: 10.5px; fill: var(--ink-mute); }
  209. svg.arch .layer-bg {
  210. fill: var(--paper);
  211. stroke: var(--ink);
  212. stroke-width: 1;
  213. }
  214. svg.arch .layer-shared {
  215. fill: #F8F4E8;
  216. stroke: var(--ink);
  217. stroke-width: 1.5;
  218. }
  219. svg.arch .layer-existing {
  220. fill: var(--paper);
  221. stroke: var(--ink-3);
  222. stroke-width: 1.2;
  223. }
  224. svg.arch .layer-new {
  225. fill: #FCEFE7;
  226. stroke: var(--accent);
  227. stroke-width: 1.5;
  228. }
  229. svg.arch .layer-coupling {
  230. fill: var(--paper);
  231. stroke: var(--gold);
  232. stroke-width: 1.5;
  233. stroke-dasharray: 5 3;
  234. }
  235. svg.arch .layer-stub {
  236. fill: var(--paper-warm);
  237. stroke: var(--ink-mute);
  238. stroke-width: 1;
  239. stroke-dasharray: 3 3;
  240. }
  241. svg.arch .pill-shared { fill: var(--moss); stroke: none; }
  242. svg.arch .pill-existing { fill: var(--ink-3); stroke: none; }
  243. svg.arch .pill-new { fill: var(--accent); stroke: none; }
  244. svg.arch .pill-coupling { fill: var(--gold); stroke: none; }
  245. svg.arch .pill-stub { fill: var(--ink-mute); stroke: none; }
  246. svg.arch .pill-text { fill: var(--paper); font-family: var(--mono); font-size: 9.5px; letter-spacing: 0.1em; text-transform: uppercase; }
  247. svg.arch .arrow-data {
  248. stroke: var(--moss);
  249. stroke-width: 1.5;
  250. fill: none;
  251. }
  252. svg.arch .arrow-act {
  253. stroke: var(--accent);
  254. stroke-width: 1.5;
  255. fill: none;
  256. }
  257. svg.arch .arrow-internal {
  258. stroke: var(--ink);
  259. stroke-width: 1;
  260. fill: none;
  261. stroke-dasharray: 3 3;
  262. }
  263. svg.arch .arrow-coupling {
  264. stroke: var(--gold);
  265. stroke-width: 1.5;
  266. fill: none;
  267. stroke-dasharray: 6 3;
  268. }
  269. svg.arch .arrow-label {
  270. font-family: var(--mono);
  271. font-size: 10px;
  272. fill: var(--ink-mute);
  273. letter-spacing: 0.05em;
  274. }
  275. .legend {
  276. display: grid;
  277. grid-template-columns: repeat(auto-fit, minmax(220px, 1fr));
  278. gap: 10px 32px;
  279. margin-top: 20px;
  280. padding-top: 16px;
  281. border-top: 1px dashed var(--paper-line);
  282. font-size: 12.5px;
  283. }
  284. .legend-item {
  285. display: flex;
  286. align-items: center;
  287. gap: 12px;
  288. color: var(--ink-2);
  289. }
  290. .legend-swatch {
  291. width: 28px;
  292. height: 12px;
  293. flex-shrink: 0;
  294. border: 1px solid var(--ink);
  295. }
  296. .legend-swatch.shared { background: #F8F4E8; border-color: var(--ink); border-width: 1.5px; }
  297. .legend-swatch.existing { background: var(--paper); border-color: var(--ink-3); border-width: 1.2px; }
  298. .legend-swatch.new { background: #FCEFE7; border-color: var(--accent); border-width: 1.5px; }
  299. .legend-swatch.coupling { background: var(--paper); border-color: var(--gold); border-width: 1.5px; border-style: dashed; }
  300. .legend-swatch.stub { background: var(--paper-warm); border-color: var(--ink-mute); border-width: 1px; border-style: dashed; }
  301. .legend-line {
  302. width: 32px;
  303. height: 0; border-top-width: 2px; border-top-style: solid;
  304. flex-shrink: 0;
  305. }
  306. .legend-line.data { border-color: var(--moss); }
  307. .legend-line.act { border-color: var(--accent); }
  308. .legend-line.internal { border-color: var(--ink); border-top-style: dashed; }
  309. .legend-line.coupling { border-color: var(--gold); border-top-style: dashed; }
  310. .table-wrap {
  311. background: var(--paper-warm);
  312. border: 1px solid var(--ink);
  313. padding: 28px 24px 24px;
  314. margin: 16px 0;
  315. position: relative;
  316. }
  317. .table-wrap[data-tag]::before {
  318. content: attr(data-tag);
  319. position: absolute;
  320. top: -12px;
  321. left: 24px;
  322. background: var(--paper);
  323. padding: 0 12px;
  324. font-family: var(--mono);
  325. font-size: 11px;
  326. letter-spacing: 0.2em;
  327. text-transform: uppercase;
  328. color: var(--ink-3);
  329. border: 1px solid var(--ink);
  330. height: 24px;
  331. display: flex;
  332. align-items: center;
  333. }
  334. table.matrix {
  335. width: 100%;
  336. border-collapse: collapse;
  337. font-size: 13px;
  338. }
  339. table.matrix th, table.matrix td {
  340. text-align: left;
  341. padding: 9px 12px;
  342. border-bottom: 1px solid var(--paper-line);
  343. vertical-align: top;
  344. }
  345. table.matrix th {
  346. font-family: var(--serif);
  347. font-weight: 500;
  348. font-style: italic;
  349. color: var(--ink);
  350. font-size: 14px;
  351. font-variation-settings: "opsz" 14, "SOFT" 60;
  352. border-bottom: 1.5px solid var(--ink);
  353. }
  354. table.matrix td.mono {
  355. font-family: var(--mono);
  356. font-size: 12px;
  357. }
  358. table.matrix td.shared { color: var(--moss); font-weight: 500; }
  359. table.matrix td.existing { color: var(--ink-3); }
  360. table.matrix td.new { color: var(--accent); font-weight: 500; }
  361. table.matrix td.muted { color: var(--ink-mute); }
  362. table.matrix tr:last-child td { border-bottom: none; }
  363. .gantt-bar {
  364. position: relative;
  365. height: 22px;
  366. background: var(--paper);
  367. border: 1px solid var(--ink-mute);
  368. border-radius: 2px;
  369. margin-bottom: 2px;
  370. }
  371. .gantt-fill {
  372. position: absolute;
  373. top: 0; bottom: 0;
  374. background: var(--accent);
  375. opacity: 0.85;
  376. display: flex;
  377. align-items: center;
  378. padding: 0 8px;
  379. font-family: var(--mono);
  380. font-size: 10px;
  381. color: var(--paper);
  382. letter-spacing: 0.08em;
  383. text-transform: uppercase;
  384. white-space: nowrap;
  385. }
  386. .gantt-fill.shared-bar { background: var(--moss); }
  387. .gantt-fill.cross-bar { background: var(--gold); }
  388. footer {
  389. margin-top: 48px;
  390. padding-top: 16px;
  391. border-top: 1px dashed var(--paper-line);
  392. font-family: var(--mono);
  393. font-size: 11px;
  394. color: var(--ink-mute);
  395. letter-spacing: 0.1em;
  396. display: flex;
  397. justify-content: space-between;
  398. flex-wrap: wrap;
  399. gap: 12px;
  400. }
  401. footer .stamp {
  402. font-family: var(--serif);
  403. font-style: italic;
  404. letter-spacing: 0.02em;
  405. }
  406. @keyframes drawIn {
  407. from { opacity: 0; transform: translateY(8px); }
  408. to { opacity: 1; transform: translateY(0); }
  409. }
  410. .head, .subtitle, .intro, .diagram-wrap, .table-wrap, footer {
  411. animation: drawIn 0.55s ease-out backwards;
  412. }
  413. .head { animation-delay: 0.05s; }
  414. .subtitle { animation-delay: 0.12s; }
  415. @media (max-width: 700px) {
  416. main { padding: 32px 20px; }
  417. .head { flex-direction: column; }
  418. .tagline { text-align: left; }
  419. }
  420. </style>
  421. </head>
  422. <body>
  423. <main>
  424. <header class="head">
  425. <div>
  426. <div class="eyebrow">解耦架构 · 调控 + 新建 双子系统</div>
  427. <h1>新建广告 <em>·</em> 新建创意 · 架构设计</h1>
  428. </div>
  429. <div class="tagline">
  430. 项目代号 auto_put_ad_mini<br>
  431. plan v2 · 2026-06-05
  432. </div>
  433. </header>
  434. <p class="subtitle">
  435. 现有"调控子系统"做减法 — <strong style="color:var(--ink);font-style:normal">关停 / 调价 / 扩量</strong>;新增"新建子系统"做加法 — <strong style="color:var(--accent);font-style:normal">建广告 / 挂创意</strong>。两者共享数据 + 平台 API + 基础知识,但各自的<strong style="color:var(--ink);font-style:normal">脑子 (skill + prompt)</strong>独立,避免互相污染。
  436. </p>
  437. <p class="intro">
  438. 本文档展示 <strong>6 张图</strong>:① 三层架构(共享 infra · 双子系统 · 关联点) · ② 数据契约流向 · ③ 关联点放大图 · ④ 模块 A/B 内部流水线 · ⑤ 决策框架 L1/L2/L3 · ⑥ 实施甘特图。配色:<code>cream</code> 为共享 infra,<code>navy</code> 既有调控,<code>terracotta</code> 新建子系统,<code>gold</code> 跨系统关联点。
  439. </p>
  440. <div style="background:#FCEFE7;border-left:4px solid var(--accent);padding:14px 20px;margin:16px 0 8px;font-size:13.5px;color:var(--ink-2)">
  441. <strong style="color:var(--accent);font-family:var(--serif);font-style:italic;font-size:15px">关键约束 · 一账一人群包(2026-06-05 锁定)</strong><br>
  442. 一个账户固定一个 <code>custom_audience</code>(人群包),即使有多个广告也不变。这意味着 <strong>audience 不参与广告差异化</strong>,跨 tier 测试通过<strong>跨账户</strong>实现。单账户内唯一性差异化维度退化为 <code>site_set × age × geo</code> 三维,可建 <code>4×4×4 = 64</code> 种 unique 组合,起步 5-15 条远未饱和。账户与人群包映射由 <code>ACCOUNT_AUDIENCE_PACK_MAPPING[account_id]</code> 在配置中预设,LLM 不参与选择。
  443. </div>
  444. <!-- ════════════════════════════════════════════════════ -->
  445. <!-- FIGURE 1 · 三层架构总图 -->
  446. <!-- ════════════════════════════════════════════════════ -->
  447. <h2>图一 · 三层架构总览</h2>
  448. <div class="diagram-wrap" data-tag="FIG · 01 · LAYERED ARCHITECTURE">
  449. <svg class="arch" viewBox="0 0 1260 760" xmlns="http://www.w3.org/2000/svg">
  450. <defs>
  451. <marker id="arr-data" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#5C7A52"/></marker>
  452. <marker id="arr-act" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#C75D3F"/></marker>
  453. <marker id="arr-int" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0F1F2E"/></marker>
  454. <marker id="arr-cpl" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#B8902F"/></marker>
  455. </defs>
  456. <!-- =========== Layer 1 · 共享基础设施 =========== -->
  457. <rect x="40" y="40" width="1180" height="170" class="layer-shared" rx="3"/>
  458. <rect x="56" y="32" width="180" height="20" fill="#5C7A52" rx="2"/>
  459. <text x="146" y="46" class="pill-text" text-anchor="middle">Layer 1 · Shared Infra</text>
  460. <text x="630" y="78" class="title" text-anchor="middle">共享基础设施</text>
  461. <text x="630" y="98" class="agent-label" text-anchor="middle">两个子系统都依赖的"地基"— 数据 · 能力 · 知识 · 配置</text>
  462. <!-- 4 columns -->
  463. <rect x="76" y="118" width="270" height="78" class="layer-bg" rx="2"/>
  464. <text x="90" y="138" class="mono-mute">DATA 数据层</text>
  465. <text x="90" y="156" class="body-strong">data_query · roi_calculator</text>
  466. <text x="90" y="172" class="body">creative_metrics · portfolio_metrics</text>
  467. <text x="90" y="186" class="small">→ metrics_{date}.csv · portfolio_summary.json</text>
  468. <rect x="358" y="118" width="270" height="78" class="layer-bg" rx="2"/>
  469. <text x="372" y="138" class="mono-mute">CAPABILITY 能力层</text>
  470. <text x="372" y="156" class="body-strong">ad_api (腾讯 v3.0)</text>
  471. <text x="372" y="172" class="body">im_approval (飞书基类) · execution_engine</text>
  472. <text x="372" y="186" class="small">QPS · retry · audit log 公共部分</text>
  473. <rect x="640" y="118" width="270" height="78" class="layer-bg" rx="2"/>
  474. <text x="654" y="138" class="mono-mute">KNOWLEDGE 知识层</text>
  475. <text x="654" y="156" class="body-strong">skills/ad_domain.md</text>
  476. <text x="654" y="172" class="body">skills/platform_rules.md</text>
  477. <text x="654" y="186" class="small">两个 Agent 系统 prompt 都注入</text>
  478. <rect x="922" y="118" width="270" height="78" class="layer-bg" rx="2"/>
  479. <text x="936" y="138" class="mono-mute">CONFIG 配置层</text>
  480. <text x="936" y="156" class="body-strong">config.py [SHARED] 段</text>
  481. <text x="936" y="172" class="body">账户白名单 · QPS · 时区 · 数据窗口</text>
  482. <text x="936" y="186" class="small">基础阈值 · 冷启动天数 · 最低统计门槛</text>
  483. <!-- 共享层 → 两个子系统的分流箭头 -->
  484. <path class="arrow-data" d="M 350 210 L 350 250" marker-end="url(#arr-data)"/>
  485. <path class="arrow-data" d="M 910 210 L 910 250" marker-end="url(#arr-data)"/>
  486. <!-- =========== Layer 2a · 调控子系统(现有)=========== -->
  487. <rect x="40" y="260" width="580" height="350" class="layer-existing" rx="3"/>
  488. <rect x="56" y="252" width="220" height="20" fill="#4A5870" rx="2"/>
  489. <text x="166" y="266" class="pill-text" text-anchor="middle">Layer 2a · 调控子系统(现有)</text>
  490. <text x="330" y="296" class="title" text-anchor="middle">调控子系统</text>
  491. <text x="330" y="316" class="agent-label" text-anchor="middle" style="fill:var(--ink-3)">"做减法 + 微调"— 完全保留,本期几乎不动</text>
  492. <rect x="60" y="340" width="540" height="36" class="layer-bg" rx="2"/>
  493. <text x="74" y="362" class="mono-mute">ENTRYPOINT</text>
  494. <text x="220" y="362" class="body-strong" style="font-family:var(--mono);font-size:13px">execute_once.py</text>
  495. <text x="430" y="362" class="small">每日 02:00 UTC (K8s cronjob)</text>
  496. <rect x="60" y="386" width="540" height="60" class="layer-bg" rx="2"/>
  497. <text x="74" y="406" class="mono-mute">BRAIN · CODE</text>
  498. <text x="74" y="424" class="body">tools/ad_decision.py · execution_engine 现有 dispatch</text>
  499. <text x="74" y="438" class="small">VALID_ACTIONS = pause / bid_down / bid_up / scale_up / observe / hold / creative_adjust</text>
  500. <rect x="60" y="456" width="540" height="60" class="layer-bg" rx="2"/>
  501. <text x="74" y="476" class="mono-mute">BRAIN · KNOWLEDGE</text>
  502. <text x="74" y="494" class="body-strong">prompts/system.prompt</text>
  503. <text x="74" y="508" class="body">skills/decision_strategy.md · posterior_wisdom.md</text>
  504. <rect x="60" y="526" width="540" height="68" class="layer-bg" rx="2"/>
  505. <text x="74" y="546" class="mono-mute">OUTPUT · APPROVAL · EXECUTION</text>
  506. <text x="74" y="562" class="body">→ outputs/reports/llm_decisions_{date}.csv</text>
  507. <text x="74" y="576" class="body">→ outputs/reports/decision_{date}.xlsx · <tspan style="font-family:var(--mono);font-size:11.5px">FEISHU_OPERATOR_CHAT_ID</tspan></text>
  508. <text x="74" y="588" class="small">→ outputs/execution_log/exec_{date}.jsonl(审计)</text>
  509. <!-- =========== Layer 2b · 新建子系统(新增)=========== -->
  510. <rect x="640" y="260" width="580" height="350" class="layer-new" rx="3"/>
  511. <rect x="656" y="252" width="220" height="20" fill="#C75D3F" rx="2"/>
  512. <text x="766" y="266" class="pill-text" text-anchor="middle">Layer 2b · 新建子系统(新增)</text>
  513. <text x="930" y="296" class="title" text-anchor="middle" style="fill:var(--accent)">新建子系统</text>
  514. <text x="930" y="316" class="agent-label" text-anchor="middle" style="fill:var(--ink-3)">"做加法"— 全新独立 entrypoint,与调控并行</text>
  515. <rect x="660" y="340" width="540" height="36" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-width:1.2"/>
  516. <text x="674" y="362" class="mono-mute">ENTRYPOINT</text>
  517. <text x="820" y="362" class="body-strong" style="font-family:var(--mono);font-size:13px;fill:var(--accent)">execute_creation_once.py</text>
  518. <text x="1030" y="362" class="small">每日 02:30 UTC (新 cronjob)</text>
  519. <rect x="660" y="386" width="540" height="60" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-width:1.2"/>
  520. <text x="674" y="406" class="mono-mute">BRAIN · CODE(全新 8 个模块)</text>
  521. <text x="674" y="422" class="body" style="font-size:11.5px">creation_decision · ad_creation · creative_creation</text>
  522. <text x="674" y="436" class="body" style="font-size:11.5px">material_recall · material_recall_sources · dedup_check<tspan style="fill:var(--ink-mute)"> (stub)</tspan> · uniqueness_check · audience_demand</text>
  523. <rect x="660" y="456" width="540" height="60" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-width:1.2"/>
  524. <text x="674" y="476" class="mono-mute">BRAIN · KNOWLEDGE(独立 prompt + skill)</text>
  525. <text x="674" y="494" class="body-strong" style="fill:var(--accent)">prompts/system_creation.prompt</text>
  526. <text x="674" y="508" class="body">skills/creation_strategy.md(新增)</text>
  527. <rect x="660" y="526" width="540" height="68" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-width:1.2"/>
  528. <text x="674" y="546" class="mono-mute">OUTPUT · APPROVAL · EXECUTION</text>
  529. <text x="674" y="562" class="body">→ outputs/reports/creation_decisions_{date}.csv</text>
  530. <text x="674" y="576" class="body">→ outputs/reports/creation_{date}.xlsx · <tspan style="font-family:var(--mono);font-size:11.5px;fill:var(--accent)">FEISHU_CREATION_CHAT_ID</tspan></text>
  531. <text x="674" y="588" class="small">→ outputs/execution_log/creation_exec_{date}.jsonl(独立审计)</text>
  532. <!-- =========== Layer 3 · 最小耦合点 =========== -->
  533. <rect x="40" y="640" width="1180" height="100" class="layer-coupling" rx="3"/>
  534. <rect x="56" y="632" width="200" height="20" fill="#B8902F" rx="2"/>
  535. <text x="156" y="646" class="pill-text" text-anchor="middle">Layer 3 · Minimal Coupling</text>
  536. <text x="630" y="670" class="title" text-anchor="middle" style="fill:var(--gold)">关联点(本期实现:单向)</text>
  537. <text x="630" y="690" class="body" text-anchor="middle">新建子系统启动时只读调控的 <tspan style="font-family:var(--mono)">llm_decisions_{LATEST}.csv</tspan>,
  538. 提取 <tspan style="font-family:var(--mono);fill:var(--ink)">{ad_id where action=='pause'}</tspan> 加入 <tspan style="font-family:var(--mono);fill:var(--accent)">excluded_ad_ids</tspan> 黑名单</text>
  539. <text x="630" y="710" class="small" text-anchor="middle">add_creative 候选标记阶段硬过滤 · 不给"即将被关停的广告"补创意 · 反向耦合(调控读新建)留下期</text>
  540. <!-- 关联点箭头 -->
  541. <path class="arrow-coupling" d="M 330 610 L 330 640" marker-end="url(#arr-cpl)"/>
  542. <text x="340" y="628" class="arrow-label" style="fill:var(--gold)">latest_decisions</text>
  543. <path class="arrow-coupling" d="M 930 640 L 930 610" marker-end="url(#arr-cpl)"/>
  544. <text x="888" y="630" class="arrow-label" style="fill:var(--gold)" text-anchor="end">excluded_ad_ids</text>
  545. </svg>
  546. <div class="legend">
  547. <div class="legend-item"><span class="legend-swatch shared"></span>共享 infra(数据 / API / 基础 skill)</div>
  548. <div class="legend-item"><span class="legend-swatch existing"></span>调控子系统(现有 · 不动)</div>
  549. <div class="legend-item"><span class="legend-swatch new"></span>新建子系统(全新)</div>
  550. <div class="legend-item"><span class="legend-swatch coupling"></span>跨系统关联点(单向 · 最小)</div>
  551. <div class="legend-item"><span class="legend-line data"></span>数据流(共享 → 子系统)</div>
  552. <div class="legend-item"><span class="legend-line coupling"></span>关联流(单向只读)</div>
  553. </div>
  554. </div>
  555. <!-- ════════════════════════════════════════════════════ -->
  556. <!-- FIGURE 2 · 数据契约流向 -->
  557. <!-- ════════════════════════════════════════════════════ -->
  558. <h2>图二 · 数据契约 — 文件级数据流</h2>
  559. <p class="intro">
  560. 两个子系统通过<strong>文件系统</strong>通信,**互不调用对方 API**。所有产物文件都在 <code>outputs/</code> 下,可单独审计。共享只读输入由调控子系统在 02:00 写出 → 新建子系统在 02:30 读入。
  561. </p>
  562. <div class="diagram-wrap" data-tag="FIG · 02 · DATA CONTRACTS">
  563. <svg class="arch" viewBox="0 0 1260 620" xmlns="http://www.w3.org/2000/svg">
  564. <defs>
  565. <marker id="arr-data2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#5C7A52"/></marker>
  566. <marker id="arr-int2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0F1F2E"/></marker>
  567. <marker id="arr-cpl2" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#B8902F"/></marker>
  568. </defs>
  569. <!-- ============ 共享只读输入(上方) ============ -->
  570. <rect x="40" y="40" width="1180" height="120" class="layer-shared" rx="3"/>
  571. <text x="60" y="62" class="mono-mute">SHARED READ-ONLY INPUTS · 共享只读输入(由调控产 / 新建读)</text>
  572. <rect x="60" y="78" width="260" height="68" class="layer-bg" rx="2"/>
  573. <text x="74" y="96" class="mono">metrics_{date}.csv</text>
  574. <text x="74" y="112" class="small">广告级 + 创意级 ROI</text>
  575. <text x="74" y="126" class="small">候选标记(roi_low / decay_signal / ...)</text>
  576. <text x="74" y="140" class="small">由 roi_calculator.py 产</text>
  577. <rect x="340" y="78" width="260" height="68" class="layer-bg" rx="2"/>
  578. <text x="354" y="96" class="mono">portfolio_summary_{date}.json</text>
  579. <text x="354" y="112" class="small">tier 基线 channel_p50 / tier_fission_mean</text>
  580. <text x="354" y="126" class="small">渠道 P25/50/75 分位</text>
  581. <text x="354" y="140" class="small">由 portfolio_metrics.py 产</text>
  582. <rect x="620" y="78" width="260" height="68" class="layer-bg" rx="2"/>
  583. <text x="634" y="96" class="mono">ad_status_{date}.csv</text>
  584. <text x="634" y="112" class="small">广告状态快照(活跃 / pause / 删除)</text>
  585. <text x="634" y="126" class="small">出价 · 预算 · 定向</text>
  586. <text x="634" y="140" class="small">由 data_query.py 产</text>
  587. <rect x="900" y="78" width="300" height="68" class="layer-bg" rx="2"/>
  588. <text x="914" y="96" class="mono">creative_pause_history.json</text>
  589. <text x="914" y="112" class="mono" style="font-size:10.5px">adjustment_history.json</text>
  590. <text x="914" y="128" class="small">操作级频次(7 日窗口)</text>
  591. <text x="914" y="142" class="small">两子系统都读以避免频次违规</text>
  592. <!-- ============ 调控子系统产物(左下) ============ -->
  593. <rect x="40" y="200" width="540" height="200" class="layer-existing" rx="3"/>
  594. <text x="56" y="222" class="mono-mute">ADJUSTMENT SUBSYSTEM OUTPUTS</text>
  595. <text x="56" y="240" class="title">调控产物(现有)</text>
  596. <rect x="60" y="256" width="500" height="36" class="layer-bg" rx="2"/>
  597. <text x="74" y="276" class="mono">outputs/reports/llm_decisions_{date}.csv</text>
  598. <text x="380" y="276" class="small">每行一条决策(7 种 action)</text>
  599. <rect x="60" y="300" width="500" height="36" class="layer-bg" rx="2"/>
  600. <text x="74" y="320" class="mono">outputs/reports/decision_{date}.xlsx</text>
  601. <text x="380" y="320" class="small">飞书审批表(调控群)</text>
  602. <rect x="60" y="344" width="500" height="36" class="layer-bg" rx="2"/>
  603. <text x="74" y="364" class="mono">outputs/execution_log/exec_{date}.jsonl</text>
  604. <text x="380" y="364" class="small">API 调用审计</text>
  605. <!-- ============ 新建子系统产物(右下) ============ -->
  606. <rect x="640" y="200" width="580" height="280" class="layer-new" rx="3"/>
  607. <text x="656" y="222" class="mono-mute" style="fill:var(--accent)">CREATION SUBSYSTEM OUTPUTS</text>
  608. <text x="656" y="240" class="title" style="fill:var(--accent)">新建产物(全新)</text>
  609. <rect x="660" y="256" width="540" height="36" class="layer-bg" rx="2" style="stroke:var(--accent)"/>
  610. <text x="674" y="276" class="mono" style="fill:var(--accent)">outputs/reports/creation_decisions_{date}.csv</text>
  611. <text x="990" y="276" class="small">action ∈ {create_ad, add_creative}</text>
  612. <rect x="660" y="300" width="540" height="36" class="layer-bg" rx="2" style="stroke:var(--accent)"/>
  613. <text x="674" y="320" class="mono" style="fill:var(--accent)">outputs/reports/creation_{date}.xlsx</text>
  614. <text x="990" y="320" class="small">飞书审批表(新建群)</text>
  615. <rect x="660" y="344" width="540" height="36" class="layer-bg" rx="2" style="stroke:var(--accent)"/>
  616. <text x="674" y="364" class="mono" style="fill:var(--accent)">outputs/execution_log/creation_exec_{date}.jsonl</text>
  617. <text x="990" y="364" class="small">独立审计</text>
  618. <rect x="660" y="388" width="260" height="80" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-dasharray:3 3"/>
  619. <text x="674" y="406" class="mono" style="font-size:10.5px;fill:var(--accent)">outputs/data/ad_fingerprint_cache.json</text>
  620. <text x="674" y="422" class="small">营销内容指纹(唯一性预校验)</text>
  621. <text x="674" y="436" class="small" style="font-style:italic">每次新建广告前先比对此缓存</text>
  622. <text x="674" y="450" class="small" style="font-style:italic">+ 调 ads_get 同步</text>
  623. <rect x="940" y="388" width="260" height="80" class="layer-bg" rx="2" style="stroke:var(--accent);stroke-dasharray:3 3"/>
  624. <text x="954" y="406" class="mono" style="font-size:10.5px;fill:var(--accent)">creative_add_history.json</text>
  625. <text x="954" y="422" class="mono" style="font-size:10.5px;fill:var(--accent)">ad_creation_history.json</text>
  626. <text x="954" y="440" class="small">7 日累计护栏数据源</text>
  627. <text x="954" y="454" class="small" style="font-style:italic">类比现有 creative_pause_history</text>
  628. <!-- ============ 数据流箭头 ============ -->
  629. <!-- 共享 → 调控 -->
  630. <path class="arrow-data" d="M 180 158 L 180 200" marker-end="url(#arr-data2)"/>
  631. <!-- 共享 → 新建 -->
  632. <path class="arrow-data" d="M 770 158 L 770 200" marker-end="url(#arr-data2)"/>
  633. <!-- 调控 → 新建(关联点:单向只读) -->
  634. <path class="arrow-coupling" d="M 560 278 C 600 278 600 278 640 278" marker-end="url(#arr-cpl2)"/>
  635. <text x="582" y="271" class="arrow-label" text-anchor="middle" style="fill:var(--gold)">read pause ad_id</text>
  636. <!-- 注释:反向耦合留下期 -->
  637. <line x1="640" y1="320" x2="560" y2="320" stroke="#7A8294" stroke-width="0.6" stroke-dasharray="2 4"/>
  638. <text x="600" y="334" class="small" text-anchor="middle" style="font-style:italic;font-size:9.5px">反向耦合(调控读新建)留下期</text>
  639. <!-- ============ 关联点细节(底部说明) ============ -->
  640. <rect x="40" y="510" width="1180" height="86" class="layer-coupling" rx="3"/>
  641. <text x="58" y="532" class="mono-mute" style="fill:var(--gold)">LAYER 3 · COUPLING DETAIL</text>
  642. <text x="58" y="550" class="body-strong" style="fill:var(--ink)">新建子系统 Step 1:</text>
  643. <text x="58" y="568" class="body" style="font-family:var(--mono);font-size:11.5px">excluded_ad_ids = read_pause_ad_ids(latest_llm_decisions)</text>
  644. <text x="58" y="584" class="body">→ 传给 LLM prompt + 候选标记代码(<tspan style="font-family:var(--mono);font-size:11.5px;fill:var(--accent)">creation_decision.mark_add_creative_candidates</tspan>)</text>
  645. <text x="700" y="550" class="body-strong" style="fill:var(--ink)">空盘场景(常态):</text>
  646. <text x="700" y="568" class="body">如果调控 latest 无 pause 决策 → <tspan style="font-style:italic">excluded_ad_ids = ∅</tspan></text>
  647. <text x="700" y="584" class="body">新建子系统照常按自己的候选 + LLM 决策跑</text>
  648. </svg>
  649. </div>
  650. <!-- ════════════════════════════════════════════════════ -->
  651. <!-- FIGURE 3 · 模块 A + B 内部流水线 -->
  652. <!-- ════════════════════════════════════════════════════ -->
  653. <h2>图三 · 模块 A 广告新建 · 内部流水线</h2>
  654. <div class="diagram-wrap" data-tag="FIG · 03 · MODULE A · NEW AD PIPELINE">
  655. <svg class="arch" viewBox="0 0 1260 540" xmlns="http://www.w3.org/2000/svg">
  656. <defs>
  657. <marker id="arr-act3" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#C75D3F"/></marker>
  658. <marker id="arr-int3" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0F1F2E"/></marker>
  659. </defs>
  660. <!-- Top: 触发候选标记 (L1) -->
  661. <rect x="40" y="40" width="1180" height="90" class="layer-bg" rx="3"/>
  662. <text x="58" y="62" class="mono-mute">STEP 1 · 候选标记(L1 代码层 · 每 tier 硬算 6 信号)</text>
  663. <text x="58" y="80" class="body-strong" style="font-family:var(--mono);font-size:12.5px;fill:var(--accent)">tools/creation_decision.py::mark_create_ad_candidates(portfolio_summary, ads_snapshot, history)</text>
  664. <rect x="60" y="92" width="190" height="32" class="layer-bg" rx="2"/>
  665. <text x="68" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">tier_active_low</text>
  666. <rect x="260" y="92" width="190" height="32" class="layer-bg" rx="2"/>
  667. <text x="268" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">tier_pause_burst</text>
  668. <rect x="460" y="92" width="190" height="32" class="layer-bg" rx="2"/>
  669. <text x="468" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">tier_creative_refresh_failed</text>
  670. <rect x="660" y="92" width="190" height="32" class="layer-bg" rx="2"/>
  671. <text x="668" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">tier_uniqueness_slots_available</text>
  672. <rect x="860" y="92" width="160" height="32" class="layer-bg" rx="2"/>
  673. <text x="868" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">tier_roi_healthy</text>
  674. <rect x="1030" y="92" width="170" height="32" class="layer-bg" rx="2"/>
  675. <text x="1038" y="111" class="small" style="font-family:var(--mono);font-size:10.5px">account_quota_remaining</text>
  676. <path class="arrow-internal" d="M 630 130 L 630 154" marker-end="url(#arr-int3)"/>
  677. <text x="640" y="148" class="arrow-label">任 4 项命中 → 候选</text>
  678. <!-- Step 2: LLM 综合判断 (L2) -->
  679. <rect x="40" y="160" width="1180" height="60" class="layer-bg" rx="3" style="stroke:var(--accent);stroke-width:1.5"/>
  680. <text x="58" y="182" class="mono-mute" style="fill:var(--accent)">STEP 2 · LLM 综合判断(L2 · skill 启发式)</text>
  681. <text x="58" y="200" class="body-strong" style="fill:var(--accent)">skills/creation_strategy.md</text>
  682. <text x="58" y="214" class="body" style="font-size:11.5px">看 6 个候选 + tier 趋势 + 7 日累计配额,综合决定 "create_ad(tier_X, N 条)" + reason 5 元组 + confidence</text>
  683. <path class="arrow-internal" d="M 630 220 L 630 244" marker-end="url(#arr-int3)"/>
  684. <!-- Step 3: 唯一性枚举搜索 -->
  685. <rect x="40" y="250" width="1180" height="120" class="layer-bg" rx="3"/>
  686. <text x="58" y="272" class="mono-mute">STEP 3 · 唯一性枚举搜索(避免 1901634)· 约束:一账一包,audience 账户级固定</text>
  687. <text x="58" y="290" class="body-strong" style="font-family:var(--mono);font-size:12.5px">tools/ad_creation.py::enumerate_new_ad_candidates(account_id, N)</text>
  688. <text x="58" y="308" class="body" style="font-size:11.5px">笛卡尔积 <tspan style="font-family:var(--mono);fill:var(--accent)">site_set × age × geo</tspan>(3 维,共 4×4×4=64 组合) → 过滤已有 fingerprint → 取前 N</text>
  689. <rect x="60" y="320" width="220" height="42" class="layer-bg" rx="2"/>
  690. <text x="70" y="338" class="small" style="font-family:var(--mono);font-size:10.5px">site_set: 知乎信息流 · 朋友圈</text>
  691. <text x="70" y="354" class="small" style="font-family:var(--mono);font-size:10.5px">微信公众号 · 优量汇 ...(4)</text>
  692. <rect x="290" y="320" width="220" height="42" class="layer-bg" rx="2"/>
  693. <text x="300" y="338" class="small" style="font-family:var(--mono);font-size:10.5px">age 离散段: 18-25 / 26-35 /</text>
  694. <text x="300" y="354" class="small" style="font-family:var(--mono);font-size:10.5px">36-45 / 46-55(4)</text>
  695. <rect x="520" y="320" width="220" height="42" class="layer-bg" rx="2"/>
  696. <text x="530" y="338" class="small" style="font-family:var(--mono);font-size:10.5px">geo 离散段: 全国 / 一线 /</text>
  697. <text x="530" y="354" class="small" style="font-family:var(--mono);font-size:10.5px">二线 / 三四线(4)</text>
  698. <rect x="760" y="320" width="440" height="42" class="layer-bg" rx="2" style="stroke:var(--gold)"/>
  699. <text x="770" y="338" class="small" style="font-family:var(--mono);font-size:10.5px;fill:var(--gold)">audience 已由 ACCOUNT_AUDIENCE_PACK_MAPPING 固定</text>
  700. <text x="770" y="354" class="small" style="font-style:italic">+ fingerprint_cache + ads_get(account_id) → 单账户 64 组合中取 N 个 unique</text>
  701. <path class="arrow-internal" d="M 630 370 L 630 394" marker-end="url(#arr-int3)"/>
  702. <!-- Step 4: 出价 + 预算 + 命名 -->
  703. <rect x="40" y="400" width="1180" height="86" class="layer-bg" rx="3"/>
  704. <text x="58" y="422" class="mono-mute">STEP 4 · 出价基准三层降级 + 预算 + 命名</text>
  705. <text x="58" y="438" class="body-strong" style="font-family:var(--mono);font-size:12px">tools/ad_creation.py::compute_target_bid(tier, site_set, age, geo)</text>
  706. <rect x="58" y="448" width="290" height="32" class="layer-bg" rx="2"/>
  707. <text x="68" y="466" class="small" style="font-family:var(--mono);font-size:10.5px">① combo_median (≥3 历史)→ factor 1.20</text>
  708. <rect x="358" y="448" width="290" height="32" class="layer-bg" rx="2"/>
  709. <text x="368" y="466" class="small" style="font-family:var(--mono);font-size:10.5px">② tier_history_median → factor 1.30</text>
  710. <rect x="658" y="448" width="290" height="32" class="layer-bg" rx="2"/>
  711. <text x="668" y="466" class="small" style="font-family:var(--mono);font-size:10.5px">③ channel_p50(兜底)→ factor 1.50</text>
  712. <rect x="958" y="448" width="244" height="32" class="layer-bg" rx="2"/>
  713. <text x="968" y="466" class="small" style="font-family:var(--mono);font-size:10.5px">budget = combo_median × 0.5</text>
  714. <path class="arrow-act" d="M 630 486 L 630 510" marker-end="url(#arr-act3)"/>
  715. <!-- Step 5: 输出 -->
  716. <rect x="40" y="510" width="1180" height="20" class="layer-new" rx="2"/>
  717. <text x="630" y="525" text-anchor="middle" class="body-strong" style="fill:var(--accent);font-size:11.5px">→ 写一行到 creation_decisions_{date}.csv · action_type='create_ad' · 等飞书审批 · 通过则调 ad_api.ad_create()</text>
  718. </svg>
  719. </div>
  720. <h2>图四 · 模块 B 创意新建 · 内部流水线</h2>
  721. <div class="diagram-wrap" data-tag="FIG · 04 · MODULE B · NEW CREATIVE PIPELINE">
  722. <svg class="arch" viewBox="0 0 1260 580" xmlns="http://www.w3.org/2000/svg">
  723. <defs>
  724. <marker id="arr-act4" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#C75D3F"/></marker>
  725. <marker id="arr-int4" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0F1F2E"/></marker>
  726. <marker id="arr-cpl4" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#B8902F"/></marker>
  727. </defs>
  728. <!-- Step 1: 候选标记 (L1) -->
  729. <rect x="40" y="40" width="1180" height="100" class="layer-bg" rx="3"/>
  730. <text x="58" y="62" class="mono-mute">STEP 1 · 候选标记(L1 代码层 · 每广告硬算 7 信号)</text>
  731. <text x="58" y="80" class="body-strong" style="font-family:var(--mono);font-size:12.5px;fill:var(--accent)">tools/creation_decision.py::mark_add_creative_candidates(metrics, excluded_ad_ids, history, tier_summary)</text>
  732. <rect x="58" y="92" width="160" height="38" class="layer-bg" rx="2"/>
  733. <text x="66" y="108" class="small" style="font-family:var(--mono);font-size:10.5px">decay_signal</text>
  734. <text x="66" y="122" class="small">(复用现有)</text>
  735. <rect x="228" y="92" width="160" height="38" class="layer-bg" rx="2"/>
  736. <text x="236" y="108" class="small" style="font-family:var(--mono);font-size:10.5px">creative_count_low</text>
  737. <text x="236" y="122" class="small">&lt; 15</text>
  738. <rect x="398" y="92" width="160" height="38" class="layer-bg" rx="2"/>
  739. <text x="406" y="108" class="small" style="font-family:var(--mono);font-size:10.5px">creative_age_old</text>
  740. <text x="406" y="122" class="small">中位 ≥ 7 天</text>
  741. <rect x="568" y="92" width="160" height="38" class="layer-bg" rx="2"/>
  742. <text x="576" y="108" class="small" style="font-family:var(--mono);font-size:10.5px">not_recently_added</text>
  743. <text x="576" y="122" class="small">7 天未补过</text>
  744. <rect x="738" y="92" width="160" height="38" class="layer-bg" rx="2"/>
  745. <text x="746" y="108" class="small" style="font-family:var(--mono);font-size:10.5px">ad_alive_and_healthy</text>
  746. <text x="746" y="122" class="small">ROI ≥ P50 × 0.90</text>
  747. <rect x="908" y="92" width="146" height="38" class="layer-bg" rx="2" style="stroke:var(--gold);stroke-width:1.2"/>
  748. <text x="916" y="108" class="small" style="font-family:var(--mono);font-size:10.5px;fill:var(--gold)">tier_not_declining</text>
  749. <text x="916" y="122" class="small">tier 趋势护栏(深度补)</text>
  750. <rect x="1064" y="92" width="140" height="38" class="layer-bg" rx="2" style="stroke:var(--gold);stroke-width:1.2"/>
  751. <text x="1072" y="108" class="small" style="font-family:var(--mono);font-size:10.5px;fill:var(--gold)">not_in_excluded</text>
  752. <text x="1072" y="122" class="small">关联点过滤</text>
  753. <path class="arrow-internal" d="M 630 140 L 630 164" marker-end="url(#arr-int4)"/>
  754. <text x="640" y="158" class="arrow-label">任 4 项命中 → 候选</text>
  755. <!-- Step 2: LLM (L2) -->
  756. <rect x="40" y="170" width="1180" height="60" class="layer-bg" rx="3" style="stroke:var(--accent);stroke-width:1.5"/>
  757. <text x="58" y="192" class="mono-mute" style="fill:var(--accent)">STEP 2 · LLM 综合判断(L2 · skill 启发式)</text>
  758. <text x="58" y="210" class="body-strong" style="fill:var(--accent)">skills/creation_strategy.md</text>
  759. <text x="58" y="224" class="body" style="font-size:11.5px">综合候选 + tier 趋势 + 频次 + 配额 → 决定 "add_creative(ad_X, ≤ 5 条)" + 三路素材配比 + reason + confidence</text>
  760. <path class="arrow-internal" d="M 630 230 L 630 254" marker-end="url(#arr-int4)"/>
  761. <!-- Step 3: 三路素材召回 -->
  762. <rect x="40" y="260" width="1180" height="120" class="layer-bg" rx="3"/>
  763. <text x="58" y="282" class="mono-mute">STEP 3 · 三路素材召回(黑盒 API + 排序加权)</text>
  764. <text x="58" y="300" class="body-strong" style="font-family:var(--mono);font-size:12.5px">tools/material_recall.py::recall_materials(audience_demand, top_k=50, sources, weights)</text>
  765. <rect x="58" y="312" width="380" height="60" class="layer-bg" rx="2"/>
  766. <rect x="58" y="312" width="36" height="60" fill="#5C7A52" rx="2"/>
  767. <text x="76" y="346" text-anchor="middle" class="pill-text" style="fill:var(--paper)" transform="rotate(-90 76 346)">50%</text>
  768. <text x="106" y="332" class="body-strong" style="font-size:13px">① 历史投放素材</text>
  769. <text x="106" y="350" class="small" style="font-family:var(--mono);font-size:10.5px">HistorySource</text>
  770. <text x="106" y="364" class="small">score = 0.3×cost + 0.4×CTR + 0.3×ROI(标准化)</text>
  771. <rect x="448" y="312" width="380" height="60" class="layer-bg" rx="2"/>
  772. <rect x="448" y="312" width="36" height="60" fill="#5C7A52" rx="2"/>
  773. <text x="466" y="346" text-anchor="middle" class="pill-text" style="fill:var(--paper)" transform="rotate(-90 466 346)">30%</text>
  774. <text x="496" y="332" class="body-strong" style="font-size:13px">② 合作方即转卡片</text>
  775. <text x="496" y="350" class="small" style="font-family:var(--mono);font-size:10.5px">PartnerSource</text>
  776. <text x="496" y="364" class="small">score = 卡片点击率</text>
  777. <rect x="838" y="312" width="380" height="60" class="layer-bg" rx="2"/>
  778. <rect x="838" y="312" width="36" height="60" fill="#5C7A52" rx="2"/>
  779. <text x="856" y="346" text-anchor="middle" class="pill-text" style="fill:var(--paper)" transform="rotate(-90 856 346)">20%</text>
  780. <text x="886" y="332" class="body-strong" style="font-size:13px">③ AI 改写 (取 ① top 5)</text>
  781. <text x="886" y="350" class="small" style="font-family:var(--mono);font-size:10.5px">RewriteSource · uses LLM</text>
  782. <text x="886" y="364" class="small">light:同义改写 · medium:句式重组</text>
  783. <path class="arrow-internal" d="M 630 380 L 630 404" marker-end="url(#arr-int4)"/>
  784. <!-- Step 4: 判重 stub + AI 改写升档 -->
  785. <rect x="40" y="410" width="580" height="100" class="layer-bg" rx="3" style="stroke:var(--ink-mute);stroke-width:1;stroke-dasharray:3 3"/>
  786. <text x="58" y="432" class="mono-mute">STEP 4 · 4+M 判重(本期 STUB)</text>
  787. <text x="58" y="450" class="body-strong" style="font-family:var(--mono);font-size:12px">tools/dedup_check.py::check_material_duplicate(...)</text>
  788. <text x="58" y="468" class="body" style="font-size:11.5px">DEDUP_ENABLED=False · always returns not_duplicate</text>
  789. <text x="58" y="486" class="body" style="font-size:11.5px">本地预筛:同广告下 <tspan style="font-family:var(--mono)">md5(image_id+title+desc)</tspan> 去重</text>
  790. <text x="58" y="502" class="small" style="font-style:italic">→ 后续接 4+M 云服务,只改本函数实现,接口不变</text>
  791. <rect x="640" y="410" width="580" height="100" class="layer-bg" rx="3"/>
  792. <text x="658" y="432" class="mono-mute">STEP 5 · AI 改写命中重复时升档</text>
  793. <text x="658" y="450" class="body-strong">light 改写 → 命中重复 → medium → skip</text>
  794. <text x="658" y="468" class="body" style="font-size:11.5px">最多尝试 2 次(<tspan style="font-family:var(--mono)">AI_REWRITE_MAX_ATTEMPTS_PER_MATERIAL=2</tspan>)</text>
  795. <text x="658" y="486" class="body" style="font-size:11.5px">改写后再走判重 → 才上传 / 挂载</text>
  796. <text x="658" y="502" class="small" style="font-style:italic">heavy 级(图像重新生成)留下期</text>
  797. <!-- Step 6: 渐进式 + 上限 -->
  798. <path class="arrow-act" d="M 630 510 L 630 534" marker-end="url(#arr-act4)"/>
  799. <rect x="40" y="540" width="1180" height="32" class="layer-new" rx="2"/>
  800. <text x="630" y="560" text-anchor="middle" class="body-strong" style="fill:var(--accent);font-size:12px">渐进式控制 · 单次 ≤ 5 · 单广告 7 日累计 ≤ 8 · 已有 ≥ 30 不触发 → 写 creation_decisions / 飞书审批 / creative_create()</text>
  801. </svg>
  802. </div>
  803. <!-- ════════════════════════════════════════════════════ -->
  804. <!-- FIGURE 5 · 决策框架 L1 / L2 / L3 -->
  805. <!-- ════════════════════════════════════════════════════ -->
  806. <h2>图五 · 决策框架:代码 vs 知识 三层分工</h2>
  807. <p class="intro">
  808. 两个子系统都遵循同一套<strong>三层分工</strong> — L1 候选标记代码(确定性 · 可单测)/ L2 LLM skill(启发式 · 灰色地带)/ L3 兜底护栏代码(确定性 · 边界)。这是分离架构的核心:**skill 不是简单等于一段话,是 LLM 的推理框架,各子系统必须独立**。
  809. </p>
  810. <div class="diagram-wrap" data-tag="FIG · 05 · L1 / L2 / L3 DECISION LAYERS">
  811. <svg class="arch" viewBox="0 0 1260 500" xmlns="http://www.w3.org/2000/svg">
  812. <!-- L1 lane -->
  813. <rect x="40" y="40" width="1180" height="130" class="layer-bg" rx="3"/>
  814. <rect x="56" y="32" width="180" height="20" fill="#4A5870" rx="2"/>
  815. <text x="146" y="46" class="pill-text" text-anchor="middle">L1 · CANDIDATE MARKING</text>
  816. <text x="60" y="76" class="mono-mute">代码层 · 确定性 · 可单测 · 可回放</text>
  817. <text x="60" y="98" class="title" style="font-size:16px">候选标记</text>
  818. <rect x="60" y="108" width="560" height="52" class="layer-existing" rx="2"/>
  819. <text x="76" y="126" class="body-strong">调控:tools/ad_decision.py</text>
  820. <text x="76" y="142" class="small" style="font-family:var(--mono);font-size:10.5px">roi_low · decay_signal · bid_up_candidate · bid_down_candidate · scale_up_candidate</text>
  821. <text x="76" y="156" class="small">(5 个,现有不动)</text>
  822. <rect x="640" y="108" width="560" height="52" class="layer-new" rx="2"/>
  823. <text x="656" y="126" class="body-strong" style="fill:var(--accent)">新建:tools/creation_decision.py</text>
  824. <text x="656" y="142" class="small" style="font-family:var(--mono);font-size:10.5px">add_creative 7 信号 + create_ad 6 信号(L1 全新)</text>
  825. <text x="656" y="156" class="small">含 tier 级护栏 + 关联点过滤(深度补全)</text>
  826. <!-- L2 lane -->
  827. <rect x="40" y="190" width="1180" height="130" class="layer-bg" rx="3" style="stroke:var(--accent);stroke-width:1.5"/>
  828. <rect x="56" y="182" width="180" height="20" fill="#C75D3F" rx="2"/>
  829. <text x="146" y="196" class="pill-text" text-anchor="middle">L2 · LLM HEURISTIC</text>
  830. <text x="60" y="226" class="mono-mute" style="fill:var(--accent)">知识层 · 启发式 · 灰色地带 · 综合权衡</text>
  831. <text x="60" y="248" class="title" style="font-size:16px;fill:var(--accent)">LLM 综合判断(skill 注入)</text>
  832. <rect x="60" y="258" width="560" height="52" class="layer-existing" rx="2"/>
  833. <text x="76" y="276" class="body-strong">调控:skills/decision_strategy.md</text>
  834. <text x="76" y="292" class="small">"任 X 项命中倾向触发" · 裂变 vs ROI 冲突 · reason 5 元组</text>
  835. <text x="76" y="306" class="small">→ 只注入 调控 Agent prompt</text>
  836. <rect x="640" y="258" width="560" height="52" class="layer-new" rx="2"/>
  837. <text x="656" y="276" class="body-strong" style="fill:var(--accent)">新建:skills/creation_strategy.md(新)</text>
  838. <text x="656" y="292" class="small">"任 4 项命中倾向触发" · 三路素材配比 · 出价 factor 选择</text>
  839. <text x="656" y="306" class="small" style="fill:var(--accent)">→ 只注入 新建 Agent prompt · 不污染调控</text>
  840. <!-- L3 lane -->
  841. <rect x="40" y="340" width="1180" height="130" class="layer-bg" rx="3"/>
  842. <rect x="56" y="332" width="180" height="20" fill="#B8902F" rx="2"/>
  843. <text x="146" y="346" class="pill-text" text-anchor="middle">L3 · HARDCODED GUARDS</text>
  844. <text x="60" y="376" class="mono-mute" style="fill:var(--gold)">代码层 · 确定性 · 边界硬约束 · 不可绕过</text>
  845. <text x="60" y="398" class="title" style="font-size:16px">兜底护栏</text>
  846. <rect x="60" y="408" width="560" height="52" class="layer-existing" rx="2"/>
  847. <text x="76" y="426" class="body-strong">调控:tools/guardrails.py(现有)</text>
  848. <text x="76" y="442" class="small" style="font-family:var(--mono);font-size:10.5px">BID_FLOOR/CEILING · MAX_ADJUSTMENTS_PER_AD_PER_DAY · 数据新鲜度</text>
  849. <text x="76" y="456" class="small">+ CreativePauseHistory 7 天去重</text>
  850. <rect x="640" y="408" width="560" height="52" class="layer-new" rx="2"/>
  851. <text x="656" y="426" class="body-strong" style="fill:var(--accent)">新建:guardrails 扩展 + creation_history(新)</text>
  852. <text x="656" y="442" class="small" style="font-family:var(--mono);font-size:10.5px">MAX_NEW_ADS_PER_TIER_PER_7D · uniqueness_check · 创意数上限</text>
  853. <text x="656" y="456" class="small" style="fill:var(--accent)">+ CreativeAddHistory · AdCreationHistory(深度补全:7 日累计)</text>
  854. </svg>
  855. </div>
  856. <!-- ════════════════════════════════════════════════════ -->
  857. <!-- FIGURE 6 · 关联点放大图(时间序) -->
  858. <!-- ════════════════════════════════════════════════════ -->
  859. <h2>图六 · 关联点放大 — 时序图</h2>
  860. <div class="diagram-wrap" data-tag="FIG · 06 · COUPLING POINT · TIME SEQUENCE">
  861. <svg class="arch" viewBox="0 0 1260 380" xmlns="http://www.w3.org/2000/svg">
  862. <defs>
  863. <marker id="arr-int6" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="5" markerHeight="5" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#0F1F2E"/></marker>
  864. <marker id="arr-cpl6" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto"><path d="M 0 0 L 10 5 L 0 10 z" fill="#B8902F"/></marker>
  865. </defs>
  866. <!-- Timeline -->
  867. <line x1="80" y1="60" x2="1180" y2="60" stroke="#0F1F2E" stroke-width="1.5"/>
  868. <text x="80" y="44" class="mono-mute">UTC 02:00</text>
  869. <text x="600" y="44" class="mono-mute" text-anchor="middle">UTC 02:30</text>
  870. <text x="1180" y="44" class="mono-mute" text-anchor="end">UTC 04:00+</text>
  871. <circle cx="80" cy="60" r="6" fill="#4A5870"/>
  872. <circle cx="600" cy="60" r="6" fill="#C75D3F"/>
  873. <circle cx="1180" cy="60" r="6" fill="#0F1F2E"/>
  874. <!-- 调控 swimlane -->
  875. <rect x="40" y="100" width="1180" height="100" class="layer-existing" rx="3"/>
  876. <text x="60" y="122" class="mono-mute">ADJUSTMENT LANE · 调控子系统</text>
  877. <rect x="80" y="140" width="200" height="42" class="layer-bg" rx="2"/>
  878. <text x="92" y="158" class="body-strong" style="font-size:12px">execute_once.py</text>
  879. <text x="92" y="174" class="small">数据→决策→审批→执行</text>
  880. <rect x="290" y="140" width="320" height="42" class="layer-bg" rx="2"/>
  881. <text x="302" y="158" class="body" style="font-size:11.5px">02:30 之前:产物落地</text>
  882. <text x="302" y="174" class="small" style="font-family:var(--mono);font-size:10.5px">outputs/reports/llm_decisions_{date}.csv</text>
  883. <rect x="620" y="140" width="560" height="42" class="layer-bg" rx="2" style="stroke-dasharray:2 4"/>
  884. <text x="632" y="158" class="body" style="font-size:11.5px;fill:var(--ink-mute)">飞书审批进行中(120 min 阻塞 · 与新建并行)</text>
  885. <text x="632" y="174" class="small" style="font-style:italic">审批通过后执行 · 此期间不影响新建子系统启动</text>
  886. <!-- 新建 swimlane -->
  887. <rect x="40" y="220" width="1180" height="140" class="layer-new" rx="3"/>
  888. <text x="60" y="242" class="mono-mute" style="fill:var(--accent)">CREATION LANE · 新建子系统</text>
  889. <rect x="600" y="260" width="200" height="42" class="layer-bg" rx="2" style="stroke:var(--accent)"/>
  890. <text x="612" y="278" class="body-strong" style="font-size:12px;fill:var(--accent)">execute_creation_once.py</text>
  891. <text x="612" y="294" class="small">02:30 启动</text>
  892. <rect x="600" y="312" width="580" height="42" class="layer-bg" rx="2" style="stroke:var(--gold);stroke-width:1.5"/>
  893. <text x="612" y="330" class="body-strong" style="font-size:11.5px;fill:var(--gold)">Step 1 · 读调控 latest_decisions</text>
  894. <text x="612" y="346" class="small" style="font-family:var(--mono);font-size:10.5px">excluded_ad_ids = {ad_id where action=='pause' in llm_decisions_{date}.csv}</text>
  895. <!-- 关联点箭头(调控 → 新建)-->
  896. <path class="arrow-coupling" d="M 380 200 C 380 235 480 220 600 330" marker-end="url(#arr-cpl6)"/>
  897. <text x="430" y="218" class="arrow-label" style="fill:var(--gold)">latest_decisions(只读)</text>
  898. <!-- 注释:之后新建跑完自己的流水线 -->
  899. <text x="810" y="285" class="body" style="font-size:11.5px">→ 候选标记(7 信号)→ LLM 决策 → 唯一性校验 → 飞书新建审批表 → ad_create / creative_create</text>
  900. </svg>
  901. </div>
  902. <!-- ════════════════════════════════════════════════════ -->
  903. <!-- FIGURE 7 · 实施甘特图 -->
  904. <!-- ════════════════════════════════════════════════════ -->
  905. <h2>图七 · 实施甘特图(10 阶段)</h2>
  906. <div class="table-wrap" data-tag="FIG · 07 · IMPLEMENTATION ROADMAP">
  907. <table class="matrix">
  908. <colgroup>
  909. <col style="width:48px"/>
  910. <col style="width:130px"/>
  911. <col style="width:auto"/>
  912. <col style="width:280px"/>
  913. <col style="width:80px"/>
  914. </colgroup>
  915. <thead>
  916. <tr><th>阶</th><th>名称</th><th>内容</th><th>关键产出</th><th>类别</th></tr>
  917. </thead>
  918. <tbody>
  919. <tr><td class="mono">a</td><td>共享 infra 抽取</td><td>im_approval.py 抽 FeishuApprovalBase · execution_engine 抽公共部分 · config.py 拆 [SHARED]/[ADJUSTMENT]/[CREATION] 三段</td><td class="mono">FeishuApprovalBase · config 重排</td><td class="shared">共享</td></tr>
  920. <tr><td class="mono">b</td><td>适配层 stub</td><td>5 个适配模块接口签名:audience_demand · material_recall · dedup_check · uniqueness_check · creation_history</td><td class="mono">5 个新文件 + 单测</td><td class="new">新建</td></tr>
  921. <tr><td class="mono">c</td><td>模块 A 内核</td><td>ad_creation.py 真实化:唯一性预校验 + 出价基准三层 + 命名 + ad_api.ad_create() 调用</td><td class="mono">tools/ad_creation.py</td><td class="new">新建</td></tr>
  922. <tr><td class="mono">d</td><td>模块 B 内核</td><td>creative_creation.py 真实化:三路召回(history 路先做)+ AI 改写(light)+ 渐进式控制 + ad_api.creative_create()</td><td class="mono">tools/creative_creation.py</td><td class="new">新建</td></tr>
  923. <tr><td class="mono">e</td><td>新建 Agent 框架</td><td>prompts/system_creation.prompt + skills/creation_strategy.md + creation_decision.py 候选标记 + 工具白名单</td><td class="mono">prompt + skill + L1 标记代码</td><td class="new">新建</td></tr>
  924. <tr><td class="mono">f</td><td>新建子系统入口</td><td>execute_creation_once.py 完整流水线:关联点过滤 → Agent → 决策落地 → 审批发送</td><td class="mono">execute_creation_once.py</td><td class="new">新建</td></tr>
  925. <tr><td class="mono">g</td><td>飞书审批扩展</td><td>FeishuCreationApproval 子类 · 新 chat_id 配置 · 新 APPROVAL_COLUMNS</td><td class="mono">tools/im_approval.py 重构</td><td class="shared">共享</td></tr>
  926. <tr><td class="mono">h</td><td>执行 dispatch</td><td>execution_engine 加 _execute_create_ad() · _execute_add_creative()(新建独占)</td><td class="mono">execution_engine 新分支</td><td class="new">新建</td></tr>
  927. <tr><td class="mono">i</td><td>端到端 + 关联点验证</td><td>execution_enabled=true · 单一测试账户跑 · 验证唯一性 / 创意数 / 关联点过滤 / 调控不受影响</td><td class="mono">回归测试 + 手工 checklist</td><td class="muted">验证</td></tr>
  928. <tr><td class="mono">j</td><td>K8s + 文档</td><td>k8s/cronjob_creation.yaml · 更新 CLAUDE.md · 监控告警</td><td class="mono">cronjob 上线 · 稳定跑 1 周</td><td class="muted">交付</td></tr>
  929. </tbody>
  930. </table>
  931. <div style="margin-top:24px">
  932. <h3>阶段甘特(相对工作量,水平比例示意)</h3>
  933. <div style="display:grid;grid-template-columns:60px 1fr;gap:6px;align-items:center;margin-top:8px">
  934. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 a</span>
  935. <div class="gantt-bar"><div class="gantt-fill shared-bar" style="left:0%;width:12%">a · 抽 infra</div></div>
  936. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 b</span>
  937. <div class="gantt-bar"><div class="gantt-fill" style="left:10%;width:8%">b · stub</div></div>
  938. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 c</span>
  939. <div class="gantt-bar"><div class="gantt-fill" style="left:18%;width:18%">c · 模块 A</div></div>
  940. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 d</span>
  941. <div class="gantt-bar"><div class="gantt-fill" style="left:25%;width:20%">d · 模块 B</div></div>
  942. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 e</span>
  943. <div class="gantt-bar"><div class="gantt-fill" style="left:38%;width:14%">e · Agent 框架</div></div>
  944. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 f</span>
  945. <div class="gantt-bar"><div class="gantt-fill" style="left:50%;width:14%">f · 子系统入口</div></div>
  946. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 g</span>
  947. <div class="gantt-bar"><div class="gantt-fill shared-bar" style="left:55%;width:10%">g · 飞书</div></div>
  948. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 h</span>
  949. <div class="gantt-bar"><div class="gantt-fill" style="left:64%;width:10%">h · execute</div></div>
  950. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 i</span>
  951. <div class="gantt-bar"><div class="gantt-fill cross-bar" style="left:74%;width:14%">i · e2e 验证</div></div>
  952. <span class="mono" style="font-size:11px;color:var(--ink-mute)">阶 j</span>
  953. <div class="gantt-bar"><div class="gantt-fill cross-bar" style="left:86%;width:14%">j · K8s + 文档</div></div>
  954. </div>
  955. <div class="legend" style="margin-top:24px">
  956. <div class="legend-item"><span class="legend-line" style="border-color:var(--moss);border-top-style:solid"></span>共享 infra 改动(影响调控,需回归)</div>
  957. <div class="legend-item"><span class="legend-line act"></span>新建子系统独占改动</div>
  958. <div class="legend-item"><span class="legend-line" style="border-color:var(--gold);border-top-style:solid"></span>验证 / 交付</div>
  959. </div>
  960. </div>
  961. </div>
  962. <!-- ════════════════════════════════════════════════════ -->
  963. <!-- 关键设计原则速查 -->
  964. <!-- ════════════════════════════════════════════════════ -->
  965. <h2>设计原则速查</h2>
  966. <div class="table-wrap" data-tag="DESIGN PRINCIPLES">
  967. <table class="matrix">
  968. <colgroup><col style="width:280px"/><col style="width:auto"/></colgroup>
  969. <tbody>
  970. <tr><td class="new">代码 vs 知识 分离</td><td>工具 / 数据(代码)是<strong>确定性</strong>的,复用零风险;Skill(LLM 推理框架)是<strong>启发式</strong>的,共用会污染。Q5/Q6 改方向的核心理由。</td></tr>
  971. <tr><td class="new">分离但不盲</td><td>两个子系统通过文件系统通信,**最小耦合**:新建启动只读调控当日 latest_decisions 黑名单,避免给即将 pause 的广告补创意。</td></tr>
  972. <tr><td class="new">L1 / L2 / L3 三层分工</td><td>L1 候选标记(代码,可单测)/ L2 LLM skill(启发式)/ L3 兜底护栏(代码,边界)。两子系统共用这套分工模式。</td></tr>
  973. <tr><td class="new">YAGNI 严格执行</td><td>本期不做 reshuffle / 重度 AI 改写 / 跨账户素材 / 调控读新建 / 联合审批 / 学习期细粒度保护。接口预留,实现等下期。</td></tr>
  974. <tr><td class="new">深度思考补全(全启用)</td><td>tier 级护栏 · 渐进式挂创意(≤5/次)· 7 日累计上限 · 出价基准三层降级 · 关联点过滤 · confidence 量纲校准。</td></tr>
  975. <tr><td class="new">回滚边界清晰</td><td>新建子系统失败 → 删 execute_creation_once.py 即可;CREATION_ENABLED=False 总开关;调控完全不受影响。</td></tr>
  976. </tbody>
  977. </table>
  978. </div>
  979. <!-- ════════════════════════════════════════════════════ -->
  980. <footer>
  981. <div>auto_put_ad_mini · v2 解耦架构 · brain 独立 · infra 共享</div>
  982. <div class="stamp">drafted 2026-06-05 · plan approved · 待实施</div>
  983. </footer>
  984. </main>
  985. </body>
  986. </html>