吾爱破解 - 52pojie.cn

 找回密码
 注册[Register]

QQ登录

只需一步,快速开始

查看: 1245|回复: 17
收起左侧

[其他原创] ChatGPT 浏览器效率插件:对话可视化为图谱及时间线,把握对话脉络快速定位消息,

  [复制链接]
Roberick 发表于 2026-2-5 16:36
本帖最后由 Roberick 于 2026-2-5 16:44 编辑

ChatGPT Graph Navigator

titu.png

仓库链接: https://github.com/Robbings/chatgpt-graph-navigator

希望能够得到您的Star


一、为什么我们需要非线性对话?

相比于Gemini,ChatGPT支持通过修改提问或者回答,产生新的对话分支,并且每一个分支都可以被保存和重新访问。

intro1.png

我个人非常喜欢这个功能。因为复杂问题的解决包含了不断地假设,试错和分支探索 ,而这个功能让多分支的图谱式对话成为可能。

举个栗子,比如搞科研或者开发一个项目的时候让GPT生成方案,它会提供多个选择,针对每一个方案我需要并行地讨论,然后确认如何选择。如果纯线性对话,一方面后续很难定位和复盘,另一方面,假设我最终选定一套方案,其他方案的大量对话就会变成无用的上下文,干扰模型思考和后续的复盘。而方案开始实施后我也会遇到很多问题需要处理,这些问题有些彼此相关,有些彼此无关,这时我也会使用分支功能,每个分支解决一个独立的问题。

所以在进行复杂对话的时候,如果采用线性对话,会有诸多弊端,比如:

  • 📉 “上下文污染”问题:  当你在同一个对话流中按顺序尝试不同方案时,无关的上下文和失败的尝试会不断堆积。这种“噪音”不仅消耗 Token 配额,还会干扰模型的注意力,使其难以针对你当前的策略提供最精准的分析。
  • 🔀 “并行探索”的刚需:  为了获取最佳结果,你往往需要对对话进行“分叉”——通过修改 Prompt 或重新生成回复来测试不同的路径。在线性界面中,管理这些“平行宇宙”简直是一场灾难。你很容易忘记思路是在哪里分岔的,也记不清哪个分支产出了最佳结果。
  • 🧠 逻辑混乱,定位困难:  试图在脑海中复盘 20 分钟前的 Prompt 与刚刚写好的新变体之间的逻辑关系,是一件极度消耗精力的事情。

ChatGPT Graph Navigator 专为解决此问题而生。  我们将你的分支可视化,帮助你隔离上下文以获取更纯净的模型输出,同时让你原本复杂的推理结构变得井井有条。

二、功能介绍

main_feature.png

核心能力一览:

  • 🎨 两种界面: 选择 侧边栏 (Sidebar) 享受常驻的沉浸式工作流,或使用 悬浮窗 (Floating Window) 进行随叫随到的轻量化查看。
  • 👁️ 两个可视化视图:
  • 图谱视图 (Graph View): 采用思维导图结构,助你一眼掌握对话“全局”与逻辑脉络。
  • 时间线树 (Timeline Tree): 采用 Git 风格的垂直树状图,精准追踪每一次细微的修改与分支。
  • ⚡ 导航: 点击任意节点即可 直接跳转 至对应分支的具体消息,瞬间还原历史上下文。
  • 🔍 搜索: 在整个对话树中快速定位特定的 Prompt 或 AI 回复,不再迷失在长对话中。
  • 🛠️ 实用工具: 内置长消息自动折叠功能,并计划持续集成更多效率工具(如导出、格式化等)。

更多功能展示

1. 侧边栏

sidepanel

侧边栏专为提升效率而生,提供两种模式以契合您的工作流:

a. 图谱模式 (Graph Mode)

掌控结构与上下文跳转的最佳选择。

  • 空间掌控: 支持自由缩放与平移,瞬间掌握对话主题的完整拓扑结构。
  • 一键跳转: 点击图谱中的任意消息节点,即可 瞬间跳转 到任意分支的任意对话,并立即恢复当时的上下文环境。
b. 时间线模式 (Timeline Mode)

精准定位与内容检索的利器。

  • 专注筛选: 信息噪音太多?切换过滤器以显示 全部问答仅问题 (Prompts) 或 **仅回答 **。非常适合快速回顾您的 Prompt 迭代历史。同时也支持点击跳转。
  • 即时搜索: 使用内置搜索栏快速定位关键词,快速定位消息,回车直接跳转。
2. 悬浮窗

float_main.png

  • 🚀 拖拽与缩放: 在屏幕任意位置访问完整的图谱/时间线视图。
  • 👻 穿透模式: 点击穿透按钮,直接与悬浮窗背后的页面进行交互,互不干扰。
  • 📌 固定与融合: 支持窗口 置顶 并自由调节 透明度
