1:"$Sreact.fragment" 2:I[56271,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],"ThemeProviders"] 3:I[41402,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],""] 4:I[91367,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],"KBarSearchProvider"] 5:I[52619,["2619","static/chunks/2619-eccd988d1e161df3.js","1356","static/chunks/1356-354ecf51aaaf5203.js","6909","static/chunks/app/blog/%5B...slug%5D/page-d416e20a09ba8ecb.js"],""] 6:I[51350,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],"KBarButton"] 10:I[57150,[],""] :HL["/_next/static/css/29ff447a95e95257.css","style"] :HL["/_next/static/css/77af622156c5e021.css","style"] :HL["/_next/static/css/ddf3d904beac0ed7.css","style"] 0:{"P":null,"b":"FUTryh0Sm2lrVLTvF5oMH","p":"","c":["","blog","mpt-open-source-contribution-analysis"],"i":false,"f":[[["",{"children":["blog",{"children":[["slug","mpt-open-source-contribution-analysis","c"],{"children":["__PAGE__",{}]}]}]},"$undefined","$undefined",true],["",["$","$1","c",{"children":[[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/29ff447a95e95257.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}],["$","link","1",{"rel":"stylesheet","href":"/_next/static/css/77af622156c5e021.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","html",null,{"lang":"zh-cn","className":"scroll-smooth","suppressHydrationWarning":true,"children":[["$","link",null,{"rel":"apple-touch-icon","sizes":"76x76","href":"/static/favicons/apple-touch-icon.png"}],["$","link",null,{"rel":"icon","type":"image/png","sizes":"32x32","href":"/static/favicons/favicon-32x32.png"}],["$","link",null,{"rel":"icon","type":"image/png","sizes":"16x16","href":"/static/favicons/favicon-16x16.png"}],["$","link",null,{"rel":"manifest","href":"/static/favicons/site.webmanifest"}],["$","link",null,{"rel":"mask-icon","href":"/static/favicons/safari-pinned-tab.svg","color":"#5bbad5"}],["$","meta",null,{"name":"msapplication-TileColor","content":"#4f46e5"}],["$","meta",null,{"name":"theme-color","media":"(prefers-color-scheme: light)","content":"#ffffff"}],["$","meta",null,{"name":"theme-color","media":"(prefers-color-scheme: dark)","content":"#0f172a"}],["$","link",null,{"rel":"alternate","type":"application/rss+xml","href":"/feed.xml"}],["$","body",null,{"className":"bg-white pl-[calc(100vw-100%)] text-black antialiased dark:bg-gray-950 dark:text-white","children":["$","$L2",null,{"children":[["$undefined","$undefined","$undefined",["$","$L3",null,{"async":true,"defer":true,"src":"https://analytics.umami.is/script.js"}],"$undefined","$undefined"],["$","section",null,{"className":"mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0","children":[["$","$L4",null,{"kbarConfig":{"searchDocumentsPath":"/search.json"},"children":[["$","header",null,{"className":"flex items-center w-full bg-white dark:bg-gray-950 justify-between py-10","children":[["$","$L5",null,{"className":"break-words","href":"/","aria-label":"TechLog","children":["$","div",null,{"className":"flex items-center justify-between","children":[["$","div",null,{"className":"mr-3","children":["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","xmlnsXlink":"http://www.w3.org/1999/xlink","width":53.87,"height":43.61,"viewBox":"344.564 330.278 111.737 91.218","children":[["$","defs",null,{"children":[["$","linearGradient",null,{"id":"logo_svg__b","x1":420.97,"x2":420.97,"y1":331.28,"y2":418.5,"gradientUnits":"userSpaceOnUse","children":[["$","stop",null,{"offset":"0%","style":{"stopColor":"#06b6d4","stopOpacity":1}}],["$","stop",null,{"offset":"100%","style":{"stopColor":"#67e8f9","stopOpacity":1}}]]}],["$","linearGradient",null,{"id":"logo_svg__d","x1":377.89,"x2":377.89,"y1":331.28,"y2":418.5,"gradientUnits":"userSpaceOnUse","children":[["$","stop",null,{"offset":"0%","style":{"stopColor":"#06b6d4","stopOpacity":1}}],["$","stop",null,{"offset":"100%","style":{"stopColor":"#67e8f9","stopOpacity":1}}]]}],["$","path",null,{"id":"logo_svg__a","d":"M453.3 331.28v28.57l-64.66 58.65v-30.08z"}],["$","path",null,{"id":"logo_svg__c","d":"M410.23 331.28v28.57l-64.67 58.65v-30.08z"}]]}],["$","use",null,{"xlinkHref":"#logo_svg__a","fill":"url(#logo_svg__b)"}],["$","use",null,{"xlinkHref":"#logo_svg__c","fill":"url(#logo_svg__d)"}]]}]}],["$","div",null,{"className":"hidden h-6 text-2xl font-semibold sm:block","children":"TechLog"}]]}]}],["$","div",null,{"className":"flex items-center space-x-4 leading-5 sm:-mr-6 sm:space-x-6","children":[["$","div",null,{"className":"no-scrollbar hidden max-w-40 items-center gap-x-4 overflow-x-auto sm:flex md:max-w-72 lg:max-w-96","children":[["$","$L5","博客",{"className":"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100","href":"/blog.html","children":"博客"}],["$","$L5","标签",{"className":"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100","href":"/tags.html","children":"标签"}],["$","$L5","项目",{"className":"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100","href":"/projects.html","children":"项目"}],["$","$L5","关于",{"className":"hover:text-primary-500 dark:hover:text-primary-400 m-1 font-medium text-gray-900 dark:text-gray-100","href":"/about.html","children":"关于"}]]}],["$","$L6",null,{"aria-label":"Search","children":"$L7"}],"$L8","$L9"]}]]}],"$La"]}],"$Lb"]}]]}]}]]}]]}],{"children":["blog","$Lc",{"children":[["slug","mpt-open-source-contribution-analysis","c"],"$Ld",{"children":["__PAGE__","$Le",{},null,false]},null,false]},null,false]},null,false],"$Lf",false]],"m":"$undefined","G":["$10",[]],"s":false,"S":true} 11:I[49217,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],"default"] 12:I[394,["2545","static/chunks/c16f53c3-391a1f5a73546b11.js","2619","static/chunks/2619-eccd988d1e161df3.js","3353","static/chunks/3353-35c19838f8cf7b3b.js","7177","static/chunks/app/layout-cb4429a7e3e88a9f.js"],"default"] 13:I[9766,[],""] 14:I[98924,[],""] 16:I[24431,[],"OutletBoundary"] 18:I[15278,[],"AsyncMetadataOutlet"] 1a:I[24431,[],"ViewportBoundary"] 1c:I[24431,[],"MetadataBoundary"] 1d:"$Sreact.suspense" 7:["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","fill":"none","viewBox":"0 0 24 24","strokeWidth":1.5,"stroke":"currentColor","className":"hover:text-primary-500 dark:hover:text-primary-400 h-6 w-6 text-gray-900 dark:text-gray-100","children":["$","path",null,{"strokeLinecap":"round","strokeLinejoin":"round","d":"M21 21l-5.197-5.197m0 0A7.5 7.5 0 105.196 5.196a7.5 7.5 0 0010.607 10.607z"}]}] 8:["$","$L11",null,{}] 9:["$","$L12",null,{}] a:["$","main",null,{"className":"mb-auto","children":["$","$L13",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L14",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":[["$","div",null,{"className":"flex flex-col items-start justify-start md:mt-24 md:flex-row md:items-center md:justify-center md:space-x-6","children":[["$","div",null,{"className":"space-x-2 pt-6 pb-8 md:space-y-5","children":["$","h1",null,{"className":"text-6xl leading-9 font-extrabold tracking-tight text-gray-900 md:border-r-2 md:px-6 md:text-8xl md:leading-14 dark:text-gray-100","children":"404"}]}],["$","div",null,{"className":"max-w-md","children":[["$","p",null,{"className":"mb-4 text-xl leading-normal font-bold md:text-2xl","children":"Sorry we couldn't find this page."}],["$","p",null,{"className":"mb-8","children":"But dont worry, you can find plenty of other things on our homepage."}],["$","$L5",null,{"className":"focus:shadow-outline-blue inline rounded-lg border border-transparent bg-blue-600 px-4 py-2 text-sm leading-5 font-medium text-white shadow-xs transition-colors duration-150 hover:bg-blue-700 focus:outline-hidden dark:hover:bg-blue-500","href":"/","children":"Back to homepage"}]]}]]}],[]],"forbidden":"$undefined","unauthorized":"$undefined"}]}] b:["$","footer",null,{"children":["$","div",null,{"className":"mt-16 flex flex-col items-center","children":[["$","div",null,{"className":"mb-3 flex space-x-4","children":[["$","a",null,{"className":"text-sm text-gray-500 transition hover:text-gray-600","target":"_blank","rel":"noopener noreferrer","href":"mailto:birenwenmou@qq.com","children":[["$","span",null,{"className":"sr-only","children":"mail"}],["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","viewBox":"0 0 20 20","className":"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6","children":[["$","title",null,{"children":"Mail"}],["$","path",null,{"d":"M2.003 5.884L10 9.882l7.997-3.998A2 2 0 0016 4H4a2 2 0 00-1.997 1.884z"}],["$","path",null,{"d":"M18 8.118l-8 4-8-4V14a2 2 0 002 2h12a2 2 0 002-2V8.118z"}]]}]]}],["$","a",null,{"className":"text-sm text-gray-500 transition hover:text-gray-600","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/joker1point","children":[["$","span",null,{"className":"sr-only","children":"github"}],["$","svg",null,{"xmlns":"http://www.w3.org/2000/svg","viewBox":"0 0 24 24","className":"hover:text-primary-500 dark:hover:text-primary-400 fill-current text-gray-700 dark:text-gray-200 h-6 w-6","children":[["$","title",null,{"children":"GitHub"}],["$","path",null,{"d":"M12 .297c-6.63 0-12 5.373-12 12 0 5.303 3.438 9.8 8.205 11.385.6.113.82-.258.82-.577 0-.285-.01-1.04-.015-2.04-3.338.724-4.042-1.61-4.042-1.61C4.422 18.07 3.633 17.7 3.633 17.7c-1.087-.744.084-.729.084-.729 1.205.084 1.838 1.236 1.838 1.236 1.07 1.835 2.809 1.305 3.495.998.108-.776.417-1.305.76-1.605-2.665-.3-5.466-1.332-5.466-5.93 0-1.31.465-2.38 1.235-3.22-.135-.303-.54-1.523.105-3.176 0 0 1.005-.322 3.3 1.23.96-.267 1.98-.399 3-.405 1.02.006 2.04.138 3 .405 2.28-1.552 3.285-1.23 3.285-1.23.645 1.653.24 2.873.12 3.176.765.84 1.23 1.91 1.23 3.22 0 4.61-2.805 5.625-5.475 5.92.42.36.81 1.096.81 2.22 0 1.606-.015 2.896-.015 3.286 0 .315.21.69.825.57C20.565 22.092 24 17.592 24 12.297c0-6.627-5.373-12-12-12"}]]}]]}],null,null,null,null,null,null,null,null,null]}],["$","div",null,{"className":"mb-2 flex space-x-2 text-sm text-gray-500 dark:text-gray-400","children":[["$","div",null,{"children":"眠月"}],["$","div",null,{"children":" • "}],["$","div",null,{"children":"© 2026"}],["$","div",null,{"children":" • "}],["$","$L5",null,{"className":"break-words","href":"/","children":"TechLog"}]]}],["$","div",null,{"className":"mb-8 text-sm text-gray-500 dark:text-gray-400","children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/joker1point","children":"GitHub"}]}]]}]}] c:["$","$1","c",{"children":[null,["$","$L13",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L14",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}] d:["$","$1","c",{"children":[null,["$","$L13",null,{"parallelRouterKey":"children","error":"$undefined","errorStyles":"$undefined","errorScripts":"$undefined","template":["$","$L14",null,{}],"templateStyles":"$undefined","templateScripts":"$undefined","notFound":"$undefined","forbidden":"$undefined","unauthorized":"$undefined"}]]}] e:["$","$1","c",{"children":["$L15",[["$","link","0",{"rel":"stylesheet","href":"/_next/static/css/ddf3d904beac0ed7.css","precedence":"next","crossOrigin":"$undefined","nonce":"$undefined"}]],["$","$L16",null,{"children":["$L17",["$","$L18",null,{"promise":"$@19"}]]}]]}] f:["$","$1","h",{"children":[null,[["$","$L1a",null,{"children":"$L1b"}],null],["$","$L1c",null,{"children":["$","div",null,{"hidden":true,"children":["$","$1d",null,{"fallback":null,"children":"$L1e"}]}]}]]}] 1f:I[62088,["2619","static/chunks/2619-eccd988d1e161df3.js","1356","static/chunks/1356-354ecf51aaaf5203.js","6909","static/chunks/app/blog/%5B...slug%5D/page-d416e20a09ba8ecb.js"],"default"] 20:I[81356,["2619","static/chunks/2619-eccd988d1e161df3.js","1356","static/chunks/1356-354ecf51aaaf5203.js","6909","static/chunks/app/blog/%5B...slug%5D/page-d416e20a09ba8ecb.js"],"Image"] 15:[["$","script",null,{"type":"application/ld+json","dangerouslySetInnerHTML":{"__html":"{\"@context\":\"https://schema.org\",\"@type\":\"BlogPosting\",\"headline\":\"如何给一个陌生开源项目做架构分析,并找到能合进去的贡献点\",\"datePublished\":\"2026-09-15T00:00:00.000Z\",\"dateModified\":\"2026-09-15T00:00:00.000Z\",\"description\":\"以 MoneyPrinterTurbo 为例,按 7 个维度(任务规划、多 Agent 协作、上下文管理、Human-in-the-loop、评估框架、工具路由、Streaming)系统拆解一个陌生项目的架构缺陷,从中筛出 Top 3 贡献方向,并给出方案骨架与给维护者的英文沟通草稿。\",\"image\":\"/static/images/twitter-card.png\",\"url\":\"https://techlog-18328.app.workbuddy.host/blog/mpt-open-source-contribution-analysis\",\"author\":[{\"@type\":\"Person\",\"name\":\"眠月\"}]}"}}],["$","section",null,{"className":"mx-auto max-w-3xl px-4 sm:px-6 xl:max-w-5xl xl:px-0","children":[["$","$L1f",null,{}],["$","article",null,{"children":["$","div",null,{"className":"xl:divide-y xl:divide-gray-200 xl:dark:divide-gray-700","children":[["$","header",null,{"className":"pt-6 xl:pb-6","children":["$","div",null,{"className":"space-y-1 text-center","children":[["$","dl",null,{"className":"space-y-10","children":[["$","div",null,{"children":[["$","dt",null,{"className":"sr-only","children":"Published on"}],["$","dd",null,{"className":"text-base leading-6 font-medium text-gray-500 dark:text-gray-400","children":["$","time",null,{"dateTime":"2026-09-15T00:00:00.000Z","children":"2026年9月15日星期二"}]}]]}],["$","div",null,{"children":[["$","dt",null,{"className":"sr-only","children":"Word count"}],["$","dd",null,{"className":"text-sm text-gray-400 dark:text-gray-500","children":["3,861"," 字"," · 阅读约 14 分钟"]}]]}]]}],["$","div",null,{"children":["$","h1",null,{"className":"text-3xl leading-9 font-extrabold tracking-tight text-gray-900 sm:text-4xl sm:leading-10 md:text-5xl md:leading-14 dark:text-gray-100","children":"如何给一个陌生开源项目做架构分析,并找到能合进去的贡献点"}]}]]}]}],["$","div",null,{"className":"grid-rows-[auto_1fr] divide-y divide-gray-200 pb-8 xl:grid xl:grid-cols-4 xl:gap-x-6 xl:divide-y-0 dark:divide-gray-700","children":[["$","dl",null,{"className":"pt-6 pb-10 xl:border-b xl:border-gray-200 xl:pt-11 xl:dark:border-gray-700","children":[["$","dt",null,{"className":"sr-only","children":"Authors"}],["$","dd",null,{"children":["$","ul",null,{"className":"flex flex-wrap justify-center gap-4 sm:space-x-12 xl:block xl:space-y-8 xl:space-x-0","children":[["$","li","眠月",{"className":"flex items-center space-x-2","children":[["$","$L20",null,{"src":"/static/images/avatar.png","width":38,"height":38,"alt":"avatar","className":"h-10 w-10 rounded-full"}],["$","dl",null,{"className":"text-sm leading-5 font-medium whitespace-nowrap","children":[["$","dt",null,{"className":"sr-only","children":"Name"}],["$","dd",null,{"className":"text-gray-900 dark:text-gray-100","children":"眠月"}],["$","dt",null,{"className":"sr-only","children":"Twitter"}],["$","dd",null,{"children":""}]]}]]}]]}]}]]}],["$","div",null,{"className":"divide-y divide-gray-200 xl:col-span-3 xl:row-span-2 xl:pb-0 dark:divide-gray-700","children":[["$","div",null,{"className":"prose dark:prose-invert max-w-none pt-10 pb-8","children":[["$","h3",null,{"className":"content-header","id":"top-3-贡献方向-任务断点续跑checkpointresume-官方-mcp-server--issue-1157-批量脚本去重前两者来自架构分析第三个是-23-天可合入的信任建立型-pr","children":[["$","a",null,{"className":"break-words","href":"#top-3-贡献方向-任务断点续跑checkpointresume-官方-mcp-server--issue-1157-批量脚本去重前两者来自架构分析第三个是-23-天可合入的信任建立型-pr","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"$L21"]}],"$L22","$L23","$L24","$L25","$L26","$L27","$L28","$L29","$L2a","$L2b","$L2c","$L2d","$L2e","$L2f","$L30","$L31","$L32","$L33","$L34","$L35","$L36","$L37","$L38","$L39","$L3a","$L3b","$L3c","$L3d","$L3e","$L3f","$L40","$L41","$L42","$L43","$L44","$L45","$L46","$L47","$L48","$L49","$L4a","$L4b","$L4c","$L4d","$L4e","$L4f","$L50","$L51","$L52","$L53","$L54","$L55","$L56","$L57","$L58","$L59","$L5a","$L5b","$L5c","$L5d","$L5e","$L5f","$L60","$L61","$L62","$L63","$L64","$L65","$L66","$L67","$L68","$L69","$L6a","$L6b","$L6c","$L6d","$L6e","$L6f","$L70","$L71"]}],"$L72","$L73"]}],"$L74"]}]]}]}]]}]] 75:I[16991,["2619","static/chunks/2619-eccd988d1e161df3.js","1356","static/chunks/1356-354ecf51aaaf5203.js","6909","static/chunks/app/blog/%5B...slug%5D/page-d416e20a09ba8ecb.js"],"default"] 83:I[50528,["2619","static/chunks/2619-eccd988d1e161df3.js","1356","static/chunks/1356-354ecf51aaaf5203.js","6909","static/chunks/app/blog/%5B...slug%5D/page-d416e20a09ba8ecb.js"],"default"] 21:["$","strong",null,{"children":"Top 3 贡献方向:① 任务断点续跑(Checkpoint/Resume)② 官方 MCP Server ③ Issue #1157 批量脚本去重;前两者来自架构分析,第三个是 2~3 天可合入的信任建立型 PR"}] 22:["$","p",null,{"children":"当前项目是 harry0703/MoneyPrinterTurbo(10 万+ stars 的 AI 短视频自动生成工具)。"}] 23:["$","hr",null,{}] 24:["$","h2",null,{"className":"content-header","id":"准备工作项目理解","children":[["$","a",null,{"className":"break-words","href":"#准备工作项目理解","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"准备工作:项目理解"]}] 25:["$","h3",null,{"className":"content-header","id":"目录结构depth3-为核心模块","children":[["$","a",null,{"className":"break-words","href":"#目录结构depth3-为核心模块","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"目录结构(depth=3,★ 为核心模块)"]}] 26:["$","$L75",null,{"className":"language-js","children":["$","code",null,{"className":"language-js code-highlight","children":[["$","span",null,{"className":"code-line","children":[["$","span",null,{"className":"token maybe-class-name","children":"MoneyPrinterTurbo"}],["$","span",null,{"className":"token operator","children":"/"}],"\n"]}],["$","span",null,{"className":"code-line","children":["├── main",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token constant","children":"API"}]," 服务启动入口\n"]}],["$","span",null,{"className":"code-line","children":["├── webui",["$","span",null,{"className":"token operator","children":"/"}],"\n"]}],["$","span",null,{"className":"code-line","children":["│ └── ",["$","span",null,{"className":"token maybe-class-name","children":"Main"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token maybe-class-name","children":"Streamlit"}]," ",["$","span",null,{"className":"token maybe-class-name","children":"WebUI"}]," 入口(",["$","span",null,{"className":"token number","children":"1500"}],["$","span",null,{"className":"token operator","children":"+"}]," 行单文件)\n"]}],["$","span",null,{"className":"code-line","children":["├── app",["$","span",null,{"className":"token operator","children":"/"}],"\n"]}],["$","span",null,{"className":"code-line","children":["│ ├── asgi",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," ",["$","span",null,{"className":"token operator","children":"/"}]," router",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token maybe-class-name","children":"FastAPI"}]," 装配与路由\n"]}],["$","span",null,{"className":"code-line","children":["│ ├── config",["$","span",null,{"className":"token operator","children":"/"}]," # config",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"toml"}]," 解析\n"]}],["$","span",null,{"className":"code-line","children":["│ ├── controllers",["$","span",null,{"className":"token operator","children":"/"}]," # ★ ",["$","span",null,{"className":"token constant","children":"API"}]," 层(v1",["$","span",null,{"className":"token operator","children":"/"}],"video",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py、llm"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py、music"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py)"}],"\n"]}],["$","span",null,{"className":"code-line","children":["│ ├── models",["$","span",null,{"className":"token operator","children":"/"}],"\n"]}],["$","span",null,{"className":"code-line","children":["│ │ ├── schema",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ★ ",["$","span",null,{"className":"token maybe-class-name","children":"VideoParams(Pydantic"}]," 请求模型)\n"]}],["$","span",null,{"className":"code-line","children":["│ │ ├── ",["$","span",null,{"className":"token keyword","children":"const"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ★ 任务状态常量(",["$","span",null,{"className":"token constant","children":"TASK_STATE_"}],["$","span",null,{"className":"token operator","children":"*"}],")\n"]}],["$","span",null,{"className":"code-line","children":["│ │ └── llm_provider",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ★ ",["$","span",null,{"className":"token number","children":"13"}],["$","span",null,{"className":"token operator","children":"+"}]," ",["$","span",null,{"className":"token constant","children":"LLM"}]," ",["$","span",null,{"className":"token maybe-class-name","children":"Provider"}]," 注册表\n"]}],["$","span",null,{"className":"code-line","children":["│ ├── services",["$","span",null,{"className":"token operator","children":"/"}]," # ★★★ 核心业务层\n"]}],"$L76","$L77","$L78","$L79","$L7a","$L7b","$L7c","$L7d","$L7e","$L7f","$L80","$L81","$L82"]}]}] 27:["$","h3",null,{"className":"content-header","id":"核心循环与规划范式","children":[["$","a",null,{"className":"break-words","href":"#核心循环与规划范式","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"核心循环与规划范式"]}] 28:["$","p",null,{"children":["这个项目",["$","strong",null,{"children":"没有 LLM Agent 循环"}],",而是一条硬编码的确定性流水线:",["$","code",null,{"children":"app/services/task.py"}]," 的 ",["$","code",null,{"children":"start()"}]," 顺序执行 脚本生成(llm)→ 关键词提取(llm)→ 素材下载(material)→ 语音合成(voice)→ 视频合成(video),每阶段更新 ",["$","code",null,{"children":"state.py"}]," 中的任务状态。规划范式是",["$","strong",null,{"children":["固定 Pipeline + ",["$","code",null,{"children":"stop_at"}]," 阶段截断检查点"]}],",LLM 只在两个节点作为\"单步工具\"被调用,无 ReAct、无动态重规划、无工具选择——这正是后面架构分析的价值所在。",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://deepwiki.com/harry0703/MoneyPrinterTurbo/5-core-services","children":"DeepWiki - Core Services"}]," ",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://deepwiki.com/harry0703/MoneyPrinterTurbo/5.1-task-orchestration","children":"DeepWiki - Task Orchestration"}]]}] 29:["$","hr",null,{}] 2a:["$","h2",null,{"className":"content-header","id":"分析维度一issue-列表筛选","children":[["$","a",null,{"className":"break-words","href":"#分析维度一issue-列表筛选","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"分析维度一:Issue 列表筛选"]}] 2b:["$","p",null,{"children":["当前仓库 Open Issue 仅 6 条(783 条已关闭),且全部只有 ",["$","code",null,{"children":"enhancement"}]," 标签——",["$","strong",null,{"children":["没有 ",["$","code",null,{"children":"good first issue"}]," / ",["$","code",null,{"children":"help wanted"}]," 标签可用"]}],",这本身说明该仓库 issue 卫生一般,也意味着\"代码分析维度\"比\"issue 维度\"更有产出空间。对现有 6 条逐一评估:"]}] 2c:["$","div",null,{"className":"w-full overflow-x-auto","children":["$","table",null,{"children":[["$","thead",null,{"children":["$","tr",null,{"children":[["$","th",null,{"children":"Issue"}],["$","th",null,{"children":"标题(类型)"}],["$","th",null,{"children":"所需技能"}],["$","th",null,{"children":"工作量"}],["$","th",null,{"children":"推荐理由"}]]}]}],["$","tbody",null,{"children":[["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1157","children":"#1157"}]}],["$","td",null,{"children":"批量生成多视频时脚本应不同"}],["$","td",null,{"children":"Python、LLM Prompt"}],["$","td",null,{"children":"小(2~3 天)"}],["$","td",null,{"children":["需求明确,改动集中在 ",["$","code",null,{"children":"llm.py"}]," + ",["$","code",null,{"children":"task.py"}]," 共 1~2 个文件,是理想的首个 PR"]}]]}],["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1205","children":"#1205"}]}],["$","td",null,{"children":"阿拉伯字体(RTL 支持)"}],["$","td",null,{"children":"Python、PIL、i18n"}],["$","td",null,{"children":"中(3~5 天)"}],["$","td",null,{"children":["12 条评论需求强烈、受益面广,涉及 ",["$","code",null,{"children":"subtitle.py"}]," 渲染链路,但 RTL 文本整形(arabic_reshaper + bidi)有一定踩坑成本"]}]]}],["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1183","children":"#1183"}]}],["$","td",null,{"children":"README 澄清视频生成机制"}],["$","td",null,{"children":"英文技术写作"}],["$","td",null,{"children":"小(1 天)"}],["$","td",null,{"children":"纯文档 PR,可作热身但面试价值低;23 条评论说明社区确有误解"}]]}],["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1280","children":"#1280"}]}],["$","td",null,{"children":"安装门槛太高"}],["$","td",null,{"children":"Docker、uv、打包"}],["$","td",null,{"children":"中"}],["$","td",null,{"children":"方向模糊(一键脚本?依赖瘦身?),需先在 issue 下与维护者对齐范围"}]]}],["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1274","children":"#1274"}]}],["$","td",null,{"children":"本地文生图/文生视频"}],["$","td",null,{"children":"模型集成(Diffusion)"}],["$","td",null,{"children":"大"}],["$","td",null,{"children":"架构级功能,远超 2 周与 300 行约束"}]]}],["$","tr",null,{"children":[["$","td",null,{"children":["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues/1256","children":"#1256"}]}],["$","td",null,{"children":"分镜板功能"}],["$","td",null,{"children":"全栈"}],["$","td",null,{"children":"大"}],["$","td",null,{"children":"新增子系统,超范围"}]]}]]}]]}]}] 2d:["$","p",null,{"children":["认领情况需注意:#1183 已有 23 条评论(很可能有人在做),#1205 有 12 条评论,动手前先通读评论区确认无人认领;#1157 仅 1 条评论且已开 27 天,是最干净的切入点。",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/harry0703/MoneyPrinterTurbo/issues","children":"GitHub Issues"}]]}] 2e:["$","hr",null,{}] 2f:["$","h2",null,{"className":"content-header","id":"分析维度二架构层缺陷分析","children":[["$","a",null,{"className":"break-words","href":"#分析维度二架构层缺陷分析","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"分析维度二:架构层缺陷分析"]}] 30:["$","h3",null,{"className":"content-header","id":"1-任务规划","children":[["$","a",null,{"className":"break-words","href":"#1-任务规划","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"1. 任务规划"]}] 31:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," ",["$","code",null,{"children":"app/services/task.py"}]," 的 ",["$","code",null,{"children":"start()"}]," 是唯一编排入口,5 阶段顺序执行,通过 ",["$","code",null,{"children":"stop_at"}]," 参数支持在脚本/音频阶段后截断(",["$","code",null,{"children":"task.py"}]," 210-340 行,",["$","code",null,{"children":"webui_task.py"}]," 122-156 行消费)。失败处理是 ",["$","code",null,{"children":"tm.start"}]," 内的 try-except:捕获后调 ",["$","code",null,{"children":"sm.state.update_task(TASK_STATE_FAILED)"}]," 记录 ",["$","code",null,{"children":"failed_stage"}]," 与错误信息后直接终止(",["$","code",null,{"children":"task.py"}]," 95-112 行)。唯一的重试逻辑在 LLM 层——",["$","code",null,{"children":"llm.py"}]," 的 ",["$","code",null,{"children":"_generate_response"}]," 最多重试 5 次。"]}] 32:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 无任何重规划或恢复机制——素材下载失败、TTS 返回 403、FFmpeg 崩溃任一环节失败,整个任务作废,已花费的 LLM token、已下载的素材、已合成的音频全部丢弃重来。",["$","code",null,{"children":"stop_at"}]," 只支持\"正向暂停\",不支持\"失败恢复\"。"]}] 33:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," high(社区高频抱怨点正是 TTS/合成阶段失败,一失败就是分钟级的沉没成本)"]}] 34:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 引入 stage-level checkpoint:每阶段产物(script、terms、audio、materials 清单)已在 ",["$","code",null,{"children":"storage/tasks/{id}/"}]," 落盘,只需增加\"阶段游标 + 产物有效性校验\",任务重试时跳过已完成阶段。"]}] 35:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 3",["$","del",null,{"children":["4 个文件(",["$","code",null,{"children":"task.py"}],"、",["$","code",null,{"children":"state.py"}],"、",["$","code",null,{"children":"schema.py"}],"、",["$","code",null,{"children":"controllers/v1/video.py"}],"),约 200"]}],"300 行"]}] 36:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," 长时任务的可靠性工程——状态机设计、幂等性、产物复用语义。"]}] 37:["$","h3",null,{"className":"content-header","id":"2-多-agent-协作","children":[["$","a",null,{"className":"break-words","href":"#2-多-agent-协作","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"2. 多 Agent 协作"]}] 38:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," 单编排器串行架构。仅有的并发点是 ",["$","code",null,{"children":"upload_post.py"}]," 的 ",["$","code",null,{"children":"_cross_post_executor"}],"(信号量控制的固定 2 worker 线程池,含 ",["$","code",null,{"children":"_is_cross_post_owner_alive"}]," 进程存活检测)和 ",["$","code",null,{"children":"webui_task.py"}]," 的 ",["$","code",null,{"children":"InMemoryTaskManager"}],"(并发硬编码为 1,保证 WebUI 会话配置一致性)。"]}] 39:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 脚本生成与素材检索天然可拆为 Orchestrator + Worker(脚本 Agent 分段 → 素材 Worker 并行按段检索 → 聚合),目前是完全串行的一次性调用;无 Agent 间状态共享协议。"]}] 3a:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," medium"]}] 3b:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 短期可做低风险优化——",["$","code",null,{"children":"generate_terms"}]," 返回的关键词数组可并行下载素材;长期才考虑编排拆分。"]}] 3c:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 1",["$","del",null,{"children":"2 个文件,约 50"}],"100 行(仅并行化)"]}] 3d:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," 并发编排与吞吐优化,但叙事上不如方向 1/6 扎实。"]}] 3e:["$","h3",null,{"className":"content-header","id":"3-上下文管理策略","children":[["$","a",null,{"className":"break-words","href":"#3-上下文管理策略","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"3. 上下文管理策略"]}] 3f:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," ",["$","code",null,{"children":"llm.py"}]," 的 ",["$","code",null,{"children":"generate_script"}]," / ",["$","code",null,{"children":"generate_terms"}]," 均为",["$","strong",null,{"children":"无状态单轮调用"}],"(系统提示 + 主题 + 语言参数),不存在对话历史累积,因此没有 token 上限管理问题。一个值得学习的细节:视频任务启动时传入 ",["$","code",null,{"children":"app_config"}]," 配置快照,保证任务运行中用户改全局配置不影响重试一致性(",["$","code",null,{"children":"llm.py"}]," 14-145 行)。"]}] 40:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 因为是 pipeline 而非对话 Agent,上下文管理基本不构成瓶颈;真正的缺陷是",["$","strong",null,{"children":"批量模式无跨调用上下文"}],"——",["$","code",null,{"children":"video_count > 1"}]," 时每个视频独立生成,互不知情,直接导致 Issue #1157 的\"脚本雷同\"问题。"]}] 41:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," low(本身)/ medium(与 #1157 结合时)"]}] 42:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 批量生成时注入\"前序脚本摘要\"作为去重约束,或按角度轮换提示词模板。"]}] 43:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 1 个文件(",["$","code",null,{"children":"llm.py"}],"),约 50~80 行"]}] 44:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," 批量 LLM 调用的多样性控制与成本意识。"]}] 45:["$","h3",null,{"className":"content-header","id":"4-human-in-the-loop-机制","children":[["$","a",null,{"className":"break-words","href":"#4-human-in-the-loop-机制","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"4. Human-in-the-loop 机制"]}] 46:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," 已有半成品 HITL:",["$","code",null,{"children":"stop_at"}]," 参数允许流水线在脚本/音频阶段暂停,WebUI 用户审查编辑脚本文本后再继续合成(",["$","code",null,{"children":"webui_task.py"}]," 122-156 行);跨平台上传有进程存活检测防孤儿任务。"]}] 47:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 无正式 Checkpoint 持久化——暂停状态只存在于内存或 Redis,进程重启即丢;人工编辑后的脚本通过\"填回 Streamlit 表单\"这种非结构化方式回传,无 API 级的 review/resume 接口;失败后人工反馈无法融入续跑,只能整任务重开。"]}] 48:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," high"]}] 49:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 与维度 1 合并处理:",["$","code",null,{"children":"storage/tasks/{id}/"}]," 增加 ",["$","code",null,{"children":"checkpoint.json"}],"(阶段游标 + 产物路径 + 参数指纹),新增 ",["$","code",null,{"children":"POST /v1/tasks/{id}/resume"}]," 端点,人工可编辑已生成脚本后从音频阶段续跑。"]}] 4a:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 3",["$","del",null,{"children":"4 个文件,约 250"}],"350 行"]}] 4b:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," HITL 设计模式(review gate + resume)+ 断点续跑,是 7 个维度里最能体现 Agent 系统设计完整性的方向。"]}] 4c:["$","h3",null,{"className":"content-header","id":"5-agent-评估框架","children":[["$","a",null,{"className":"break-words","href":"#5-agent-评估框架","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"5. Agent 评估框架"]}] 4d:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," ",["$","code",null,{"children":"test/"}]," 目录有传统单元测试:",["$","code",null,{"children":"test_llm.py"}],"(验证 think 标签剥离、",["$","code",null,{"children":"_sanitize_error_message"}]," 凭据脱敏)、",["$","code",null,{"children":"test_subtitle.py"}],"(Levenshtein 距离对齐算法)、",["$","code",null,{"children":"test_voice.py"}],"(TTS 时序)。但全是确定性逻辑测试,",["$","strong",null,{"children":"无任何 LLM 输出质量评估"}],"——脚本是否偏题、长度是否匹配 ",["$","code",null,{"children":"video_duration"}],"、关键词的素材命中率,全部无度量、无 golden set、无 LangSmith 类集成。"]}] 4e:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 项目的核心卖点是\"AI 生成脚本\",但这个能力完全不可评估、不可回归。脚本超长导致 TTS 截断、关键词太抽象导致素材不匹配(社区高频抱怨),都是无评估机制导致的慢性问题。"]}] 4f:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," medium-high"]}] 50:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 最小可用 eval pipeline:离线 golden set(主题 → 期望要点/时长区间)+ LLM-as-judge 评分脚本 + 一个硬校验(脚本字数 × 语速 ≈ video_duration 的断言)。对主流程零侵入,纯新增目录。"]}] 51:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 新增 ",["$","code",null,{"children":"eval/"}]," 目录,2~3 个文件,约 150 行"]}] 52:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," LLM 系统的可观测性与量化评估——正好衔接你 LangChain.js/LangSmith 的经验。"]}] 53:["$","h3",null,{"className":"content-header","id":"6-tool-检索与路由","children":[["$","a",null,{"className":"break-words","href":"#6-tool-检索与路由","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"6. Tool 检索与路由"]}] 54:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," 全部路由是",["$","strong",null,{"children":"配置驱动 + 字符串匹配"}],",无 LLM 工具选择:LLM 层用 ",["$","code",null,{"children":"app/models/llm_provider.py"}]," 的 ",["$","code",null,{"children":"LLMProviderSpec"}]," 注册表管理 13+ Provider(",["$","code",null,{"children":"get_llm_provider"}]," 运行时解析,含废弃模型名迁移);TTS 层靠 voice_name 的前缀/后缀判断路由(",["$","code",null,{"children":"voice.py"}]," 205-245 行:",["$","code",null,{"children":"siliconflow:"}]," / ",["$","code",null,{"children":"gemini:"}]," / ",["$","code",null,{"children":"mimo:"}]," 前缀、",["$","code",null,{"children":"-V2"}]," 后缀);BGM 有 ",["$","code",null,{"children":"_VIDEO_MUSIC_PROVIDERS"}]," 注册表(",["$","code",null,{"children":"task.py"}]," 61-79 行)。"]}] 55:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," ",["$","strong",null,{"children":"不支持 MCP 协议"}],",也没有任何 tool-calling 能力——项目本身是一个\"被调用的工具\",而非\"调用工具的 Agent\"。TTS 路由的 if-else 前缀判断散落且新增 Provider 需改多处。"]}] 56:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," medium(对你是机会)"]}] 57:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," 官方 MCP Server——用 FastMCP 把 ",["$","code",null,{"children":"create_task"}]," / ",["$","code",null,{"children":"get_task"}]," / ",["$","code",null,{"children":"list_voices"}]," / ",["$","code",null,{"children":"generate_script"}]," 封装为标准 MCP tools,让 Claude、Cursor 等任意 MCP 客户端直接驱动视频生成流水线。主仓库代码零侵入。"]}] 58:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 新增 ",["$","code",null,{"children":"mcp/"}]," 目录约 250~300 行 + 文档"]}] 59:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," Agent 工具生态位思考与 tool schema 粒度设计——你的 MCP 集成经验在这里是降维打击。"]}] 5a:["$","h3",null,{"className":"content-header","id":"7-streaming-与中间状态可见性","children":[["$","a",null,{"className":"break-words","href":"#7-streaming-与中间状态可见性","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"7. Streaming 与中间状态可见性"]}] 5b:["$","p",null,{"children":[["$","strong",null,{"children":"现状描述:"}]," API 层是",["$","strong",null,{"children":"轮询模型"}],"——",["$","code",null,{"children":"POST /v1/create-task"}]," 后客户端反复 GET 任务结果接口查 state;WebUI 用 ",["$","code",null,{"children":"deque"}]," + Streamlit Fragments 周期性刷新进度(",["$","code",null,{"children":"webui_task.py"}]," 53-120 行)。无 SSE、无 WebSocket、无 token 级流式(脚本生成时 WebUI 同步阻塞等待)。"]}] 5c:["$","p",null,{"children":[["$","strong",null,{"children":"缺陷/缺失:"}]," 无事件订阅接口;阶段级中间状态(当前执行到哪个 stage、正在下载第几个素材、FFmpeg 进度)不对外暴露,前端只能拿到一个百分比。"]}] 5d:["$","p",null,{"children":[["$","strong",null,{"children":"影响程度:"}]," medium"]}] 5e:["$","p",null,{"children":[["$","strong",null,{"children":"改进方向:"}]," ",["$","code",null,{"children":"state.py"}]," 增加轻量事件总线(Redis 后端天然可用 pubsub),",["$","code",null,{"children":"controllers/v1/video.py"}]," 新增 SSE 端点 ",["$","code",null,{"children":"/v1/tasks/{id}/events"}],"。埋点只在现有 ",["$","code",null,{"children":"update_task"}]," 调用处,低侵入。"]}] 5f:["$","p",null,{"children":[["$","strong",null,{"children":"改动范围:"}]," 2",["$","del",null,{"children":"3 个文件,约 150"}],"250 行"]}] 60:["$","p",null,{"children":[["$","strong",null,{"children":"面试叙事角度:"}]," 事件驱动架构 + 你可用 React 技术栈做一个实时 dashboard demo,前后端叙事闭环。",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://deepwiki.com/harry0703/MoneyPrinterTurbo/3.2-multi-provider-architecture","children":"DeepWiki - Multi-Provider Architecture"}]," ",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://deepwiki.com/harry0703/MoneyPrinterTurbo/5.2-llm-integration","children":"DeepWiki - LLM Integration"}]," ",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://deepwiki.com/harry0703/MoneyPrinterTurbo/4.1-web-interface-(streamlit)","children":"DeepWiki - Web Interface"}]]}] 61:["$","hr",null,{}] 62:["$","h2",null,{"className":"content-header","id":"最终输出top-3-贡献建议","children":[["$","a",null,{"className":"break-words","href":"#最终输出top-3-贡献建议","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"最终输出:Top 3 贡献建议"]}] 63:["$","h3",null,{"className":"content-header","id":"第-1-名任务-checkpoint-与断点续跑机制","children":[["$","a",null,{"className":"break-words","href":"#第-1-名任务-checkpoint-与断点续跑机制","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"第 1 名:任务 Checkpoint 与断点续跑机制"]}] 64:["$","ul",null,{"children":[["$","li",null,{"children":[["$","strong",null,{"children":"一句话描述:"}]," 为 5 阶段流水线引入产物级持久化与 resume 能力,任务失败或暂停后从断点恢复,不再整链路重跑。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"来源维度:"}]," 代码分析-维度 4 + 维度 1"]}],["$","li",null,{"children":[["$","strong",null,{"children":"入口文件:"}]," ",["$","code",null,{"children":"app/services/task.py"}],"(",["$","code",null,{"children":"start()"}],")、",["$","code",null,{"children":"app/services/state.py"}],"、",["$","code",null,{"children":"app/models/schema.py"}],"、",["$","code",null,{"children":"app/controllers/v1/video.py"}]]}],["$","li",null,{"children":[["$","strong",null,{"children":"为什么适合我:"}]," 纯 Python、不碰模型层;核心是状态机与幂等设计,你 2 周内可交付 MVP(checkpoint 落盘 + resume 参数 + 3 类产物复用校验),且直接命中社区最高频的痛点(失败重来)。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"预计工作量:"}]," 中"]}],["$","li",null,{"children":[["$","strong",null,{"children":"面试中能讲什么:"}]," 长任务的可靠性设计——阶段游标 vs 全量重放、产物指纹校验(参数变了产物是否还有效)、幂等性边界、双后端(内存/Redis)一致性取舍。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"风险点:"}]," 产物复用语义需维护者认可(人工编辑过的脚本如何标记);需要兼容 WebUI 与 API 两条调用路径。"]}]]}] 65:["$","h3",null,{"className":"content-header","id":"第-2-名官方-mcp-server-集成","children":[["$","a",null,{"className":"break-words","href":"#第-2-名官方-mcp-server-集成","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"第 2 名:官方 MCP Server 集成"]}] 66:["$","ul",null,{"children":[["$","li",null,{"children":[["$","strong",null,{"children":"一句话描述:"}]," 用 FastMCP 把视频生成能力封装为标准 MCP tools(",["$","code",null,{"children":"create_task"}],"、",["$","code",null,{"children":"get_task"}],"、",["$","code",null,{"children":"list_voices"}],"、",["$","code",null,{"children":"generate_script"}],"),让 Claude/Cursor 等 Agent 客户端直接驱动本项目。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"来源维度:"}]," 代码分析-维度 6(同时呼应 Issue #1274 的\"本地化、Agent 化\"社区诉求)"]}],["$","li",null,{"children":[["$","strong",null,{"children":"入口文件:"}]," 新增 ",["$","code",null,{"children":"mcp/"}]," 目录,复用 ",["$","code",null,{"children":"app/services/"}]," 全部能力"]}],["$","li",null,{"children":[["$","strong",null,{"children":"为什么适合我:"}]," MCP 集成正是你的核心经验;这是三个方向中唯一\"人无我有\"的差异化贡献,且对主代码零侵入、PR 通过阻力小。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"预计工作量:"}]," 中(MVP 约 300 行)"]}],["$","li",null,{"children":[["$","strong",null,{"children":"面试中能讲什么:"}]," Agent 工具粒度设计(粗粒度一键生成 vs 细粒度分步 tool 的权衡)、MCP 协议细节、开源生态位判断——为什么一个视频工具值得成为 Agent 的一个 tool。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"风险点:"}]," 维护者可能倾向独立仓库而非主仓库集成,",["$","strong",null,{"children":"务必先开 Discussion 征求意见"}],";工具粒度若太粗会被质疑只是 API 换皮。"]}]]}] 67:["$","h3",null,{"className":"content-header","id":"第-3-名issue-1157-批量多视频脚本去重","children":[["$","a",null,{"className":"break-words","href":"#第-3-名issue-1157-批量多视频脚本去重","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"第 3 名:Issue #1157 批量多视频脚本去重"]}] 68:["$","ul",null,{"children":[["$","li",null,{"children":[["$","strong",null,{"children":"一句话描述:"}]," ",["$","code",null,{"children":"video_count > 1"}]," 时让每个视频拿到不同角度/结构的脚本,而非重复生成近似内容。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"来源维度:"}]," Issue #1157 + 代码分析-维度 3"]}],["$","li",null,{"children":[["$","strong",null,{"children":"入口文件:"}]," ",["$","code",null,{"children":"app/services/llm.py"}],"(",["$","code",null,{"children":"generate_script"}],")、",["$","code",null,{"children":"app/services/task.py"}],"(批量循环处)"]}],["$","li",null,{"children":[["$","strong",null,{"children":"为什么适合我:"}]," 2~3 天可完成并合入,是建立维护者信任的首个 PR;技术上覆盖 prompt 工程与批量 LLM 调用的多样性控制。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"预计工作量:"}]," 小"]}],["$","li",null,{"children":[["$","strong",null,{"children":"面试中能讲什么:"}]," 批量生成的去重策略对比(前序摘要注入 vs 角度轮换模板 vs 温度调节)、成本意识(N 次调用的 token 开销)。"]}],["$","li",null,{"children":[["$","strong",null,{"children":"风险点:"}]," 期望行为需先在 issue 下确认(\"不同\"是指完全不同主题还是同主题不同结构?);27 天无人认领但也无人回复,维护者活跃度存疑。"]}]]}] 69:["$","p",null,{"children":[["$","strong",null,{"children":"建议节奏:"}]," 第 1 周完成 #1157 合入建立信任 → 第 2 周主攻 Checkpoint PR,MCP 方向先发 Discussion 探维护者口风,作为长线第二贡献。",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://www.cnblogs.com/zhang-yd/p/20243084","children":"今日开源-MoneyPrinterTurbo 项目深度分析"}]," ",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://ghtrends.dev/harry0703/MoneyPrinterTurbo","children":"GhTrends.dev"}]]}] 6a:["$","hr",null,{}] 6b:["$","h2",null,{"className":"content-header","id":"附top-1-方向的技术方案骨架供你启动第二阶段","children":[["$","a",null,{"className":"break-words","href":"#附top-1-方向的技术方案骨架供你启动第二阶段","aria-hidden":"true","tabIndex":"-1","children":["$","span",null,{"className":"content-header-link","children":["$","svg",null,{"className":"h-5 linkicon w-5","fill":"currentColor","viewBox":"0 0 20 20","xmlns":"http://www.w3.org/2000/svg","children":[["$","path",null,{"d":"M12.232 4.232a2.5 2.5 0 0 1 3.536 3.536l-1.225 1.224a.75.75 0 0 0 1.061 1.06l1.224-1.224a4 4 0 0 0-5.656-5.656l-3 3a4 4 0 0 0 .225 5.865.75.75 0 0 0 .977-1.138 2.5 2.5 0 0 1-.142-3.667l3-3Z"}],["$","path",null,{"d":"M11.603 7.963a.75.75 0 0 0-.977 1.138 2.5 2.5 0 0 1 .142 3.667l-3 3a2.5 2.5 0 0 1-3.536-3.536l1.225-1.224a.75.75 0 0 0-1.061-1.06l-1.224 1.224a4 4 0 1 0 5.656 5.656l3-3a4 4 0 0 0-.225-5.865Z"}]]}]}]}],"附:Top 1 方向的技术方案骨架(供你启动第二阶段)"]}] 6c:["$","p",null,{"children":[["$","strong",null,{"children":"问题边界:"}]," 核心解决\"任务失败后从已完成阶段恢复\";不在范围内:跨进程分布式锁、素材内容级 diff、自动无限重试。成功标准:同一任务二次启动时,已完成阶段的 LLM/TTS 调用次数为零;约束:不改 ",["$","code",null,{"children":"VideoParams"}]," 公共字段语义,单 PR 控制在 300 行内。"]}] 6d:["$","p",null,{"children":[["$","strong",null,{"children":"两个候选方案对比:"}]," 方案 A 是",["$","strong",null,{"children":"隐式 checkpoint"}],"(resume 时扫描 ",["$","code",null,{"children":"storage/tasks/{id}/"}]," 下已有产物自动复用,",["$","code",null,{"children":"task.py"}]," 各阶段入口加\"产物存在则跳过\"判断)——侵入小但产物有效性靠隐式推断;方案 B 是",["$","strong",null,{"children":"显式 checkpoint"}],"(新增 ",["$","code",null,{"children":"checkpoint.json"}]," 记录阶段游标 + 参数指纹 hash,resume 时校验指纹决定复用哪些阶段)——多约 80 行但语义清晰、可测试。",["$","strong",null,{"children":"推荐方案 B"}],":参数指纹解决了\"用户改了配置但旧产物被错误复用\"的隐性 bug,且这正是面试中被追问时的加分点。"]}] 6e:["$","p",null,{"children":[["$","strong",null,{"children":"实现步骤:"}]," ① ",["$","code",null,{"children":"schema.py"}]," 增加 ",["$","code",null,{"children":"CheckpointData"}]," 模型 → ② ",["$","code",null,{"children":"task.py"}]," 各阶段完成时写游标(含产物路径 + 参数指纹)→ ③ ",["$","code",null,{"children":"start()"}]," 入口接收 ",["$","code",null,{"children":"resume_task_id"}],",逐阶段校验指纹后跳过 → ④ ",["$","code",null,{"children":"controllers/v1/video.py"}]," 暴露 resume 参数并透传 → ⑤ 单测覆盖\"指纹不匹配不复用\"\"跨阶段续跑\"两个核心用例。"]}] 6f:["$","p",null,{"children":["$","strong",null,{"children":"给维护者的英文评论草稿(发在 #1157 或新 Discussion):"}]}] 70:["$","blockquote",null,{"children":["$","p",null,{"children":["Hi, thanks for maintaining this great project. I noticed that when a task fails at a later stage (e.g. video composition or TTS), all previously generated artifacts (script, audio, materials) are discarded and the whole pipeline restarts — the ",["$","code",null,{"children":"failed_stage"}]," is recorded in task state but never used for recovery. I'd like to propose an opt-in ",["$","code",null,{"children":"resume"}]," mechanism: persist a per-stage checkpoint (artifact paths + params fingerprint) under ",["$","code",null,{"children":"storage/tasks/{id}/"}],", so a retried task can skip completed stages. It would touch ",["$","code",null,{"children":"app/services/task.py"}]," and ",["$","code",null,{"children":"state.py"}],", roughly 300 lines, no public API changes. Is this something you'd consider accepting? Happy to share a detailed design first."]}]}] 71:["$","p",null,{"children":"这段流程走完(issue 沟通 → 方案确认 → PR 拆分),你的面试叙事就有了完整闭环:从架构洞察、方案对比、社区协作到量化成果。"}] 72:["$","div",null,{"className":"pt-6 pb-6 text-sm text-gray-700 dark:text-gray-300","children":[["$","a",null,{"className":"break-words","target":"_blank","rel":"nofollow","href":"https://mobile.twitter.com/search?q=https%3A%2F%2Ftechlog-18328.app.workbuddy.host%2Fblog%2Fmpt-open-source-contribution-analysis","children":"Discuss on Twitter"}]," • ",["$","a",null,{"className":"break-words","target":"_blank","rel":"noopener noreferrer","href":"https://github.com/joker1point/techlog/blob/main/data/blog/mpt-open-source-contribution-analysis.mdx","children":"View on GitHub"}]]}] 73:["$","div",null,{"className":"pt-6 pb-6 text-center text-gray-700 dark:text-gray-300","id":"comment","children":["$","$L83",null,{"slug":"mpt-open-source-contribution-analysis"}]}] 74:["$","footer",null,{"children":[["$","div",null,{"className":"divide-gray-200 text-sm leading-5 font-medium xl:col-start-1 xl:row-start-2 xl:divide-y dark:divide-gray-700","children":[["$","div",null,{"className":"py-4 xl:py-8","children":[["$","h2",null,{"className":"text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400","children":"Tags"}],["$","div",null,{"className":"flex flex-wrap","children":[["$","$L5","open-source",{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase","href":"/tags/open-source.html","children":"open-source"}],["$","$L5","agent",{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase","href":"/tags/agent.html","children":"agent"}],["$","$L5","architecture",{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase","href":"/tags/architecture.html","children":"architecture"}],["$","$L5","python",{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400 mr-3 text-sm font-medium uppercase","href":"/tags/python.html","children":"python"}]]}]]}],["$","div",null,{"className":"flex justify-between py-4 xl:block xl:space-y-8 xl:py-8","children":[["$","div",null,{"children":[["$","h2",null,{"className":"text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400","children":"Previous Article"}],["$","div",null,{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400","children":["$","$L5",null,{"className":"break-words","href":"/blog/mpt-pr-1291-contribution-review.html","children":"给 119k star 项目提 PR:8 小时从评论到合并的完整复盘"}]}]]}],["$","div",null,{"children":[["$","h2",null,{"className":"text-xs tracking-wide text-gray-500 uppercase dark:text-gray-400","children":"Next Article"}],["$","div",null,{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400","children":["$","$L5",null,{"className":"break-words","href":"/blog/dev-lessons-skill-distillation.html","children":"把 22 篇项目文档蒸馏成一个可进化的全局技能"}]}]]}]]}]]}],["$","div",null,{"className":"pt-4 xl:pt-8","children":["$","$L5",null,{"className":"text-primary-500 hover:text-primary-600 dark:hover:text-primary-400","href":"/blog.html","aria-label":"Back to the blog","children":"← Back to the blog"}]}]]}] 76:["$","span",null,{"className":"code-line","children":["│ │ ├── task",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ★★★ ",["$","span",null,{"className":"token number","children":"5"}]," ",["$","span",null,{"className":"token function","children":"阶段流水线编排器(start"}],["$","span",null,{"className":"token punctuation","children":"("}],["$","span",null,{"className":"token punctuation","children":")"}],")\n"]}] 77:["$","span",null,{"className":"code-line","children":["│ │ ├── state",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # 任务状态存储(内存 ",["$","span",null,{"className":"token operator","children":"/"}]," ",["$","span",null,{"className":"token maybe-class-name","children":"Redis"}]," 双后端)\n"]}] 78:["$","span",null,{"className":"code-line","children":["│ │ ├── llm",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # 脚本生成 ",["$","span",null,{"className":"token operator","children":"+"}]," 关键词提取(多 ",["$","span",null,{"className":"token maybe-class-name","children":"Provider)"}],"\n"]}] 79:["$","span",null,{"className":"code-line","children":["│ │ ├── material",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # 素材检索下载(Pexels",["$","span",null,{"className":"token operator","children":"/"}],["$","span",null,{"className":"token maybe-class-name","children":"Pixabay)"}],"\n"]}] 7a:["$","span",null,{"className":"code-line","children":["│ │ ├── voice",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token constant","children":"TTS"}]," 路由(edge",["$","span",null,{"className":"token operator","children":"-"}],"tts",["$","span",null,{"className":"token operator","children":"/"}],["$","span",null,{"className":"token maybe-class-name","children":"Azure"}],["$","span",null,{"className":"token operator","children":"/"}],["$","span",null,{"className":"token maybe-class-name","children":"OpenAI…)"}],"\n"]}] 7b:["$","span",null,{"className":"code-line","children":["│ │ ├── video",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token maybe-class-name","children":"MoviePy"}]," ",["$","span",null,{"className":"token operator","children":"+"}]," ",["$","span",null,{"className":"token maybe-class-name","children":"FFmpeg"}]," 视频合成\n"]}] 7c:["$","span",null,{"className":"code-line","children":["│ │ ├── subtitle",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # faster",["$","span",null,{"className":"token operator","children":"-"}],"whisper 字幕 ",["$","span",null,{"className":"token operator","children":"+"}]," 对齐纠错\n"]}] 7d:["$","span",null,{"className":"code-line","children":["│ │ └── upload_post",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"py"}]," # ",["$","span",null,{"className":"token maybe-class-name","children":"TikTok"}],["$","span",null,{"className":"token operator","children":"/"}],["$","span",null,{"className":"token maybe-class-name","children":"Instagram"}]," 跨平台发布(线程池)\n"]}] 7e:["$","span",null,{"className":"code-line","children":["│ └── utils",["$","span",null,{"className":"token operator","children":"/"}],"\n"]}] 7f:["$","span",null,{"className":"code-line","children":["├── resource",["$","span",null,{"className":"token operator","children":"/"}]," # 字体、",["$","span",null,{"className":"token constant","children":"BGM"}],"、演示素材\n"]}] 80:["$","span",null,{"className":"code-line","children":["├── storage",["$","span",null,{"className":"token operator","children":"/"}]," # 任务产物目录(tasks",["$","span",null,{"className":"token operator","children":"/"}],["$","span",null,{"className":"token punctuation","children":"{"}],"task_id",["$","span",null,{"className":"token punctuation","children":"}"}],["$","span",null,{"className":"token operator","children":"/"}],")\n"]}] 81:["$","span",null,{"className":"code-line","children":["├── test",["$","span",null,{"className":"token operator","children":"/"}]," # 单元测试(test_llm",["$","span",null,{"className":"token operator","children":"/"}],"test_voice",["$","span",null,{"className":"token operator","children":"/"}],"test_subtitle…)\n"]}] 82:["$","span",null,{"className":"code-line","children":["└── config",["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"example"}],["$","span",null,{"className":"token punctuation","children":"."}],["$","span",null,{"className":"token property-access","children":"toml"}]," # 全部 ",["$","span",null,{"className":"token maybe-class-name","children":"Provider"}]," 配置模板\n"]}] 1b:[["$","meta","0",{"charSet":"utf-8"}],["$","meta","1",{"name":"viewport","content":"width=device-width, initial-scale=1"}]] 17:null 19:{"metadata":[["$","title","0",{"children":"如何给一个陌生开源项目做架构分析,并找到能合进去的贡献点 | TechLog"}],["$","meta","1",{"name":"description","content":"以 MoneyPrinterTurbo 为例,按 7 个维度(任务规划、多 Agent 协作、上下文管理、Human-in-the-loop、评估框架、工具路由、Streaming)系统拆解一个陌生项目的架构缺陷,从中筛出 Top 3 贡献方向,并给出方案骨架与给维护者的英文沟通草稿。"}],["$","meta","2",{"name":"robots","content":"index, follow"}],["$","meta","3",{"name":"googlebot","content":"index, follow, max-video-preview:-1, max-image-preview:large, max-snippet:-1"}],["$","link","4",{"rel":"canonical","href":"https://techlog-18328.app.workbuddy.host/blog/mpt-open-source-contribution-analysis"}],["$","link","5",{"rel":"alternate","type":"application/rss+xml","href":"https://techlog-18328.app.workbuddy.host/feed.xml"}],["$","meta","6",{"property":"og:title","content":"如何给一个陌生开源项目做架构分析,并找到能合进去的贡献点"}],["$","meta","7",{"property":"og:description","content":"以 MoneyPrinterTurbo 为例,按 7 个维度(任务规划、多 Agent 协作、上下文管理、Human-in-the-loop、评估框架、工具路由、Streaming)系统拆解一个陌生项目的架构缺陷,从中筛出 Top 3 贡献方向,并给出方案骨架与给维护者的英文沟通草稿。"}],["$","meta","8",{"property":"og:url","content":"https://techlog-18328.app.workbuddy.host/blog/mpt-open-source-contribution-analysis"}],["$","meta","9",{"property":"og:site_name","content":"TechLog"}],["$","meta","10",{"property":"og:locale","content":"en_US"}],["$","meta","11",{"property":"og:image","content":"https://techlog-18328.app.workbuddy.host/static/images/twitter-card.png"}],["$","meta","12",{"property":"og:type","content":"article"}],["$","meta","13",{"property":"article:published_time","content":"2026-09-15T00:00:00.000Z"}],["$","meta","14",{"property":"article:modified_time","content":"2026-09-15T00:00:00.000Z"}],["$","meta","15",{"property":"article:author","content":"眠月"}],["$","meta","16",{"name":"twitter:card","content":"summary_large_image"}],["$","meta","17",{"name":"twitter:title","content":"如何给一个陌生开源项目做架构分析,并找到能合进去的贡献点"}],["$","meta","18",{"name":"twitter:description","content":"以 MoneyPrinterTurbo 为例,按 7 个维度(任务规划、多 Agent 协作、上下文管理、Human-in-the-loop、评估框架、工具路由、Streaming)系统拆解一个陌生项目的架构缺陷,从中筛出 Top 3 贡献方向,并给出方案骨架与给维护者的英文沟通草稿。"}],["$","meta","19",{"name":"twitter:image","content":"https://techlog-18328.app.workbuddy.host/static/images/twitter-card.png"}]],"error":null,"digest":"$undefined"} 1e:"$19:metadata"