RAG4Spice开发随笔
本学期有一门课,需要写hspice 做数字后端的仿真。众所不周知,这个仿真语言十分小众,现有大模型根本做不到正确输出。但本人又是究极懒狗,不想查语法之类,刚好了解到rag的技术,遂决定在ai辅助下做一下开发。
开始的构想十分美好:把lab pdf丢给程序,直接输出每个任务的代码,直接跑一下就交上去,就可以迅速把作业水掉了。当然,做为第一个原型,应当首先验证rag系统是否能够运行。所以第一步,先把整个基础结构搭出来,完成输入一张任务截图→OCR提取图中内容→根据内容查找→查找返回结果整合交给llm输出代码的workflow。完成这一步也花了不少功夫,尤其是刚产生这个想法的时候实际对rag的流程也是一知半解,embedding模型,向量数据库选型之类都是llm辅助下完成的(当然它也选得很好),在claude code的大力加持之下终于完成了这一步。
而从这个小原型到前文中提到的美好构想,显然仍然需要大费周章。lab pdf 里面什么都有,除了具体任务的介绍还有环境配置课程介绍之类,OCR之后自然是乱七八糟,直接一股脑丢给大模型填满上下文实在是很烂的选择。因此想到用一个长上下文的小模型做任务分解。为了在前端上渲染出分解好的任务,必须控制输出为json格式。json的设计,除了必须有的id和title之外,还加了任务简介(description)以及该任务涉及的知识(knowledge)。
需要注意的是,现有的大模型(即使是多模态)在电路图识别上效果都不怎么好,因此电路图这部分只能让human in the loop了——由用户自己把电路图相关信息输进去。岔开一嘴说,这就充分体现了我们Verilog这类电路描述语言的优势。电路图是给人看的,大模型还是看这类语言比较好。因此我觉得电路如果能用mermaid那类的语言来表示,大模型处理电路问题的能力应该 能提升一大截。
任务分解后,用户就可以直接点击生成代码生成了,api request发给llm,前端再渲染出结果,这一部分也没啥好说的。
还是着重说一下里面使用的rag技术吧(其实也没什么好说),对pdf进行处理之后用langchain中的分块函数分块,500个字符一块,每个块之间留50个字符的重叠,然后就是经典的embedding,计算余弦相似度,返回最相似的3个块。没有reranking,也没有混合检索这类很fancy的trick,因为其实对于查语法也实在是够用了。我的需求其实只是大模型针对每个任务帮我搭一个框架,然后我改一改交作业而已。
写到这里它做为一个个人练手的toy项目,个人觉得它的历史使命已经完成了。当然还有一些可以优化的地方,比如它读不到我们实验服务器上面pmos和nmos的网表信息,因此写出来的器件定义常常是错的之类。但感觉这样的提升也是有限,有这样的时间,还不如我自己上手改一改呢。
写完项目本着不浪费的原则,就写简历上去找rag和agent相关的实习去了。然后显然被拷打。实际上我觉得这个项目有意思的与其说是rag相关,不如说是任务分解agent的思路。单就rag而言,其实算不上有多少技术含量。同时,实习/工业界会更看重一些性能指标,这就涉及到了需要测试rag本身结构的性能——而这个项目之中,显然也是没有的。从这个角度,也可以看出自己玩票和学术/工业界项目的区别。
不过也有好处,算是通过项目让我了解了很多rag和agent相关的知识。同时对于设计agent流程,有了一点自己的见解。
除此之外,它还促使我进行了一些思考:我真正在意的是项目开发之中的什么部分?前文没有说到的是,项目开发的过程中,我和claude code花了许多时间和token去重构api-key设置的部分,从一开始将其设计为环境变量的一部分,到最后的在前端UI上渲染为类似cherry studio的url+api key。我似乎并没有对rag的底层结构做很多的优化,而是很在意与用户交互的部分。或者说,这是我没有提前设计如何评估rag性能导致的?因为没有提前评估,所以导致无法显式地看到rag的性能,因此既没有动机也没有思路进行优化。之前自己写的项目大多是所见即所得的前端项目,之后,也需要考虑这一点。
总之,还是要学习,沉淀!
最后,项目已经开源在Github:https://github.com/Oscillater/RAG4Spice