3. 长消息折叠

fold.png

  • 📂 消息自动折叠:长回复/代码块可自动或手动折叠,界面更清爽。
  • 支持自定义折叠提问或回答,可以设置折叠阈值,也可以手动折叠。

三、安装指南

🚧 敬请期待: 我们正在进行 Chrome 应用商店的审核流程,审核通过后将第一时间在此更新安装链接!

  1. 下载: 在Github下载最新的 Release 版本,或者在本贴下载压缩包。
  2. 打开扩展页: 在浏览器地址栏输入 chrome://extensions/ 并回车。
  3. 开启开发者模式: 打开页面右上角的“开发者模式”开关。
  4. 加载: 点击左上角的 “加载未打包的扩展程序” 按钮,选择下载的文件;或者直接将压缩包拖拽进入浏览器。

    四、后续计划

现在插件还在快速开发迭代的阶段,后续的计划主要包括:

  1. 节点和分支的高亮,收藏,分类等功能。
  2. 更多工具的集成,目前计划添加:对话或者消息级别的导出,其他功能如果需要欢迎issue。
  3. 图谱编辑: 删除不需要的分支或节点,以及手动编辑图谱结构,比如删除,添加节点间的连线,从而令图谱不再局限于消息结构,让逻辑更加清晰。
  4. 全局知识图谱: 实现针对项目或者自定义跨对话的更复杂的知识图谱构建和管理。
  5. 个人知识库的管理: 基于图谱构建个人的知识库,并支持知识库的管理,检索,导出,在对话中导入等功能。

五、写在最后

最后的最后,非常欢迎感兴趣的朋友们试用本插件! 目前项目还处于早期阶段,还有诸多 Bug 和不足,非常欢迎大家在 Issues 里反馈。如果觉得这个小工具对你有帮助,十分希望能得到您的一个 Star,这对我是莫大的鼓励。

如果您有新的想法非常欢迎Fork我们的项目,并提交PR!

最后最后的最后,再贴一下项目中文README的链接,项目和完整的介绍请参见:https://github.com/Robbings/chatgpt-graph-navigator/blob/master/README_ZH.md

附录:关键代码

完整代码已经上传到附件并开源在了github。

[b]#### 1. findScrollContainer - Find Scrollable Ancestor

function findScrollContainer(element) {
  let el = element.parentElement;
  while (el) {
    const style = window.getComputedStyle(el);
    const overflowY = style.overflowY;
    const isScrollable = (overflowY === 'auto' || overflowY === 'scroll')
                         && el.scrollHeight > el.clientHeight;
    if (isScrollable) {
      return el;
    }
    el = el.parentElement;
  }
  return document.documentElement;
}

[b]#### 2. isElementNearViewportCenter - Check Position

function isElementNearViewportCenter(element) {
  const rect = element.getBoundingClientRect();
  const viewportHeight = window.innerHeight;
  const elementCenter = rect.top + rect.height / 2;
  const centerZoneTop = viewportHeight * 0.25;
  const centerZoneBottom = viewportHeight * 0.75;
  return elementCenter >= centerZoneTop && elementCenter <= centerZoneBottom;
}

[b]#### 3. waitForScrollToStop - Detect Scroll End

function waitForScrollToStop(container, timeout = 1500) {
  return new Promise((resolve) => {
    let lastScrollTop = container.scrollTop;
    let stableCount = 0;
    const STABLE_THRESHOLD = 3;
    const startTime = Date.now();
    const check = () => {
      const currentScrollTop = container.scrollTop;
      if (Math.abs(currentScrollTop - lastScrollTop) < 1) {
        stableCount++;
        if (stableCount >= STABLE_THRESHOLD) { resolve(); return; }
      } else {
        stableCount = 0;
        lastScrollTop = currentScrollTop;
      }
      if (Date.now() - startTime > timeout) { resolve(); return; }
      requestAnimationFrame(check);
    };
    requestAnimationFrame(check);
  });
}

[b]#### 4. scrollUntilVisible - Main Scroll Logic

