项目近况与一些想法
我的个人用AI搓的来找实习的项目(vid-lens)从上次八月初(26.8.3)更新了一下前端 UI 之后也没怎么去管了,因为7月底到八月中旬都在忙着找实习,一直是拿着旧的项目形态去面试,其实可以发现几次面试的面试官对这个项目的AI部分都没什么兴趣?好像主要拷打的都是文件处理还有消息队列的使用,而对于RAG的功能几乎没有问。
原因我觉得一个是RAG现在确实可能是比较烂大街,培训班的类似项目泛滥,各种所谓“企业级知识库”、“知识库Agent接入长期记忆”,我个人感觉的话,大部分其实不过只是调了 SpringAI 或者其他 AI 框架的 API,然后没什么工程性的处理,然后让 AI 随便写个玩具chatbot项目让人可以跟AI对对话,然后就做成课一堆人来学习了?类似的“企业级RAG”确实是层出不穷了。其二是我觉得真正的企业级RAG,可能只有少部分真的需要的厂才在认真做,觉得实习生或者应届生对于RAG可能只是了解一点点皮毛,所以就不咋问了。而且真的要“企业级”的RAG知识库,它的流程一定是更加复杂要考虑更多工程上的问题的,真正落到企业里,往往还要考虑数据处理、检索质量、权限、成本,以及持续的 Eval(评测),具体流程也得跟业务需求结合,绝对不是像培训班那样调个框架的 API 就行的。
题外话好像扯的有点多了,说回我这次更新之后的项目,我有感觉其实这次新的功能,好像本质上也是一种 RAG 范式的体现?这个 RAG 范式只是我瞎说的,我记得之前在哪看到过一篇讲RAG的文章说,RAG 其实是一种范式,为什么这样说呢,那篇文章说本质上这种在一个系统流程中按需给AI补充“外部知识”的这个过程其实就是一种RAG ,毕竟他的中文就叫检索增强生成,检索其实就是从外部找,所以像claude code那种 grep / glob 搜索文件文本或许也能算一种 “RAG范式”?
从转写问答到按需查看画面
说到我的项目,为什么说我自己感觉也是一种RAG范式,这次做的功能其实就是弥补之前最严重的问题 —— 怎么让Agent也 “看” 到视频画面。
先简要说一下我之前的项目是怎样的,其实就是把视频通过ASR转成文本,然后把这个文本喂给AI总结出摘要,然后还可以跟AI对话,根据视频内容,但是其实只是根据视频的文本来RAG而已。所以我之前的项目总结来说,能说的点其实就是两个方面上,一是后端上的文件处理和消息队列异步,二是AI相关,调用ASR以及LLM,来进行摘要和简单RAG问答。
然而,既然是“视频”,那它一定是两个层面的,那就是“视”和“听”,也就是我们看视频用眼睛看和用耳朵听,但是放到Agent(或者说AI)呢,其实我之前做的就算是“听”了,也就是视频的音频转成文本喂给LLM。
所以现在最大的难点就是怎么让Agent“看”,但是说到“看”,就又会引出一些难点,一个是,视频其实就是连续多个画面帧组成,所以把每一秒甚至更小的每一帧直接喂给多模态的LLM,显然不合理,所以现实情况应该是只选取部分给LLM;那么第二个难点又来了,如果要这样做,要怎么给LLM准确的需要的画面呢,再说的Agentic一点,怎么让AI来按需的捕捉自己要看的以及要给用户呈现的视频画面帧呢?
所以上面说了那么多,就引出了我这次主要的更新,让Agent“看”视频。我觉得之前那一版其实更像只是一个有视频文本的chatbot,其实根本算不上”Agent“,真正的Agent,从最简单的定义来说,应该是AI能感知环境获取相关上下文,并为了达到某一个目标,做出规划,进行一个不断思考-执行-观察的闭环的循环,直到达到目标或者终止条件,从而停止。
下面就开始讲一下这次的主要更新思路。
从视频内容定位到具体画面
首先需要解决的,其实是怎么知道应该看视频的哪一部分。
比如问一个教学视频:“这里展示的配置参数是多少?”转写文本里可能只有一句“大家按屏幕上的配置来就行”,真正的参数都在画面上。这个时候,即使把这句话检索得再准确,模型也没办法只靠转写回答。
我现在的处理思路,是先利用转写、已有的画面描述和 OCR 找到相关位置,再根据问题去补看对应时间附近的画面。前面的检索主要负责缩小范围,后面的视觉调用才负责查看具体细节。
不过要做到这一点,需要先补上一个之前容易忽略的问题:检索出来的文本,究竟对应视频的什么时间?
之前文本经过 ASR、拼接、语义切片之后,得到的是一组供 RAG 检索的 chunk。但 RAG 的文本块和 ASR 的音频分片并不是同一个东西,不能认为检索到了第几个 chunk,就对应第几个音频分片。重新调整一次切片策略,这种对应关系就可能完全变掉。
所以这次把来源信息保留到了检索块里,包括它来自转写、OCR 还是画面描述,对应的时间范围,以及原始分片或者画面的标识。后面的检索、Agent、引用和播放器,都沿着这份来源信息去定位。
这里还有一个限制:如果 ASR 只返回了一大段文字,没有逐句时间戳,那我只能知道它属于哪段音频,不能假装知道某句话精确出现在第几秒。时间只能粗略定位时就保留粗略范围,完全无法确认时就标记未知。
这部分看起来只是多存了几个字段,但如果来源关系不准确,后面让 Agent 按时间找画面就没有可靠的基础了。
在提问时按需补充视觉信息
有了时间定位,接下来才是让 Agent 真正去“看”。
视频处理阶段会先抽取部分画面,保存 OCR 和画面描述,作为后续检索的线索。但提前处理的时候并不知道用户会问什么,一段通用的画面描述,也不可能把所有细节都写进去。
比如它可能只描述“画面中展示了一张折线图”,但用户问的是某个年份的数值,或者两条线分别代表什么。即使之前已经处理过这张图,还是需要带着具体问题重新看。
所以这次增加了查询时的视觉调查工具 investigate_visual。Agent 可以提交需要确认的问题,以及前面已经定位到的时间范围,由后端从当前视频中抽取少量帧,再交给视觉模型查看。
以一个假设的问题为例,整个过程可以是:
用户询问视频中某张图表的具体数值
→ 检索转写或已有视觉信息,找到相关时间范围
→ 查看该范围已有的画面记录
→ 信息不足时,从原视频补充抽帧
→ 带着问题调用视觉模型
→ 根据返回的观察继续检索,或者组织回答这样,提前建立的索引和提问时的查看就能配合起来。索引帮助定位,新的视觉调用负责补充当前问题需要的细节。
当然,这个“按需”也需要有边界。不能模型觉得还没看清,就一直抽帧、一直调用 API。目前视觉调查工具会限制时间窗口数量、抽帧数量和模型调用次数;如果预算用完了,或者画面里确实看不清,就保留没有解决的问题。
至于具体抽哪几帧、如何访问原视频,还是由后端执行。模型负责提出查看需求,不能随便传一个文件路径或者其他视频,让工具直接去读。
有限的 Agent 执行循环
前面说到 Agent,这里也需要区分一下项目里现在的几种执行方式。
普通问答还是保留原来的 RAG 路径;流式 Agent 模式主要按预先定义的步骤执行。另外新增的 research 模式,才会让模型根据已有信息,在工具白名单里选择下一步动作。
比如先检索转写,发现问题涉及屏幕内容,再检索视觉证据;已有描述不够,就补看相关画面;如果不同来源对不上,再继续寻找补充信息,或者带着不确定性结束。
每次工具执行之后,结果都会回到当前研究状态,供下一次决策使用。这样才有了前面说的“执行—观察—再决定”的循环。
不过目前它仍然是一个单视频范围内的受控 Agent。步数、重新规划次数和工具调用都有约束,也没有把所有模式都做成动态规划。我觉得现阶段先把这些边界固定下来比较合适,至少出了问题,可以知道它在哪一步拿到了什么,又为什么继续往下走。
为此,这次也把一次执行、其中的步骤和工具调用分别持久化。除了最后的回答,还能保留执行状态和已经完成的结果,用来处理重复请求、失败后的恢复,以及后续排查。
这里也不是简单地失败就全部重跑。尤其是模型调用,如果外部已经执行成功,但本地还没来得及保存结果,就不能直接认为“什么都没发生”。这类状态需要单独处理,否则恢复一次可能又产生一遍调用和费用。
回答与证据的核对
让模型看到画面之后,还有一个问题:它看到的东西,真的支持最后的回答吗?
比如画面上有一张表,不代表模型读对了里面的数字;引用指向了正确时间,也不代表回答里的整句话都能从这个画面得到。
所以这次还增加了 Claim 和 Evidence 的关联记录。简单理解,Claim 是回答里提出的事实,Evidence 是支持或者反驳它的转写、OCR、画面等来源。
生成候选回答之后,会有一个单独的检查环节,重新读取引用的证据,检查它是否支持回答,并进行有限的反向检索,寻找可能的更正、例外或者冲突信息。
对于视觉证据,还会重新读取保存的画面,带着需要核对的说法调用视觉模型,而不是只拿第一次生成的画面描述再问一遍“这样说对不对”。
举个假设的例子,如果候选回答说“图中 A 的数值是 80”,核验时就要重新看图,确认画面是否真的支持这个数值。如果画面模糊、标签看不清,或者只显示了部分内容,就应该判定信息不足。
单张截图也有它的局限。它可以支持“这一帧出现了什么”,但很难证明“整个视频都没有出现什么”,更不能只靠一帧就确认一段操作的完整先后关系。
当前核验不通过的候选回答,会被拦截并返回无法充分确认的提示。不过这个检查本身仍然依赖模型,也有检索和调用预算,所以它能增加一道约束,并不等于已经证明答案绝对正确。
我觉得这里比较有意义的是,系统开始区分“模型生成了一句话”和“这句话有哪些可以回看的依据”。
视频处理与前端的完善
为了支撑前面的流程,这次也调整了原来的视频处理链路。
ASR 之前按固定时长切音频,切片边界可能刚好落在一句话中间。现在相邻分片会保留一小段重叠音频,转写完成后再对齐和去重,尽量保留边界处的上下文。同时增加了有上限的并发转写,已经成功的分片也能在重试时复用。
视觉处理也不再依赖 ASR 成功之后才继续。对于没有有效语音、主要展示屏幕操作的视频,可以用已有视觉内容建立索引;反过来,视觉处理失败时,也尽量保留转写问答的能力。
消息队列这边则补了不同队列的预取与并发控制、视觉处理的并发限制,以及一些任务状态和重复投递的问题。这部分和前面讲的 Agent 看起来距离比较远,但新增一条视觉处理分支之后,任务什么时候算完成、哪些结果可以复用,就都需要重新确认。
前端也围绕这些能力重新整理了一遍。现在视频工作台里可以查看播放器、转写、时间线和视觉观察记录,问答里则有引用和证据详情,并能从可定位的引用跳回原视频。
这里的视觉记录目前主要展示保存的观察文本,再通过播放器回看对应位置。对我来说,比起单纯把聊天框做得更好看,这种关联更有用:看完回答之后,可以继续检查它引用的那段视频。
另外也补了模型配置和记忆管理界面。长期记忆目前主要围绕明确的回答偏好,并提供同意、撤回和删除等控制。它可以影响回答方式,但不能替代当前视频的证据。
一点体会
这次改下来,我感觉最主要的变化,是开始认真处理“模型回答之前,究竟应该拿到什么信息”。
之前更多是把转写文本切好、存进去,提问时检索出来再交给模型。现在需要根据问题判断,是继续找文本、查看已有画面描述,还是回到原视频补看;拿到结果之后,还要保留来源,检查它能不能支持回答。
这也能接回前面我对 RAG 的那个理解:至少在这个项目里,检索和工具调用都在帮助模型获取当前缺少的外部信息。只是补充的内容从文本扩展到了带时间和来源的视觉观察,而且这个过程可以根据已有结果继续调整。
目前还有不少限制,比如采样会漏掉很短暂的画面,粗粒度的 ASR 时间也会影响定位,视觉模型仍然可能读错内容。后面还需要通过具体视频和问题去评测,看看补看画面到底解决了哪些问题,又增加了多少延迟和调用成本。
不过相比八月初主要围绕转写文本的那一版,现在至少已经把“找相关内容、按需看画面、核对回答、回到原视频”这条流程接起来了。对于一个视频项目来说,我觉得这是这次更新里比较实质的变化。