How lfnovo/open-notebook Works
该项目定位为Google Notebook LM的开源、可自托管的增强版替代方案。与仅限Google生态的Notebook LM相比,其核心竞争优势在于:\n1. **数据主权与隐私**:用户可以完全在本地或私有云部署,实现对研究数据的100%掌控,解决了使用云服务时对敏感数据隐私的担忧。\n2. **开放性与灵活性**:支持超过16种AI服务商(包括OpenAI、Anthropic及Ollama等本地模型),允许用户根据成本、性能或隐私需求自由选择,彻底摆脱供应商锁定。\n3. **功能扩展与创新**:在Notebook LM核心的RAG(检索增强生成)功能之上,创新性地加入了强大的多角色播客生成功能,能将研究材料一键转化为专业级播客,这是其独特的价值主张。\n4. **可编程性**:提供完整的REST API,允许开发者进行二次开发和系统集成,而Notebook LM是一个封闭系统。\n综上,Open Notebook不仅是一个功能“克隆”,更是一个在隐私、灵活性和功能广度上全面超越目标的“升级版”产品。
Overview
该项目定位为Google Notebook LM的开源、可自托管的增强版替代方案。与仅限Google生态的Notebook LM相比,其核心竞争优势在于:\n1. **数据主权与隐私**:用户可以完全在本地或私有云部署,实现对研究数据的100%掌控,解决了使用云服务时对敏感数据隐私的担忧。\n2. **开放性与灵活性**:支持超过16种AI服务商(包括OpenAI、Anthropic及Ollama等本地模型),允许用户根据成本、性能或隐私需求自由选择,彻底摆脱供应商锁定。\n3. **功能扩展与创新**:在Notebook LM核心的RAG(检索增强生成)功能之上,创新性地加入了强大的多角色播客生成功能,能将研究材料一键转化为专业级播客,这是其独特的价值主张。\n4. **可编程性**:提供完整的REST API,允许开发者进行二次开发和系统集成,而Notebook LM是一个封闭系统。\n综上,Open Notebook不仅是一个功能“克隆”,更是一个在隐私、灵活性和功能广度上全面超越目标的“升级版”产品。
为注重隐私的研究者、知识工作者和内容创作者,提供一个可私有化部署、支持多种AI模型、功能全面的知识管理与内容创作工具,作为Google Notebook LM的开源替代品。
How It Works: End-to-End Flows
用户构建知识库并进行RAG问答
这是产品的核心使用场景。用户首先创建一个“笔记本”来组织一个特定的研究主题。然后,他们将多种格式的外部资料(如PDF论文、网页文章)作为“源”添加到笔记本中。系统在后台自动对这些源进行处理,包括提取全文、智能分块,并使用AI模型将每个文本块转换为向量进行索引。处理完成后,用户可以打开笔记本的聊天窗口,输入一个问题。在提问前,他们可以精确勾选希望AI本次回答参考哪些源或笔记。系统将选定内容的文本聚合为“上下文”,连同用户的问题一起发送给大语言模型。模型在理解上下文的基础上生成精准的回答,从而实现高质量的检索增强生成(RAG)问答体验。
- 用户创建笔记本
- 用户添加多模态源(文件/URL),系统后台进行内容提取、分块与向量化
- 用户在聊天前构建动态上下文,选择参考资料
- 用户在上下文中进行提问,系统返回AI生成的回答
- 用户也可使用混合搜索直接查找相关内容片段
用户将研究材料一键生成多角色播客
此流程展示了产品的旗舰创新功能。用户首先进行一次性配置,创建好“角色模板”(定义AI主播的音色和人设)和“剧集模板”(定义播客的结构和风格)。当用户希望将知识库中的内容转化为播客时,他们只需选择一个笔记本或一段具体文本作为素材,再选定之前配置好的角色和剧集模板,然后点击“生成”。系统会立即启动一个后台作业,并在前端返回一个作业ID供用户追踪进度。后台作业会自动完成一系列复杂的AI创作:首先根据素材和模板生成播客大纲,然后为每一段生成引人入胜的多人对话脚本,最后调用文本转语音(TTS)服务合成每个角色的音频并拼接成完整的MP3文件。任务完成后,用户就可以在系统内直接收听或下载这段由AI完整制作的专业播客。
- 用户一次性配置角色模板(人设/声音)和剧集模板(风格/结构)
- 用户选择研究材料(如整个笔记本内容)和模板,提交播客生成任务
- 系统后台异步执行:生成大纲 -> 生成脚本 -> 合成音频
- 用户通过作业状态接口监控进度
- 任务完成后,用户在线播放或下载生成的MP3播客文件
用户使用AI转换器从源材料中提取结构化洞察
这个流程让用户能够对知识库进行深加工。用户首先可以创建自定义的“AI转换器”,例如定义一个名为“提取核心论点”的转换器,其核心是一个指导AI如何从文本中识别并列出核心论点的提示词。创建好后,用户可以在浏览任何一篇“源”的时候,选择这个转换器并执行。系统会将源的全文和转换器的提示词一同发送给AI,AI处理后返回的结果会自动作为一条“洞察”被保存下来,并与该源关联。随着时间推移,一篇源可能会积累下来自不同转换器的多条洞察。如果用户觉得某条AI生成的洞察非常有价值,还可以一键将其“另存为笔记”,使其成为知识库中一个可独立编辑和引用的正式成员。
- 用户定义一个可复用的AI转换器(如“摘要生成器”)
- 用户在某个源上执行该转换器
- 系统自动将AI返回结果保存为与源关联的“洞察”
- 用户可将有价值的“洞察”一键转存为可编辑的“笔记”
管理员配置AI模型并设置系统默认值
这是一个典型的系统设置和管理流程。在新部署一套Open Notebook系统后,管理员首先需要通过一个API接口检查当前环境下哪些AI服务商是可用的(基于环境变量的探测)。然后,管理员会为每个计划使用的AI模型(例如,OpenAI的gpt-4o,或本地的Ollama/llama3)创建一个配置记录。配置完成后,管理员需要进入默认模型设置界面,为系统内的各项核心功能(如聊天、嵌入生成、语音合成等)指定一个默认使用的模型ID。这个流程确保了整个系统有可用的AI能力进行驱动,并为普通用户的日常使用提供了无需每次选择模型的便捷性。当需要切换或升级模型时,管理员也只需更新这些配置即可,无需改动代码。
- 管理员检查当前环境可用的AI服务商
- 管理员为要使用的具体AI模型创建配置记录
- 管理员为聊天、嵌入等核心任务指定默认模型
- (可选)管理员设置全局密码保护API
Key Features
系统设置与模型管理
该模块为整个应用提供基础配置能力,是所有AI功能的前置依赖。其设计核心是提供极高的灵活性和控制力,允许管理员或用户精细化管理AI服务。用户可以注册来自不同供应商的多种AI模型,并为系统内不同任务(如聊天、内容转换、嵌入)指定默认模型。此外,系统还提供API访问控制和AI服务商可用性检查功能,帮助用户快速完成部署和配置。
- AI模型配置与管理 — 【设计策略】通过数据库记录而非硬编码来管理AI模型,实现动态配置。\n\n【业务逻辑】\n- Step 1: 用户通过API接口创建模型记录,必须提供服务商名称(如 'openai', 'ollama')、模型名称(如 'gpt-4o', 'llama3')和模型类型。\n- Step 2: 模型类型被严格限定为四种:`language` (语言模型), `embedding` (嵌入模型), `text_to_speech` (语音合成), `speech_to_text` (语音识别)。\n- Step 3: 系统在创建时会进行去重检查,确保同一服务商、同一模型名称和同一类型的组合是唯一的(大小写不敏感),防止配置冗余。\n- Step 4: 用户可以随时通过API查询、更新或删除已配置的模型记录。
- 系统默认模型设置 — 【设计策略】为不同AI任务设置默认模型,简化日常操作,同时允许在特定场景下进行覆盖。\n\n【业务逻辑】\n- Step 1: 系统在数据库中维护一个全局唯一的默认模型配置记录(`DefaultModels`)。\n- Step 2: 管理员可以通过API设置各项任务的默认模型ID,包括:聊天、内容转换、工具使用、内容嵌入、语音合成、语音识别,以及一个专门用于处理超长上下文的备用模型。\n- Step 3: 系统设计了备用逻辑:如果内容转换和工具使用的默认模型未设置,会自动使用聊天的默认模型。\n- Step 4: 在执行AI任务时,若用户未指定模型,系统会自动加载并使用对应任务的默认模型。如果默认模型被删除或配置错误,系统会记录日志并返回错误,强制要求管理员修复配置。
- AI服务商可用性探测 — 【用户价值】帮助用户在配置模型前,快速了解当前环境下哪些AI服务商是可用的,避免无效配置。\n\n【设计策略】基于环境变量的存在性来判断服务商的可用状态,而非进行实际的API连通性测试。\n\n【业务逻辑】\n- Step 1: 系统提供一个API接口(`GET /api/models/providers`),用于查询所有支持的服务商及其当前状态。\n- Step 2: 对于每个服务商(如ollama, openai, groq等),系统会检查其所需的一个或多个关键环境变量(如`OPENAI_API_KEY`)是否存在。\n- Step 3: 如果所需环境变量都已设置,则该服务商被标记为“可用”。\n- Step 4: 系统还会结合底层AI抽象库(Esperanto)的注册信息,报告每个可用的服务商具体支持哪几种模型类型(语言、嵌入等)。\n\n【权衡】这种方式启动快、无网络依赖,但无法验证API密钥的有效性或网络是否通畅。用户可能看到服务商“可用”,但在实际调用时仍会失败。
- API访问控制 — 【设计策略】提供一种简单的全局密码保护机制,适用于个人或小团队的私有化部署场景。\n\n【业务逻辑】\n- Step 1: 管理员可以在环境变量中设置一个`OPEN_NOTEBOOK_PASSWORD`。\n- Step 2: 如果设置了该密码,所有API请求(除了少数公开的配置和健康检查接口)都必须在请求头中包含`Authorization: Bearer {password}`。\n- Step 3: 服务器中间件会校验此密码,如果密码错误或未提供,则返回401未授权错误。\n- Step 4: 如果未设置环境变量,则整个API无需认证即可访问。\n- Step 5: 前端应用会自动检测是否需要认证,并引导用户到登录页面输入密码。
知识库构建与管理
这是产品的核心模块,负责将用户的原始资料转化为结构化的、可供AI利用的知识。它围绕“笔记本(Notebook)”和“源(Source)”两个核心概念构建。用户可以创建多个笔记本以组织不同的研究项目,并将多种格式的源文件(PDF、网页、音视频等)添加入库。所有耗时的数据处理,如文本提取、向量化,都通过后台异步作业完成,确保了流畅的前端体验。
- 笔记本管理与安全删除 — 【设计策略】以笔记本为单位组织研究材料,并在删除时提供清晰的预览,防止误删共享资源。\n\n【业务逻辑】\n- Step 1: 用户创建一个笔记本,包含名称和描述。\n- Step 2: 用户可以将“源”关联到一个或多个笔记本。一个源可以被多个笔记本共享。\n- Step 3: 当用户尝试删除一个笔记本时,系统首先运行“删除预览”逻辑,计算并告知用户:\n - 将有多少条笔记被永久删除。\n - 将有多少个“独占源”(仅被此笔记本引用的源)被删除。\n - 将有多少个“共享源”被解除关联(但不会被删除)。\n- Step 4: 用户确认后,系统执行删除操作:首先删除所有关联的笔记,然后根据用户选择删除独占源,最后解除与共享源的关联,并删除笔记本自身。
- 多模态源内容摄取 — 【设计策略】支持多种格式的源内容输入,并将其统一处理为纯文本,为后续的AI分析做准备。\n\n【业务逻辑】\n- Step 1: 用户可以通过上传文件(PDF、Office文档)、提供URL(网页、YouTube视频)或直接粘贴文本来创建“源”。\n- Step 2: 系统接收到输入后,会创建一个“源”记录,并将文件保存到指定目录(`UPLOADS_FOLDER`),或将URL、文本存入数据库。\n- Step 3: 对于文件和URL,系统会触发一个名为`process_source`的后台异步作业来提取内容。\n- Step 4: 后台作业会根据源的类型(如文件后缀名)调用不同的解析器,例如使用专门的库从PDF中提取文本,或从YouTube视频中提取字幕。所有内容最终都被转换为标准化的`full_text`字段,存储在“源”记录中。
- 内容分块与向量化 — 【用户价值】将长文档切分为有意义的小块并生成向量,使得AI可以进行精准的语义搜索,定位到最相关的段落而不是整个文档。\n\n【设计策略】采用基于内容类型的智能分块策略,并通过后台作业异步生成向量。\n\n【业务逻辑】\n- Step 1: 在源内容处理流程中,如果用户选择“嵌入(embed)”,系统会触发`embed_source`后台作业。\n- Step 2: 作业首先根据源内容类型(如Markdown、纯文本)选择合适的分块器(`chunk_text`),将`full_text`切分成多个重叠的文本块。分块大小和重叠比例可通过环境变量配置(默认为1200字符,15%重叠)。\n- Step 3: 系统将所有文本块批量发送给配置好的嵌入模型(如OpenAI的`text-embedding-3-small`),一次性生成所有块的向量。\n- Step 4: 生成的每个向量与其对应的文本块、在原文中的顺序,作为一个`source_embedding`记录被批量存入数据库,并与原始的“源”记录关联。\n- Step 5: 为了保证幂等性,每次执行向量化之前,系统会先删除该源已有的所有`source_embedding`记录。
- 长笔记的向量均值池化 — 【用户价值】即使是长篇笔记也能拥有一个高质量的单一代表性向量,使其能作为一个整体参与语义搜索和比较。\n\n【设计策略】对于超出模型单次处理长度的文本,采用“分块-嵌入-均值池化”的策略来生成单个汇总向量。\n\n【业务逻辑】\n- Step 1: 当需要为一篇笔记或AI洞察生成向量时,系统首先检查其文本长度。\n- Step 2: 如果文本长度小于等于预设的分块大小(`CHUNK_SIZE`),直接调用嵌入模型生成一个向量。\n- Step 3: 如果文本长度超过分块大小,系统先将其分块,然后批量为所有文本块生成向量。\n- Step 4: 系统执行“均值池化”算法:首先将每个文本块的向量归一化(使其长度为1),然后计算所有归一化向量的元素级平均值,最后将得到的平均向量再次归一化。\n- Step 5: 这个最终生成的单一向量被存储在笔记或洞察记录的`embedding`字段中。
知识消费与互动
当知识库构建完成后,本模块提供了与知识进行高效互动的方式。核心功能包括一个结合了关键词和语义理解的混合式搜索引擎,以及一个能够基于用户选定资料进行上下文对话的聊天系统。用户可以精确控制AI对话时参考的“记忆”范围,从而提出高度相关的问题并获得有理有据的回答。
- 混合式智能搜索 — 【设计策略】同时提供传统的文本搜索和现代的向量搜索,让用户根据需要选择最合适的检索方式。\n\n【业务逻辑】\n- Step 1: 用户在搜索框输入关键词,并选择搜索类型:“文本搜索”或“向量搜索”。\n- Step 2: 如果选择“文本搜索”,系统会调用数据库的全文检索功能(`fn::text_search`),在源和笔记的文本内容中进行关键词匹配。\n- Step 3: 如果选择“向量搜索”,系统首先会调用嵌入模型将用户的关键词转换为一个查询向量。\n- Step 4: 然后使用该查询向量,调用数据库的向量搜索功能(`fn::vector_search`),在已向量化的内容块(`source_embedding`)和笔记中寻找语义最相似的条目。\n- Step 5: 向量搜索支持设置一个最低相似度分数(默认为0.2),过滤掉不相关的结果。\n- Step 6: 用户还可以筛选搜索范围,指定是只搜索“源”,还是只搜索“笔记”,或是两者都搜索。
- 上下文感知聊天 — 【设计策略】将聊天会话与特定的知识范围(整个笔记本或单个源)绑定,并利用LangGraph持久化对话状态,实现有记忆、可追溯的对话。\n\n【业务逻辑】\n- Step 1: 用户可以为任意一个笔记本或一个源创建聊天会话。每个会话都作为一个独立的记录(`ChatSession`)存储,并通过数据库关系(`refers_to`)与笔记本或源相关联。\n- Step 2: 用户可以为每个会话单独覆盖系统默认的AI模型。\n- Step 3: 对话历史通过LangGraph的线程状态(thread state)进行管理,每个聊天会话ID对应一个唯一的线程ID。这使得对话可以跨请求保持记忆。\n- Step 4: 当用户发送消息时,前端需要将选定的上下文(见f11)连同消息一起提交。\n- Step 5: 后端将用户消息和上下文注入到当前会话的LangGraph状态中,并调用图(`chat_graph.invoke`)来生成AI的回复。图的执行结果(AI回复)会被更新回线程状态,并返回给用户。
- 动态上下文构建 — 【用户价值】让用户在提问前,像选择文件一样精确地勾选AI需要参考的资料,并能预览上下文的规模,从而完全控制AI的“记忆”边界。\n\n【设计策略】由前端负责收集用户的上下文选择,后端负责根据选择聚合内容并估算token数量。\n\n【业务逻辑】\n- Step 1: 在聊天界面,用户可以勾选笔记本内的哪些源和笔记需要被包含在本次对话的上下文中。\n- Step 2: 对于每个选中的“源”,用户还可以进一步选择其内容粒度,例如“仅使用AI生成的洞察”、“使用全文内容”等。\n- Step 3: 前端将用户的选择配置发送到后端API(`/api/notebooks/{id}/context`)。\n- Step 4: 后端根据这份配置,从数据库中提取相应的文本内容(源的全文、洞察或笔记内容),并将其拼接成一个长字符串。\n- Step 5: 系统会估算这个拼接后字符串的总token数量,并返回给前端。\n- Step 6: 用户可以看到预估的token数,然后确认将此上下文用于接下来的对话。\n\n【权衡】当前实现只进行token估算,并未发现有自动截断或优先级排序的逻辑来处理超出模型限制的超大上下文,这可能导致API调用失败或成本超预期。
内容再创作与衍生
这是本产品最具创造性的模块,它将知识库从一个被动查询的资料库,转变为一个主动生成新内容的创作工厂。用户可以定义可复用的“AI转换器”来从原始材料中批量提取结构化信息(洞察),更可以调用旗舰级的“播客生成器”,将任何文本内容一键转化为一场由多位AI主播参与的专业播客讨论。
- 可复用AI内容转换器 — 【用户价值】将重复性的内容处理任务(如“为这段文字写一个摘要”、“提取关键论点”)封装成可一键执行的模板。\n\n【设计策略】将每个转换器定义为一个包含提示词和元数据的数据库记录,执行时动态加载。\n\n【业务逻辑】\n- Step 1: 用户通过API创建一个“转换器”(`Transformation`),需定义其名称、标题、描述和一个核心的提示词模板。\n- Step 2: 用户还可以创建一个全局的“默认指令”,这段指令会自动前置于所有转换器的提示词,用于设定统一的角色、风格或格式要求。\n- Step 3: 当执行一个转换器时,用户需提供输入文本,并可选择一个特定的AI模型来执行。\n- Step 4: 后端加载转换器模板和默认指令,将它们与输入文本组合成一个完整的提示,然后调用选定的AI模型。\n- Step 5: AI的返回结果经过清理(如去除思考过程标签)后,作为转换结果返回给用户。
- AI洞察生成与管理 — 【设计策略】将AI转换器的输出结果作为结构化的“洞察”记录进行持久化,并允许用户将其提升为可编辑的“笔记”。\n\n【业务逻辑】\n- Step 1: 当一个“转换器”在某个“源”上执行后,其输出结果会被自动保存为一个“洞察”(`SourceInsight`)记录,并与该“源”关联。洞察的类型被设定为转换器的标题。\n- Step 2: 用户可以查询一个源下的所有洞察。\n- Step 3: 用户如果认为某条洞察很有价值,可以将其“另存为笔记”。\n- Step 4: 系统会创建一个新的“笔记”(`Note`)记录,其内容来自洞察,标题被自动设为“{洞察类型} from source {源标题}”。用户还可以选择将这条新笔记归入哪个笔记本。\n- Step 5: 转化后的笔记与其他手动创建的笔记一样,可以被搜索、编辑和用于聊天上下文。
- 专业级多角色播客生成 — 【用户价值】颠覆性的功能,将枯燥的文本材料自动转化为生动、专业的AI多人对话播客,极大丰富了内容呈现形式。\n\n【设计策略】采用“角色模板”与“剧集模板”相分离的两级配置系统,通过后台作业流完成“大纲生成 -> 脚本生成 -> 音频合成”的完整链条。\n\n【业务逻辑】\n- Step 1: **配置角色模板 (Speaker Profile)**:用户创建角色模板,定义1到4位AI主播。每个主播需配置姓名、人设/背景故事,以及用于生成语音的TTS提供商(如ElevenLabs)和具体的语音ID。\n- Step 2: **配置剧集模板 (Episode Profile)**:用户创建剧集模板,定义播客的整体风格。包括用于生成大纲和脚本的AI模型、播客的分段数量(3-20段)、以及指导AI生成内容的简报(briefing)模板。\n- Step 3: **提交生成任务**:用户发起播客生成,需要选择一个角色模板、一个剧集模板,并提供核心内容(可以直接输入文本,或指定一个笔记本让系统自动提取其内容)。系统提交一个`generate_podcast`后台作业,并立即返回作业ID。\n- Step 4: **后台生成 - 大纲**:后台作业首先调用AI,根据剧集模板和输入内容,生成一个JSON格式的播客大纲,包含每段的标题和讨论要点。\n- Step 5: **后台生成 - 脚本**:作业接着遍历大纲的每一段,再次调用AI,根据角色模板中的人设,为该段生成多角色对话的JSON脚本。\n- Step 6: **后台生成 - 音频**:最后,作业遍历脚本中的每一句对话,调用角色模板中对应主播的TTS配置,生成单句音频,并将所有音频拼接成一个完整的MP3文件。\n- Step 7: **结果交付**:生成的MP3文件、脚本和提纲都会被保存,并与一个“播客剧集”(`PodcastEpisode`)记录关联。用户可以通过API查询、播放或下载该剧集。
数据与系统运维
该模块为产品的稳定运行和长期维护提供保障。它包含了一些对产品经理同样有价值的、面向运维的“产品功能”。例如,数据库的自动迁移机制确保了应用在升级版本时数据的平滑过渡;向量索引重建功能则允许在更换嵌入模型或调整分块策略后,对整个知识库进行再处理,保证搜索质量。
- 数据库自动迁移 — 【用户价值】让应用升级过程自动化,无需手动执行数据库脚本,降低了部署和维护的复杂度。\n\n【设计策略】在应用启动时,自动检查数据库结构版本并应用必要的更新。\n\n【业务逻辑】\n- Step 1: 系统的所有数据库结构变更都以带版本号的SQL文件形式存储在代码库中。\n- Step 2: 应用服务器启动时,会首先连接数据库,并查询一个专门的迁移版本记录表(`_sbl_migrations`)来获取当前数据库的版本号。\n- Step 3: 系统将当前版本号与代码库中定义的所有迁移脚本进行比较。\n- Step 4: 如果发现有未应用的更高版本的脚本,系统会按顺序逐一执行这些脚本来更新数据库结构。\n- Step 5: 每成功执行一个脚本,就会在版本记录表中写入新的版本号。\n- Step 6: 如果任何迁移步骤失败,应用会启动失败并报错,阻止其在数据结构不兼容的状态下运行。
- 向量索引重建 — 【用户价值】当更换了更好的嵌入模型或优化了分块策略后,允许用户对已有知识库进行批量更新,以提升未来的搜索和问答质量。\n\n【设计策略】提供一个API触发的后台批量处理作业,并提供状态查询接口,以处理大规模的重建任务。\n\n【业务逻辑】\n- Step 1: 管理员通过API(`POST /rebuild`)发起重建任务。\n- Step 2: 请求中可以指定重建范围:是只重建“已有向量的内容”还是重建“所有内容”,以及是否包含源、笔记和洞察。\n- Step 3: 系统首先估算需要处理的条目总数,然后提交一个`rebuild_embeddings`后台作业,并返回作业ID。\n- Step 4: 后台作业会查询出所有符合条件的条目,并为每一条目提交一个单独的`embed_source`或`embed_note`等向量化作业。\n- Step 5: 管理员可以通过作业ID查询重建进度,接口会返回总数、已提交处理数、失败数等统计信息。
Core Technical Capabilities
基于后台作业的异步内容处理与衍生架构
Problem: 如何处理耗时的内容处理任务(如文件解析、向量化、播客生成),而不会让用户界面卡顿或遭遇服务器超时?传统同步处理方式会锁定用户界面,体验极差,且容易因网络波动导致任务失败。
Solution: Step 1: 将所有耗时操作(如`process_source`, `embed_source`, `generate_podcast`)封装为独立的后台作业。\nStep 2: 用户通过API提交任务后,系统使用`surreal-commands`库将作业请求持久化到数据库,并立即返回一个作业ID给前端,实现“提交即返回”。\nStep 3: 后台的工作进程独立地从数据库中拉取并执行这些作业,支持自动重试(如指数退避)和错误处理。\nStep 4: 前端可以使用作业ID轮询任务状态API,向用户展示实时进度(如 '处理中', '已完成', '失败')。部分复杂流程如内容处理使用LangGraph进行状态编排,实现更复杂的内部逻辑流转。\n核心价值:通过将耗时操作与用户请求解耦,极大提升了用户体验和系统的可靠性。
Technologies: surreal-commands, LangGraph, FastAPI, AsyncIO
Boundaries & Risks: 此架构依赖于`surreal-commands`库的稳定性和后台工作进程的健康。如果工作进程宕机,任务将不会被执行。状态更新依赖前端轮询,而非实时推送(如WebSockets),可能存在一定的延迟。作业失败后的排查需要访问后台日志,对非技术用户不友好。
插件化、可扩展的多AI服务商支持
Problem: 如何让用户自由选择AI模型(例如为了成本选择Groq,为了私密性选择本地Ollama),从而避免被单一供应商(如OpenAI或Google)锁定?同时如何保证系统在切换模型后依然能正常工作?
Solution: Step 1: 通过一个名为`Esperanto`的抽象库,统一所有AI能力的调用接口(语言模型、嵌入、语音合成等)。\nStep 2: 在数据库中存储AI模型的配置记录,而不是将模型名称硬编码在代码中。每条记录包含服务商、模型名称、类型等信息。\nStep 3: 运行时,系统根据任务需求(如“需要一个聊天模型”)和用户配置,从数据库加载模型记录。\nStep 4: 一个名为`AIFactory`的工厂类根据模型记录动态创建并返回一个具体的、可用的AI服务商实例(如LangChain的`ChatOllama`或`ChatOpenAI`实例)。\n核心价值:通过配置而非代码来切换底层AI服务,实现了极高的灵活性和成本控制能力。
Technologies: esperanto, Pydantic, SurrealDB, LangChain
Boundaries & Risks: 可用性检查仅基于环境变量是否存在,而不是实时连通性测试,用户可能配置了无效的API密钥但在运行时才发现。添加新的服务商需要更新`Esperanto`库。不同服务商的模型能力和返回格式有差异,可能会导致上层业务逻辑需要做兼容性处理。
灵活的两级模板系统实现专业播客生成
Problem: 如何让用户轻松生成风格多样的播客,同时又能保持角色人设的一致性,而不需要每次都进行繁琐的参数配置?
Solution: Step 1: 设计两级配置模板系统。`SpeakerProfile`(角色模板)专注于定义角色的声音(TTS提供商、语音ID)和人设(姓名、背景故事、性格)。\nStep 2: `EpisodeProfile`(剧集模板)专注于定义播客的结构和风格(分段数量、用于生成大纲和脚本的AI模型、内容简报模板)。\nStep 3: 用户在生成播客时,只需选择一个剧集模板和一个角色模板。系统会将两者组合,动态生成完整的播客制作指令。\n核心价值:通过“角色”与“剧本”的分离,实现了配置的解耦和复用,用户可以像搭积木一样组合出不同风格的播客,极大降低了创作门槛。
Technologies: Pydantic, Jinja2, LLM, TTS
Boundaries & Risks: 播客质量高度依赖于Jinja2提示词模板的质量和所选大语言模型(LLM)的理解与创作能力。模板是固定的,对于需要高度动态或即兴发挥风格的播客,效果可能受限。目前支持1-4个角色,不支持更多角色的复杂对话。
基于SurrealDB的领域建模与自动化迁移
Problem: 作为一款功能复杂的应用,如何高效管理实体间复杂的关联关系(如笔记本、源、笔记、聊天会话等),并确保在产品迭代时,用户的存量数据能够平滑升级?
Solution: Step 1: 利用Pydantic模型定义所有核心业务实体(Notebook, Source, Note等),实现了代码层面的强类型和数据校验。\nStep 2: 使用SurrealDB作为底层数据库,其内置的图数据库能力被用来清晰地表示实体间的关系(如`refers_to`, `artifact`等关系边)。\nStep 3: 实现了一个数据库仓库层(Repository),封装了所有CRUD操作和ID格式化逻辑,使上层业务代码更简洁。\nStep 4: 内置一个自动迁移管理器,在应用每次启动时检查数据库版本,并自动执行新的迁移脚本,保证数据结构与代码版本同步。\n核心价值:提供了一个健壮、可维护的数据持久化方案,为产品的快速迭代和长期演进奠定了坚实基础。
Technologies: SurrealDB, Pydantic, Python Async/Await
Boundaries & Risks: 当前删除操作(如删除笔记本)缺少数据库事务包裹,若中途失败可能导致数据不一致。迁移脚本是硬编码在列表中的,新增迁移时需要修改代码,有遗漏的风险。并发更新操作没有使用乐观锁,可能存在“最后写入者获胜”的数据覆盖问题。
