ARTICLE DETAIL

资讯详情

深耕网站视觉设计与运营推广的一线实战洞察。

notebooklm-py:Web 与 Android 双后端公开行为差异清单——投影差异、策略保留与跟踪中的默认值变更

notebooklm-py:Web 与 Android 双后端公开行为差异清单——投影差异、策略保留与跟踪中的默认值变更 notebooklm-pyWeb 与 Android 双后端公开行为差异清单——投影差异、策略保留与跟踪中的默认值变更【免费下载链接】notebooklm-pyUnofficial Python API and agentic skill for Google Gemini Notebook. Full programmatic access to NotebookLMs features—including capabilities the web UI doesnt expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.项目地址: https://gitcode.com/GitHub_Trending/no/notebooklm-py本文解读 notebooklm-py 仓库中提交的《Web vs Android public-behavior inventory》契约文档docs/web-android-public-behavior.md它系统性地列出了NotebookLMClient在 Webbatchexecute与 Androidprotobuf/gRPC两个后端之间仍然存在的 13 项公开行为差异并为每一项给出分类投影差异、刻意策略、能力元数据、原始逃生舱口、已修复缺陷、跟踪中的默认值变更、事实描述和钉住该行为的回归测试。读完本文你能判断某个跨后端行为差异究竟应该文档化而非修复、保留策略还是等待受控的默认值翻转并了解仓库如何用护栏测试强制维护这份清单不被悄悄删改。为什么需要这份差异清单notebooklm-py 的 typedNotebookLMClient方法在两个后端之间共享同一份公开契约Web 走batchexecute协议Android 走 protobuf/gRPC。但从源码结构看两端由不同的解码器和不同的传输层支撑src/notebooklm/_web/与src/notebooklm/_android/各自实现命名空间方法因此少数残留差异并不只是线上编码不同。这份清单的存在目的有三个让调用方不把投影差异误判为缺陷让未来重构者不把已跟踪、独立受控的默认值翻转误当作已随版本上线不把真正的 bug 误当作策略如此。后端选择本身很简单Web 是默认后端显式传backendandroid或设置环境变量NOTEBOOKLM_BACKENDandroid即可切换到 Android 实现显式参数优先于环境变量见 Python API — backend selection。文档同时声明Android 凭据master token与 Web 登录态 cookie 是两套体系选择 Android 后 Web 侧的 cookies/环境配置会被忽略见 docs/python-api.md 的 Backend selection 章节。明确非目标Non-goals这份清单定位是文档 护栏不是架构改造计划。文档明确排除以下工作护栏测试也强制这些措辞必须保留在页面中不统一 protobuf 与 batchexecute 两套编解码器不从 sharing/notes 中抽取通用的 mutation executor不实现 issue #2384 对应的get_history严格化修复该修复已由 PR #2389 独立发布见下节不涉及 v1 凭据相关工作。完整差异清单13 项以下是文档中的完整清单表。每项包含方法、实际成立的结论、分类、以及钉住该行为的测试。所有测试路径均可在当前仓库中直接运行验证。Method实际成立的事实分类钉住测试notes.getafternotes.delete一致性层面两个后端在网络上都能仍看到持久化的软删除墓碑tombstone。Android 的公开get/get_or_none将其投影为缺失抛NoteNotFoundError/ 返回NoneWeb 的get/get_or_none仍可能返回一个被清空的Note保留id标题与内容为空。Android 并没有被证明会硬删除该行——不要以假设硬删除的方式去修复它投影差异——文档化不要以假设硬删除来修复tests/e2e/test_android_notes_conformance.pylive 可选运行不要求此处重跑tests/unit/android/test_notes_frontend_parity.pytest_android_notes_satisfy_public_nullable_raw_and_absence_contractschat.get_historyon turn-fetch failure两个后端现在都会传播 turn 获取阶段的ChatError/NetworkError。Web 此前在失败时返回[]。对正数 limit 而言[]表示没有会话或没有 turnAndroid 对非正数 limit 也返回[]已修复的 bug——严格契约由 PR #2389 独立发布修复 issue #2384tests/unit/test_chat_characterization.pytest_get_history_raises_on_chat_error、test_get_history_raises_on_network_errortests/unit/android/test_chat.pytest_get_history_raises_on_turns_rpc_error、test_get_history_returns_empty_when_no_conversationget_prompt(..., require_completeFalse)Web 的 prompt 解码器本来就是严格的直连 Studio/note 路径require_completeTrue不会额外增加一次 lookup 预检。Android 的 0.x 默认仍走 legacyget_or_none可能把一个不完整聚合下的 no-hit 投影为缺失并附带已注册的artifact_ambiguous_absence警告。第一方消费者CLI/MCP 的解析器一律传require_completeTrue跟踪中的默认值变更——作为 C3-02 独立受控不在此清单内翻转默认值Webtests/unit/test_artifact_completeness.pytest_web_strict_prompt_keeps_direct_path_without_lookup_preflight。Android legacytests/unit/android/test_artifacts.pytest_android_legacy_prompt_warns_only_when_absence_is_ambiguous交互式mind_maps.generate等待结果为 FAILED/REMOVEDWeb 在等待到 failed/removed 完成态之后会继续水化hydrate交互式树除非显式failure_policyraise并且只有在该 legacy 水化确实继续时才发出mind_map_legacy_terminal_hydration警告。Android 在 legacy 模式下已经抛ArtifactNotReadyError跟踪中的默认值变更——作为 C5A-01 独立受控若该闸门条件未满足则推迟默认翻转tests/unit/test_creation_conformance.pytest_waited_interactive_outcome_matrixtests/unit/test_mind_maps_base.pytest_interactive_wait_failure_policy_preserves_each_backend_contractresearch.import_sourcesAndroid 要求规范 UUID 形式的task_id可解析但非规范的写法会被拒绝。Web 接受不透明 task id要求报告行显式携带报告字段titlereport_markdownresult_type 5并且可能重排为报告在前。两种策略都保留刻意策略——保留中性策略/顺序tests/unit/test_research_import_helpers.pytest_import_policies_are_immutable_and_preserve_task_id_validation、test_import_classification_preserves_backend_report_order。Android UUIDtests/unit/android/test_research_guards.pytest_a_parseable_but_non_canonical_run_id_is_rejected交互式 mind-map 的language公开mind_maps.generate(..., language...)入参在两个后端都被接受。Web 不在交互式CREATE_ARTIFACT请求上编码language线上没有 language 槽位。Android 会编码language_code。不要在任何对齐补丁中拒绝 Web 的language入参能力元数据——保留Web 在creation_capabilities中将交互式 mind map 列为 instructions-onlytests/unit/test_creation_conformance.pytest_interactive_domain_normalization_and_language_encodingnotebooks.get_raw原始逃生舱口。Web 返回 batchexecute 的 list 载荷。Android 返回message_to_known_dict产出的dict已知 protobuf 字段转 snake_case既不是protobuf message也不是Web 的位置行原始逃生舱口——记录真实类型Web listtests/integration/test_notebooks_integration.pytest_get_raw。Android dicttests/unit/android/test_notebook_source_reads.pytest_get_raw_is_known_field_snake_case_message_dictnotes.list_mind_maps返回类型是不透明的list[Any]。Android 返回最小的兼容[id, content]行。Web 返回完整 note 行content 嵌套在当前 metadata 信封中。应比较解码后的 content而不是逐字节对比原始行原始/兼容行——文档化tests/e2e/test_android_notes_conformance.pytests/unit/android/test_notes_frontend_parity.pytest_android_notes_satisfy_public_nullable_raw_and_absence_contractschat.get_conversation_turns后端形状的AnyWeb 返回 batchexecute 的 turn 行Android 返回ListChatTurnsResponseprotobuf message。typed 的历史读取是chat.get_history→list[tuple[str, str]]原始——文档化不在此清单中包装Web 行tests/unit/test_chat_characterization.pytest_get_conversation_turns。Android protobuftests/unit/android/test_chat.pytest_list_sessions_raw_turns_and_history_decode_exact_requestsartifacts.generate_*入参校验两端在省略 sources 时都会解析 notebook 的全量清单。Web 保留显式空source_ids[]、空 language、非字符串 instructions以及历史上被接受的 legacy 枚举式取值。Android 在派发前拒绝这些输入并要求取值属于期望枚举。Quiz/flashcard 的数量与难度在两端都会校验刻意策略——保留现有输入兼容性tests/unit/test_creation_conformance.pytest_source_omission_and_empty_are_backend_policy、test_legacy_web_accepted_inputs_do_not_acquire_android_rejections创建契约artifacts.generate_report传ReportFormat.CONCEPT_EXPLANATIONAndroid 支持概念解释型报告Web 将该格式作为不支持而拒绝能力元数据——保留tests/unit/test_creation_conformance.pytest_android_concept_report_support_is_not_fabricated_on_web交互式 mind-map 的instructionsWeb 会省略纯空白 prompt 并保留非空白文本。Android 原样保留传入文本包括空白刻意策略——保留tests/unit/test_creation_conformance.pytest_interactive_domain_normalization_and_language_encodingsources.add_file的.csv、.docx、.pptxWeb 将Source.kind暴露为CSV、DOCX或POWERPOINT。Android 把这些格式经由 Drive 暂存stage并暴露 Drive 类型GOOGLE_DRIVE线上码 14捕获到的摄取行为是内容一致、类型不一致。码 14 对其他 MIME 类型如 Sheets、PDF可以进一步区分投影差异——保留真实的 source kindtests/unit/android/test_source_upload.pytest_every_drive_staged_extension_routes_through_drivetests/unit/test_types.pysource-kind 映射捕获的 Web/Android 上传矩阵清单还说明live 的 Android notes 一致性探针是可选开启opt-in的且只会破坏性地操作它自己以唯一前缀创建的资源本文档把它引用为墓碑 /list_mind_maps的预言机oracle并不要求重跑 live 测试。逐项速读哪些差异看起来像 bug 但不是清单中最容易被误读的是投影差异类。以notes.getafternotes.delete为例两个后端在网络上看到的其实是同一个软删除墓碑差别只在公开类型的投影——Android 把墓碑投影成不存在NoteNotFoundError/NoneWeb 则投影成一个id保留、标题与内容清空的Note。文档特别强调Android 并未被证明会硬删除该行因此任何让 Web 也返回缺失之类的对齐改动都是把推测当事实。同类还有sources.add_file的类型投影上传.csv/.docx/.pptx时Web 直接暴露对应Source.kind而 Android 走 Drive 暂存路径、统一暴露GOOGLE_DRIVE线上码 14。捕获到的实际摄取结果显示内容层面是一致的只是类型字段不守恒——这是投影差异不是数据丢失捕获证据中有对应章节。刻意策略类research.import_sources、artifacts.generate_*入参校验、mind-mapinstructions空白处理则相反差异是设计上有意保留的。例如 Web 保留了历史上传入即被接受的空source_ids[]、空language、非字符串instructions等宽松面而 Android 在派发前严格拒绝并要求枚举成员合法——tests/unit/test_creation_conformance.py 中的test_legacy_web_accepted_inputs_do_not_acquire_android_rejections钉住了Web 不会被加上 Android 式拒绝这一兼容性承诺。原始逃生舱口类notebooks.get_raw、notes.list_mind_maps、chat.get_conversation_turns的共同点是返回类型本身就是后端形状调用方应比较解码后的语义内容如 mind map 的 content 文本、turn 的(role, text)元组而不是对原始行做逐字节比对。typed 读取路径chat.get_history返回list[tuple[str, str]]才是跨后端稳定契约。两项跟踪中的默认值变更C3-02 与 C5A-01清单中有两行的分类是Tracked default flip它们的默认值翻转被独立闸门gate控制且明确不在此清单中执行。两者的闸门记录在 独立 C3/C4/C5 迁移行 中C3-02get_prompt(..., require_completeFalse)的严格化现状Web 的 prompt 解码器已经严格——源码注释写明它直读 Studio、并在 Studio 未命中时传播确切的 note-backed lookup 失败require_complete只是跨后端拼写对齐的增量参数不构成 Web 预检见 src/notebooklm/_web/artifacts.py 中get_prompt的 docstring 与实现注释。Android 的 0.x 默认路径仍走 legacyget_or_none见 src/notebooklm/_android/artifacts.py 的get_prompt可能把不完整聚合下的 no-hit 投影成缺失。警告信号legacy 的歧义路径注册了artifact_ambiguous_absence弃用警告其文案直接引导调用方改用get_prompt(..., require_completeTrue)来区分 MISSING 与 UNKNOWN见 src/notebooklm/_deprecation.py。闸门条件摘自 docs/deprecations.md 的 C3-02 行artifact_ambiguous_absence必须先随某个稳定版本实际发布并满足所需间隔第一方 prompt 消费者已选择require_completeTrue路径CLI 与 MCP 的资源解析器都经由 src/notebooklm/_app/artifacts.py 的require_complete_artifact_listing严格路径最终切换默认值时还需一条精确的 changed-default API allowance。在此之前默认值保持False。调用方实践如果你的代码要对prompt 不存在与后端暂时读不到聚合做出不同处理现在就传require_completeTrue这是纯增量、两个后端都接受的参数。C5A-01Web 交互式 mind map 等待失败后的 legacy 水化现状mind_maps.generate等待到 FAILED/REMOVED 完成态时Web 的默认行为是继续水化交互式树返回带状态的结果对象只有显式failure_policyraise时改为抛错且只有 legacy 水化确实继续时才发出精确 key 为mind_map_legacy_terminal_hydration的警告见 src/notebooklm/_deprecation.py 中该 key 的注册。Android 在 legacy 模式下已经抛ArtifactNotReadyError。闸门条件该警告的 registry 源标注since0.9.0但尚无发布证据只有在其自身稳定警告版本与间隔都满足后才允许在 v1.0 翻转 Web 默认值为 raise。闸门还要求精确的 changed-default allowance 与双端行为矩阵否则推迟到后续破坏性版本。钉住测试tests/unit/test_creation_conformance.py 的test_waited_interactive_outcome_matrix覆盖等待到的交互式结果矩阵tests/unit/test_mind_maps_base.py 的test_interactive_wait_failure_policy_preserves_each_backend_contract验证failure_policy在各后端的契约保持。对使用方的含义是不要假设这两处默认值下个版本就会变。清单与闸门文档把已注册警告和已随版本发布严格区分——从源码结构看仓库的弃用注册表src/notebooklm/_deprecation.py中的注册本身不构成已发布证据这一区分在 docs/deprecations.md 的审计结论里被反复强调。已修复项chat.get_history的严格化issue #2384 / PR #2389与跟踪中相对清单里也有已解决的一行chat.get_history在 turn 获取失败时的行为。Web 曾经把取 turn 失败吞掉并返回[]与没有会话/没有 turn的合法空结果无法区分现在两个后端都会传播 turn 获取阶段的ChatError/NetworkError而[]只在正数 limit 下表示没有会话或没有 turnAndroid 对非正数 limit 同样返回[]。这一修复由 PR #2389 独立发布钉住测试分别位于tests/unit/test_chat_characterization.pytest_get_history_raises_on_chat_error、test_get_history_raises_on_network_error同时test_get_conversation_turns钉住 Web 原始 turn 行的返回形状tests/unit/android/test_chat.pytest_get_history_raises_on_turns_rpc_error、test_get_history_returns_empty_when_no_conversation。这条目的存在价值在于示范清单的第三种分类Resolved bug——差异曾经存在、现已修复文档记录的是修复后的严格契约防止回归时把旧行为当平台特性重新引入。护栏清单本身是被测试钉住的文档这份清单不只是 Markdown它是一条可执行的仓库契约。tests/_guardrails/test_web_android_public_behavior_inventory.py 会在以下任一情况失败清单页面或表格整体消失某个必需行REQUIRED_ROWS中定义的 13 个 key从artifacts.generate_*到chat.get_conversation_turns缺失某行丢失其分类class needle、钉住测试路径或关联的 issue/闸门引用docs/python-api.md 停止链接该契约页面docs/deprecations.md 中C3-02/C5A-01两个闸门 key 消失。护栏实现上有两处值得注意的工程细节可直接阅读该文件表格解析_parse_markdown_tables按 GitHub pipe-table 语法解析页面中的所有表格以表头同时含 Method / Class / Pinning定位清单表inventory_problems对每行做 class/test/extra needle 三重匹配例如notes.get after notes.delete行必须同时含tombstone与NoteNotFoundErrorget_prompt行必须含C3-02与deprecations.md。AST 级测试存在性校验对钉住测试列中每个tests/...py引用护栏解析该测试文件的 AST检查行文中点名的test_xxx函数是否真实存在——把测试名改成不存在的名字会让守卫直接失败该文件自带的test_inventory_detector_rejects_a_stale_named_test就演示了这一点。这意味着清单的文档化承诺具有回归保护任何重构若删除或改写某条差异的结论、分类或证据测试CI 会先于调用方发现。对调用方的行动建议结合本清单与 docs/python-api.md 的后端选择说明跨后端代码应遵循以下原则比较语义不比较原始形状mind map 内容用解码后的 content 比对turn 历史走chat.get_history的 typed 元组而不是比较get_raw/get_conversation_turns的返回结构。不要修复投影差异notes 墓碑、GOOGLE_DRIVE码 14的 source kind、Web 宽松保留的空source_ids[]与空白instructions都是已分类的刻意行为或线上投影改动前先查清单分类。对缺失敏感的读取用严格参数prompt 读取传require_completeTrue这是纯增量参数且两端都接受无需等待 C3-02 翻转。失败语义显式化等待交互式 mind map 生成时若希望 failed/removed 直接抛错显式传failure_policyraise不要依赖 C5A-01 的默认值翻转时间表。失败即异常chat.get_history取 turn 失败会抛ChatError/NetworkError[]只代表无会话或无 turn捕获逻辑要区分二者。清单即契约如果你的调用代码依赖了某条跨后端行为可以在本清单的对应行找到钉住它的测试路径直接运行这些测试来验证行为是否仍成立。相关文档与入口契约文档本体docs/web-android-public-behavior.mdStatus: ActiveLast Updated: 2026-09-06后端选择与凭据体系docs/python-api.mdBackend selection 章节默认值变更闸门docs/deprecations.mdIndependent C3/C4/C5 migration rowsC3-02、C5A-01 等创建参数契约背景docs/architecture.mdartifact creation contractsWeb/Android 上传矩阵捕获证据docs/android/web-compat-seam-closure.md护栏测试tests/_guardrails/test_web_android_public_behavior_inventory.py核心钉住测试tests/unit/test_creation_conformance.py、tests/unit/test_chat_characterization.py、tests/unit/test_research_import_helpers.py、tests/unit/android/test_notes_frontend_parity.py、tests/e2e/test_android_notes_conformance.py【免费下载链接】notebooklm-pyUnofficial Python API and agentic skill for Google Gemini Notebook. Full programmatic access to NotebookLMs features—including capabilities the web UI doesnt expose—via Python, CLI, and AI agents like Claude Code, Codex, and OpenClaw.项目地址: https://gitcode.com/GitHub_Trending/no/notebooklm-py创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考
返回列表