async function scrollUntilVisible(element) {
  const MAX_ATTEMPTS = 10;
  const DOM_WAIT_INITIAL = 100;
  const DOM_WAIT_MAX = 1500;
  const STUCK_THRESHOLD = 3;
  const SCROLL_TOLERANCE = 5;
  const scrollContainer = findScrollContainer(element);
  let lastScrollTop = scrollContainer.scrollTop;
  let domWaitTime = DOM_WAIT_INITIAL;
  let stuckCount = 0;
  for (let attempt = 0; attempt < MAX_ATTEMPTS; attempt++) {
    // 1. Check if already in center
    if (isElementNearViewportCenter(element)) {
      highlightElement(element);
      return true;
    }
    // 2. Scroll
    element.scrollIntoView({ behavior: 'smooth', block: 'center' });
    // 3. Wait for scroll animation
    await waitForScrollToStop(scrollContainer);
    // 4. Wait for DOM changes (lazy load)
    await waitForDOMChangeOrTimeout(scrollContainer, domWaitTime);
    // 5. Detect stuck
    const currentScrollTop = scrollContainer.scrollTop;
    const scrollDelta = Math.abs(currentScrollTop - lastScrollTop);
    if (scrollDelta < SCROLL_TOLERANCE) {
      stuckCount++;
      domWaitTime = Math.min(Math.round(domWaitTime * 1.5), DOM_WAIT_MAX);
      if (stuckCount >= STUCK_THRESHOLD) {
        highlightElement(element);
        return false;
      }
    } else {
      stuckCount = 0;
      domWaitTime = DOM_WAIT_INITIAL;
    }
    lastScrollTop = currentScrollTop;
  }
  return false;
}

[b]#### Flow

scrollToMessage(messageId)
    │
    ├─► findMessageElement(messageId)  // Find target by data-message-id or data-turn-id
    │
    └─► scrollUntilVisible(element)
            │
            ├─► findScrollContainer(element)  // Find scrollable ancestor
            │
            └─► Loop (max 10 attempts):
                    │
                    ├─► isElementNearViewportCenter() → Done if true
                    │
                    ├─► element.scrollIntoView({ block: 'center' })
                    │
                    ├─► waitForScrollToStop()
                    │
                    ├─► waitForDOMChangeOrTimeout()  // Handle lazy load
                    │
                    └─► Check stuck (scrollDelta < 5px)
                            │
                            └─► 3 consecutive stuck → Give up

chatgpt-graph-extension-v0.6.0.zip

248.06 KB, 下载次数: 18, 下载积分: 吾爱币 -1 CB

售价: 2 CB吾爱币  [记录]

插件压缩包

源码.zip

848.23 KB, 下载次数: 7, 下载积分: 吾爱币 -1 CB

售价: 2 CB吾爱币  [记录]

源码

免费评分

参与人数 4威望 +1 吾爱币 +21 热心值 +3 收起 理由
苏紫方璇 + 1 + 20 + 1 感谢发布原创作品,吾爱破解论坛因你更精彩!
iz999 + 1 我很赞同!
Issacclark1 + 1 谢谢@Thanks!
At作梦 + 1 我很赞同!

查看全部评分

发帖前要善用论坛搜索功能,那里可能会有你要找的答案或者已经有人发布过相同内容了,请勿重复发帖。

三滑稽甲苯 发表于 2026-2-5 16:44
这个雀食有用,分支太多了一个个切就很慢

免费评分

参与人数 1吾爱币 +1 收起 理由
Roberick + 1 对的对的,我就是因为手动切太麻烦了才有的这个想法

查看全部评分

_达圣 发表于 2026-2-5 19:00
交互式树状会话导图扩展是个挺方便的功能,对 ChatGPT 多轮会话爱好者来说相当有用!现在我是用油猴的目录或树状标签来定位和编排会话轮次的。
虽然能通过插件管理和切分不同分支,不过我比较好奇打印或导出多分支的所有会话时,拓扑链路如何组织?并且导出后能否独立切分某个分支以及某个节点再次导入?以及,导出后重新导入的隔离分支是否真的能做到防止上下文污染?
zhangfangyu 发表于 2026-2-5 16:46
picoyiyi 发表于 2026-2-5 16:59
有点像谷歌浏览器把gemini集成进去一样
聪本 发表于 2026-2-5 19:41
好东西!支持支持!
FQY188 发表于 2026-2-5 19:44
大佬,这个插件DK可以用么,一直使用的DK
AiGuoZhe66 发表于 2026-2-5 20:09
非常不错啊这个东西
maike9220 发表于 2026-2-6 03:38
试试这个插件 感谢了
gonga 发表于 2026-2-6 08:18
看起来不错,下载试试
您需要登录后才可以回帖 登录 | 注册[Register]

本版积分规则

返回列表

RSS订阅|小黑屋|处罚记录|联系我们|吾爱破解 - 52pojie.cn ( 京ICP备16042023号 | 京公网安备 11010502030087号 )

GMT+8, 2026-2-14 16:37

Powered by Discuz!

Copyright © 2001-2020, Tencent Cloud.

快速回复 返回顶部 返回列表