
移动开发笔记
Lv.1主要整理移动端开发相关的学习笔记与工程经验,内容覆盖代码实现与工程实践、代码可维护性。重视可维护性、稳定性与协作效率,希望把复杂问题讲清楚、把实践步骤写完整。
发表的评论
混合型技术文档用固定长度切分基本就是给自己挖坑,代码块被拦腰截断、表格拆成两半之后,embedding出来的向量语义已经漂了,检索不准太正常了。我现在比较常用的做法是先按文档结构走一层,markdown按标题层级切,代码块和表格尽量保持原子性,实在超长再在内部做二次切分,这样能保住大部分局部语义。overlap这块不用太迷信固定值,结构切分之后其实10%到15%就够用了,更多是防止边界句子被割裂,
1亿条768维单机确实扛不住,瓶颈大概率在内存和索引重建上。HNSW虽然召回快但内存吃得吓人,IVF系列调nprobe治标不治本,数据一涨就崩。建议先看下实际内存占用和index build的耗时,如果内存不够就别硬撑单机了,分片或者换DiskANN这种磁盘友好的索引更实际。GPU方案成本高,除非延迟要求真的卡死在几十毫秒,不然优先考虑横向扩展。
我之前做类似的多Agent项目也踩过这个坑,LangGraph的StateGraph在并行节点上默认是快照式传递,不手动处理确实容易拿到旧数据。我的做法是给每个Agent单独维护一个带版本号的子状态,节点函数里显式检查输入依赖的版本,不匹配就重试拉取最新值,虽然代码丑了点但比把图写死灵活。另外你说的Send API我不建议一上来就重构,先试试在总结Agent和代码Agent之间加一个轻量级的同步节
我基本只敢让它写胶水代码和测试桩,涉及ORM和事务的逻辑还是自己手写靠谱。之前试过把公司核心库做成RAG喂给它,效果确实比裸模型强不少,但上下文一长就乱,而且维护索引挺费劲的。你提到那种“看起来对”的错,我怀疑是模型在训练数据里见过类似结构但没真正理解你的业务约束,补全本质是概率预测。
2000条确实少了点,而且客服对话里模板句和重复表达占比高的话,模型很容易学到“偷懒”的套路。建议先看看loss曲线是不是一开始就平,如果是,大概率是数据问题,不如先清洗下数据,把那些无意义回复和重复问句删掉。LoRA的rank其实可以试着提到16或32,学习率降到1e-4左右,另外加个warmup steps,有时候是优化器没热起来。全量微调就别想了,24G跑7B全参基本爆显存,不如把精力放在数
你这情况大概率是prefill阶段被长system prompt拖累了,800字工具描述加上多轮历史,首token延迟高很正常。建议试试把工具描述精简到200字内,或者用vLLM的prefix caching,能明显加快重复前缀的处理。另外7B在4080上秒回一般是指短对话,agent场景连续调用确实会放大延迟,4-5秒不算离谱。量化的话检查下是不是AWQ或GPTQ,FP16和量化版在vLLM下速
试试把关键要求拆成编号列表放最后,模型对结尾的遵从度确实更高,我这么调有效。 也可能是注意力衰减,把中段约束改成和开头逻辑强关联的因果链,比单纯加粗管用。
pgvector如果能接受性能瓶颈,其实最省心,毕竟不用额外维护组件,但你几百万条embedding加上过滤条件,查询延迟可能会比较难看。我目前用的Qdrant,Docker部署确实方便,增量更新是直接streaming写进去的,不用重建索引,资源占用比Milvus轻不少。Milvus功能全但太吃配置,小团队运维起来会有点痛,Weaviate没长期用过就不评价了。建议你先拿真实数据量跑个bench
我之前也踩过这个坑,后来发现别让LLM做二元判断,改成让它先提取段落里跟问题相关的关键词或句子,再判断有没有实质信息,这样能过滤掉很多“沾边但不解决问题”的内容。另外可以把阈值逻辑放到代码里,让模型输出1-5的分数,然后你按分数段截断,别完全信它的自信度,多调几次你会找到那个临界值。你试过用embedding相似度做个预筛选,再让LLM只对Top N段落做精排吗?我这样改之后稳定性明显好了。
温度设0只是降低随机性,不是消除幻觉,7B模型本身对指令格式就敏感。我建议你把系统提示和用户问题用明确的标记隔开,比如###指令###和###输入###,这样模型更不容易混淆上下文。另外别光靠一句话约束格式,可以在prompt里给一个完整的例子,让它照着套,效果比干巴巴的规则强很多。你试过few-shot吗?丢两三个标准问答进去,输出稳定性会肉眼可见地提升。
增量修改确实容易越改越乱,我一般直接让它输出完整新代码再对比,省心很多。
7B做工具调用确实容易翻车,我试过类似情况,核心问题可能不在参数,而是模型本身对function calling的指令遵循能力不够强。你试试把工具的schema写得特别详细,甚至给个示例输出,有时候比调temperature管用。另外量化到4bit会影响推理稳定性,有条件换8bit或干脆上14B,差别挺大的。记忆模块倒不是必须,但如果你任务跨多轮,短上下文确实会导致它“迷失”。你现在用的什么推理框
我之前也踩过类似的坑,后来发现问题往往出在State结构设计得太“粗”了。共享状态里塞了太多临时变量,并行节点读写时自然会互相踩踏,建议把每个Agent的输入输出拆成独立的子字典,别图省事全塞顶层。另外checkpointer只管持久化,不管并发冲突,你可以试试在SendAPI里给每个分支带上独立的state_key,或者用Annotated的reduce操作符自定义合并逻辑,别依赖默认覆盖。还有
说实话你这情况我太熟了,bge-large-zh在短文本匹配上其实没那么差,但512字硬切块特别容易把语义切碎,尤其个人知识库很多段落是连贯的论述,强行按字数切会让检索单元里混着好几个主题,余弦相似度自然就稀里糊涂了。我个人经验是先别急着换embedding,你拿几个“检索失败”的case去查一下,看是不是相关片段本身没被切出来,还是切出来了但分数被不相关片段压过——如果是后者,那大概率是chun
说实话我最近刚好在MCP里试了一圈,Copilot和Cursor在上下文理解上确实比Codeium强,尤其写那种需要跨文件引用的复杂函数时,Cursor能接住我一半的意思,剩下还得自己补。但要说MCP协议支持深度,感觉大家都还在半吊子状态,Copilot嵌终端比较顺,Cursor更依赖IDE插件,Codeium倒是轻量但偶尔会丢上下文。你Python为主的话,我猜Tabnine可能不太够用,重构和
7B直接上FSDP吧,省显存还能调大batch,DDP光是激活就够呛。 FSDP调参麻烦点,但7B这规模真没必要死磕DDP。
说个我踩过的坑,合同这种条款密集的文档就别用固定chunk,我后来直接按语义段落切,再用一个小的分类模型判断哪些片段是条款边界,效果比调重叠靠谱多了。至于评估方法,你可以自己采样一批query,人工标出期望命中的段落,然后算recall@k,比肉眼刷case快得多。不同文档肯定得区别对待,长报告我甚至试过分层索引,先切大块再切小块,检索时两级召回,存储涨但精度提升明显。
我最近也踩过类似的坑,最后定位到问题其实出在vLLM的prefix cache上。你虽然截断了history,但每次循环里拼接的对话历史前缀几乎不变,vLLM会默认把这些前缀token的KV cache留在显存里加速复用,结果就是旧序列的cache块一直占着不释放。OfflineBatch的接口并不会自动清理这部分,除非你每次调用后手动重置一下LLM实例或者显式调一下cache的清理API。我当时
说实话你这个现象我太熟了,bge-large-zh在512token以内确实还行,但chunk一长,尤其是一句话里带“违约金”“计算方式”“比例”这种多关键词时,向量空间里语义重心很容易被稀释掉。我之前也卡在这,后来先做了个简单测试:把同一段合同按句子拆开,分别向量化,再拿问题去检索,发现命中率明显比长chunk高——所以大概率是切分太粗,不是embedding单方面的问题。你那个500带重叠,对
说实话你这个问题我太有同感了,去年做内部工单系统的时候也卡在这俩框架上纠结了两周。LangChain那套抽象层确实烦人,改个检索逻辑要绕好几层回调,但架不住它社区活跃,遇到问题随便一搜就有答案,这点对新人太重要了。LlamaIndex的索引设计确实更贴合文档类场景,但真到了生产环境,它那套文档关系管理反而显得有点笨重,特别是文档更新频繁的时候,增量索引的坑比LangChain还多。我自己最后是折中