ACL学习总结(AscendCL) 分享一份自己学习ACL的笔记,由于内容超出了最大的字符上限(共69168),所以选择直接分享一份语雀链接,链接在图片下方,大致内容如下,欢迎各位大佬前来互相交流学习: 简单来说,ACL的作用就是用来在昇腾(Ascend)设备上做小模型推理加速,例如yolo、ResNet等等各类模型,应用场景比如视频监控实时判定等等 https://www.yuque.com/u48066541/db8sl3/evem2liq09npe599?singleDoc# 《AscendCL》 上面给出的链接里代码案例使用的是C++,这里在给一份包含详细注释的Python版本 Resnet50 import os import acl import numpy as np from PIL import Image #定义常量 ACL_MEM_MALLOC_HUGE_FIRST = 0 ACL_MEMCPY_HOST_TO_DEVICE = 1 ACL_MEMCPY_DEVICE_TO_HOST = 2 #定义模型对象 class Net: def __init__(self,model_path): #构造函数 #acl初始化,device指定 self.device_id = 0 ret = acl.init() ret = acl.rt.set_device(self.device_id) #模型加载,返回模型的ID self.model_id, ret = acl.mdl.load_from_file(model_path) #创建空白的模型描述信息,获取模型描述信息的指针地址 self.model_desc = acl.mdl.create_desc() #通过模型ID,获取模型的描述信息,填充到model_desc ret = acl.mdl.get_desc(self.model_desc,self.model_id) #创建输入输出数据集 #创建输入数据集 self.input_dataset, self.input_data = self.prepare_dataset("input") #创建输出数据集 self.output_dataset, self.output_data = self.prepare_dataset("output") #实现输入输出数据集类型的创建 def prepare_dataset(self,io_type): #准备数据集 if io_type == "input": #获取模型的输入个数 io_num = acl.mdl.get_num_inputs(self.model_desc) #变量引用函数对象 acl_mdl_get_size_by_index = acl.mdl.get_input_size_by_index else: #获取模型的输出个数 io_num = acl.mdl.get_num_outputs(self.model_desc) acl_mdl_get_size_by_index = acl.mdl.get_output_size_by_index #创建aclmdlDataset类型的数据,描述模型的输入或输出 dataset = acl.mdl.create_dataset() datas = [] #循环创建输入或输出数据类型,把每个输入或输出(buffer)装入对应的dataset中 for i in range(io_num): #从模型描述信息中通过索引获取所需的buffer内存大小 buffer_size = acl_mdl_get_size_by_index(self.model_desc,i) #申请buffer_size大小的buff内存,并把申请的内存地址指针给buffer buffer, ret = acl.rt.malloc(buffer_size,ACL_MEM_MALLOC_HUGE_FIRST) #从内存创建大小为buffer_size的buffer对象,存储到buffer指针中 data_buffer = acl.create_data_buffer(buffer,buffer_size) #将buffer数据添加到数据集中 _, ret = acl.mdl.add_dataset_buffer(dataset,data_buffer) datas.append({"buffer": buffer, "data": data_buffer, "size": buffer_size}) return dataset,datas def forward(self,inputs): #模型推理函数 #遍历所有输入,拷贝到对应的buffer内存中 input_num = len(inputs) for i in range(input_num): #将输入数据转换为字节码,方便使用 bytes_data = inputs[i].tobytes() #创建指向字节码对象的指针地址 bytes_ptr = acl.util.bytes_to_ptr(bytes_data) #先将图片数据从host侧传到device侧,用于推理(申请device?) ret = acl.rt.memcpy(self.input_data[i]["buffer"], #目标地址 device self.input_data[i]["size"], #目标地址大小 bytes_ptr, #源地址 host len(bytes_data), #源地址大小 ACL_MEMCPY_HOST_TO_DEVICE #cp模式:host to device ) #模型推理,传入需要推理的模型id,输入输出数据集合 ret = acl.mdl.execute(self.model_id,self.input_dataset,self.output_dataset) #对推理的输出数据进行数据后处理,输出top5置信度的类别编号 inference_result = [] #遍历 输出集合output_data 里的所有元素,获取集合元素与其索引 for i,item in enumerate(self.output_data): #申请host侧内存 self.buffer_host, ret = acl.rt.malloc_host(self.output_data[i]["size"]) #将数据从device侧返回host侧 ret = acl.rt.memcpy(self.buffer_host, #目标地址 host self.output_data[i]["size"], #目标地址大小 self.output_data[i]["buffer"], #源地址 device self.output_data[i]["size"], #源地址大小 ACL_MEMCPY_DEVICE_TO_HOST #cp模式:device to host ) #从host侧内存地址获取(转换)bytes对象 参数1:需要转换的对象(内存地址) 参数2:数据的大小(要读取的字节数) bytes_out = acl.util.ptr_to_bytes(self.buffer_host,self.output_data[i]["size"]) #按照float32格式将数据转为numpy数组,即将这些字节数据视为32位浮点数来解释 data = np.frombuffer(bytes_out, dtype=np.float32) inference_result.append(data) #将得到的data转换为numpy数组,一维 vals = np.array(inference_result).flatten() #对结果进行softmax转换,使其变为概率分布 vals = np.exp(vals) vals = vals / np.sum(vals) return vals def transfer_pic(input_path): #数据预处理,每个模型的不同,预处理的操作也会有所不同 #将路径转换为绝对路径 input_path = os.path.abspath(input_path) #使用 PIL的 Image.open() 方法打开图像文件,返回一个Image对象,用于图像裁剪等后续处理 with Image.open(input_path) as image_file: #resnet50模型,图片裁剪为224*224,当然也不是一定要按照模型规定的大小来 img = image_file.resize((224,224)) #转换为float32类型的ndarray img = np.array(img).astype(np.float32) #根据ImageNet图像的均值和方差,进行图像归一化操作 img -= [123.675, 116.28, 103.53] img /=[58.395, 57.12, 57.375] #色域通道转换,RGB→BGR img = img[:, :, ::-1] #resnet50模型为彩色通道在前,即HWC→CHW img = img.transpose(2,0,1) #返回并添加batch通道 return np.array([img]) def print_top_5(data): #数据后处理,展示top5概率 #argsort函数:升序排序,[::-1]代表反转索引数组,即升序改为降序,[:5]代表截取前五个元素 top_5 = data.argsort()[::-1][:5] print("======== top5 inference results: =============") for i in top_5: print("[%d]: %f" % (i,data[i])) def __del__(self): #析构函数,按照资源申请的相反顺序进行销毁,回收内存 #释放host内存 ret = acl.rt.free_host(self.buffer_host) #销毁输入输出数据集 #先销毁dataset内的buffer for dataset in[self.input_data,self.output_data]: #确保dataset不为空 while dataset: #从列表末尾移除一个元素 item = dataset.pop() #销毁buffer数据 ret = acl.destroy_data_buffer(item["data"]) #释放buffer内存 ret = acl.rt.free(item["buffer"]) #销毁输入输出数据集 ret = acl.mdl.destroy_dataset(self.input_dataset) ret = acl.mdl.destroy_dataset(self.output_dataset) #销毁模型描述文件 ret = acl.mdl.destroy_desc(self.model_desc) #卸载模型 ret = acl.mdl.unload(self.model_id) #释放device ret = acl.rt.reset_device(self.device_id) #acl去初始化 ret = acl.finalize() #主调函数入口 if __name__ == "__main__": #类对象 resnet50 = Net("/home/work/zxy/pyACL/om/cls/resnet50_310P3.om") #数据 image_paths = ["/home/work/zxy/pyACL/data/cls/dog1_1024_683.jpg"] #遍历数组集合 for path in image_paths: #调用数据预处理函数,对每个数据进行预处理 image = transfer_pic(path) #将数据按照每个输入的顺序构造list传入,调用推理函数进行推理 result = resnet50.forward([image]) #数据后处理 print_top_5(result) del resnet50 1 个帖子 - 1 位参与者 阅读完整话题
.env文件里面有些密钥啥的 连接字符串啥的 然后当时ai直接回复我说这些有风险 虽然可能有点小题大做 但是如何禁止呀 Grok给的最靠谱的一个方案(官方)说需要Copilot订阅 3 个帖子 - 2 位参与者 阅读完整话题
问了官方半天不回 文档写的不太清楚 MiniMax 开放平台文档中心 音乐生成 (Music Generation) - 接口概览 - MiniMax 开放平台文档中心 此页面对您有帮助吗? | MiniMax 开放平台 API 接口能力概览,包括语言、视频、语音、图像、音乐和文件管理等多模态能力。 5 个帖子 - 3 位参与者 阅读完整话题
微软正在为 Windows 11 的搜索体验推出两项颇为关键的改进,在实际体验后,外界普遍认为微软终于开始正视用户对搜索功能的真实需求。 第一项变化已经通过 2026 年 5 月的可选更新 KB5089573 向普通用户推送,微软表示,更新后系统可以在本地索引中“仅凭两个字符就找到并优先显示文件”。 第二项改进目前则面向 Windows 11 预览版 Build 26300.8553 和 Build 26220.8544 推出,名为“按子串搜索”(Search by Substring),针对的是困扰多年的“复合文件名难搜”问题。 微软举例称,像 “MeetingNotesApril”、“ProjectStatusReport” 这样的复合名称文件,未来只要输入 “april” 或 “status” 等中间片段就可以被快速检索到,而不再必须从文件名开头输入。 长期以来,Windows 搜索在处理复合文件名时表现不佳,除非用户输入文件名开头或极为接近的字符串,否则往往很难出现正确结果,这也迫使不少用户刻意调整命名习惯来“迁就”搜索引擎。 过去用户搜索时不得不在文件名中尽量写得更全、更“规整”,以降低错过结果的风险,如今由于索引逻辑的变化,不再需要为搜索而反复编辑文件名。 在新的可选更新安装完成后,用户只需输入任意两个字符,就有机会直接看到目标文件出现在搜索结果顶部,例如输入 “XP” 即可快速定位 Windows XP 壁纸文件,而在旧版中同样操作只会先显示 XPS Viewer 这类程序。 在改进启用之前,用户往往不得不输入诸如 “xp bliss” 这样的更长关键字,才能将特定图片从一堆无关结果中“挖”出来。 不过,由于微软采取了“受控功能推出”(Controlled Feature Rollout)机制,即便安装了 5 月可选更新,有些设备暂时仍无法体验到上述搜索增强,需要等待后台逐步开关功能。 同样地,“按子串搜索”目前也仅在 Windows Insider 试验和 Beta 通道中开放,微软计划在未来数月内再逐步向所有用户推广。 之所以强调子串搜索,是因为现实中的文件命名远非规范化模板,用户经常将月份、项目名、缩写、版本号和各种临时记号混杂在一起,导致日后难以准确记忆命名开头。 测试中,未启用改进时必须记住文件名起始部分才有可能在结果中出现,而启用新功能后,只要输入“May”“Menu”“Comparison”等任一片段,系统就能立即返回 “StartMenuComparisonMay” 这样的文件,这被形容为“2026 年搜索本该有的样子”。 这轮针对搜索的优化也是微软今年 3 月在《我们对 Windows 质量的承诺》博客中所作承诺的一部分,彼时公司称将“让搜索更快地找到重要内容,更清晰地呈现应用、文件和设置,让用户快速抵达正确结果”。 此前,外界还注意到微软已承诺,Windows 11 搜索将不再在多数情况下强行把网页结果排在本地应用和文件之前,这被视为终结“搜索 Terminal 却先跳出电影《终结者》或《终极代码》之类内容”的长期笑柄。 这些都是迫切需要的调整,因为在过去几年里,桌面端搜索对日常工作流程的帮助持续缩水。 值得注意的是,搜索质量并非 Windows 11 搜索体验的唯一问题,其默认界面本身也被批评为“过度拥挤”。 在长期的迭代过程中,搜索界面塞进了越来越多的网页内容、AI 工具入口、热门趋势、Microsoft Rewards 提示以及 Bing 联动组件,而这些并不是多数用户打开搜索时真正关心的东西。 用户打开搜索,往往只是想启动应用、查找文件、打开设置,或快速完成一次计算,但界面却被当作 Bing 的推广平台。 例如,搜索界面默认会显示“每日图片”和“每日问答”。 在这些杂项中,“热门应用”尚有一定价值,因为其通常基于个人使用习惯进行排序,但搜索界面中被突出展示的 AI 工具则显得多余。 文中提到,这些所谓“AI 工具”(如 Create with AI、Search with AI、Image Creator、Video Creators)在体验上并不优于竞争对手,却仍高调占据搜索界面位置。 更糟糕的是,这些推荐组件本身是基于网页技术实现,而非原生 UI 元素,不仅点击后直接跳转到 Bing.com,本身也被视为“内存杀手”。 具有讽刺意味的是,最“干净”的官方搜索界面,竟然来自任务栏上的“询问 Copilot”(Ask Copilot):这个在 2025 年末首次展示的功能,虽然在外界口碑不佳,但其搜索界面却只有一条悬浮输入栏,几乎不含任何视觉噪音。 “询问 Copilot”此后曾从预览版中悄然移除,一度毫无声响,直到近期有面向“前沿企业”的微软文档被曝光,暗示这项功能将于 2026 年年中重返 Windows 11 任务栏。 这从反面证明微软其实完全有能力打造简洁、快速、直观的搜索体验,只是此前在产品策略上选择了充当 Bing 和各种在线服务的入口。 与此同时,微软也在修补 Windows 11 其他界面层面的“粗糙感”。 例如,2025 年 12 月,搜索界面的高度和比例被重新调整,以匹配重新设计后的开始菜单,解决了两者尺寸不一致导致的“半成品感”。 查看评论
如图,我使用 zsh + opencode, 用 /exit 退出时会在命令行留下几个字符,跟网上找到的情况好像都有点不一样,有没有佬友遇到过 1 个帖子 - 1 位参与者 阅读完整话题
我有一个Rar的压缩包,我在加密的时候可能多输了一个字符或者少输入了一个字符 字符范围:9876543210. 有大佬能帮忙解出来吗,重谢 【超级会员V6】通过百度网盘分享的文件:第三轮.rar 链接: 百度网盘 请输入提取码 复制这段内容打开「百度网盘APP 即可获取」 14 个帖子 - 7 位参与者 阅读完整话题
力扣 LeetCode 3093. 最长公共后缀查询 - 力扣(LeetCode) 3093. 最长公共后缀查询 - 给你两个字符串数组 wordsContainer 和 wordsQuery 。 对于每个 wordsQuery[i] ,你需要从 wordsContainer 中找到一个与 wordsQuery[i] 有 最长公共后缀 的字符串。如果... 思路 多亏佬友前几天题目中出现的前缀树算法,用这个答题简单多了。 因为要 最长公共后缀中字符串最短的,多个字符串长度相同时取最最先出现的 ,所以前缀树的结构要加上 最短长度 minLen 和 最早出现 idx 。 然后将 wordsContainer 中的字符串倒序插入到前缀树中,遍历 wordsQuery 用同样的找到最长公共后缀的 node ,取出idx即可。 代码 class Solution { private static class TrieNode { TrieNode[] children = new TrieNode[26]; int idx = Integer.MAX_VALUE; int minLen = Integer.MAX_VALUE; } public int[] stringIndices(String[] wordsContainer, String[] wordsQuery) { TrieNode root = new TrieNode(); for (int i = 0; i < wordsContainer.length; i++) { insert(root, wordsContainer[i], i); } int n = wordsQuery.length; int[] ans = new int[n]; for (int i = 0; i < n; i++) { ans[i] = query(root, wordsQuery[i]); } return ans; } private int query(TrieNode node, String str) { int len = str.length(); for (int i = len - 1; i >= 0; i--) { int o = str.charAt(i) - 'a'; if (node.children[o] == null) { return node.idx; } node = node.children[o]; } return node.idx; } private void insert(TrieNode node, String str, int idx) { int len = str.length(); if (node.minLen > len) { node.minLen = len; node.idx = idx; } else if (node.minLen == len && idx < node.idx) { node.idx = idx; } for (int i = len - 1; i >= 0; i--) { int o = str.charAt(i) - 'a'; if (node.children[o] == null) { node.children[o] = new TrieNode(); } node = node.children[o]; if (node.minLen > len) { node.minLen = len; node.idx = idx; } else if (node.minLen == len && idx < node.idx) { node.idx = idx; } } } } 1 个帖子 - 1 位参与者 阅读完整话题
佬友们,刚才在X音上刷到说Claude Code故意往请求里塞随机的字符破坏第三方API的缓存命中,这是真的吗? 10 个帖子 - 6 位参与者 阅读完整话题
力扣 LeetCode 3121. 统计特殊字母的数量 II - 力扣(LeetCode) 3121. 统计特殊字母的数量 II - 给你一个字符串 word。如果 word 中同时出现某个字母 c 的小写形式和大写形式,并且 每个 小写形式的 c 都出现在第一个大写形式的 c 之前,则称字母 c 是一个 特殊字母 。 返回 word 中 特殊字母 的数量。 示例 1: 输入:word = "aaAbcBC" 输出:3 解释: 特殊字母是 'a'、'b' 和 'c'。 示例 2: 输入:word = "abc" 输出:0 解释: word... 思路 跟昨天的题目差不多,统计小写字母时加个是否已出现大写字母的判断即可。 代码 class Solution { public int numberOfSpecialChars(String word) { int n = word.length(); int[] cnt = new int[26]; for (int i = 0; i < n; i++) { int o = word.charAt(i) - 'A'; if (o > 26) { if ((cnt[o - 32] & 1) == 1) { cnt[o - 32] |= 4; } cnt[o - 32] |= 2; } else { cnt[o] |= 1; } } int ans = 0; for (int i = 0; i < 26; i++) { if (cnt[i] == 3) { ans++; } } return ans; } } 1 个帖子 - 1 位参与者 阅读完整话题
tp-cmo32e7zifwduiq41xue25do84deqa6pqwlz947rn6gbwygqLdodododo 佬友们 自行把最后的大写及后续的字符串干掉就能正常用了 1 个帖子 - 1 位参与者 阅读完整话题
力扣 LeetCode 3120. 统计特殊字母的数量 I - 力扣(LeetCode) 3120. 统计特殊字母的数量 I - 给你一个字符串 word。如果 word 中同时存在某个字母的小写形式和大写形式,则称这个字母为 特殊字母 。 返回 word 中 特殊字母 的数量。 示例 1: 输入:word = "aaAbcBC" 输出:3 解释: word 中的特殊字母是 'a'、'b' 和 'c'。 示例 2: 输入:word = "abc" 输出:0 解释: word 中不存在大小写形式同时出现的字母。 示例 3: 输入:word =... 思路 按题目要求记录好大小写是否出现过就好。 代码 class Solution { public int numberOfSpecialChars(String word) { int n = word.length(); int[] cnt = new int[26]; for (int i = 0; i < n; i++) { int o = word.charAt(i) - 'A'; if (o > 26) { cnt[o - 32] |= 2; } else { cnt[o] |= 1; } } int ans = 0; for (int i = 0; i < 26; i++) { if (cnt[i] == 3) { ans++; } } return ans; } } 2 个帖子 - 2 位参与者 阅读完整话题
力扣 LeetCode 1871. 跳跃游戏 VII - 力扣(LeetCode) 1871. 跳跃游戏 VII - 给你一个下标从 0 开始的二进制字符串 s 和两个整数 minJump 和 maxJump 。一开始,你在下标 0 处,且该位置的值一定为 '0' 。当同时满足如下条件时,你可以从下标 i 移动到下标 j 处: * i + minJump <= j <= min(i + maxJump, s.length - 1) 且 * s[j] == '0'. 如果你可以到达 s 的下标 s.length -... 思路 首先题目明显的无后效性,可以用动态规划作答。 容易想到遍历一遍,从 [minJump..maxJump] 进行递推,但是看数据量 1 <= minJump <= maxJump < s.length <= 10^5 大概率会超时。线段树似乎可以,但是太重了。 逆向思考下,如果能够到达 x 点,那么在 [x-maxJump..x-minJump] 至少有一个点可以到达。这点借助前缀和可以在 O(1) 的复杂度内解决,那动态规划的方程式就由 O(n^2) 降到了 O(n) 。 代码 class Solution { public boolean canReach(String s, int minJump, int maxJump) { int n = s.length(); // 是否可以跳到坐标 boolean[] dp = new boolean[n]; dp[0] = true; // 到当前坐标为止能够到达的坐标数量 int[] prefix = new int[n]; // 本来prefix[0]应该设为1,但是这样需要把[0..minJump)都设为1,所以在不影响计算的情况下此处保持0 // prefix[0]= 1; // 初始化边界,[minJump..maxJump]只要为0均可到达 for (int i = minJump; i <= maxJump; i++) { prefix[i] = prefix[i - 1]; if (s.charAt(i) == '0') { dp[i] = true; prefix[i] += 1; } } // 只要前面 [i-maxJump..i-minJump] 范围内有点能够到达此处就能到达 for (int i = maxJump + 1; i < n; i++) { prefix[i] = prefix[i - 1]; if (s.charAt(i) == '0' && prefix[i - minJump] - prefix[i - maxJump - 1] > 0) { dp[i] = true; prefix[i] += 1; } } return dp[n - 1]; } } 1 个帖子 - 1 位参与者 阅读完整话题
在l站薅了几个佬友的mimo用,结果转过头来发现自己的mimo完全用不完 base64字符编码两次:ZEhBdFkyUnJaamxyWmpSeVpYaG9Obmw0YUd0a1pXdHNkbUl5YW5ZNU5XSnpOV3QwWldOaU9IRmtOSGxyY21obmN6ZDU= https://token-plan-cn.xiaomimimo.com/v1 https://token-plan-cn.xiaomimimo.com/anthropic 话说L站为什么不加个颜文字表情库 2 个帖子 - 2 位参与者 阅读完整话题
就是现在是不是正文回复不得小于16字符来着,我看见很多人有那种一小块的“回复”,这种“回复”不能被回复,感觉像“定向弹幕”,这种是怎么发的啊 4 个帖子 - 4 位参与者 阅读完整话题
大家好,现在使用 CLI 的 ai agent ,用它通过各种图表、流程图的方式来展示解决方案 但因为中英文混搭,所以 ascii 输出的时候经常会出现漂移 请问大家碰到这种情况是怎么解决的 ps.单独的 mermaid/excalidraw 这种暂时不考虑,我只想在终端下能够快速展示
大家好,现在使用 CLI 的 ai agent ,用它通过各种图表、流程图的方式来展示解决方案 但因为中英文混搭,所以 ascii 输出的时候经常会出现漂移 请问大家碰到这种情况是怎么解决的 ps.单独的 mermaid/excalidraw 这种暂时不考虑,我只想在终端下能够快速展示
大家好,现在使用 CLI 的 ai agent ,用它通过各种图表、流程图的方式来展示解决方案 但因为中英文混搭,所以 ascii 输出的时候经常会出现漂移 请问大家碰到这种情况是怎么解决的 ps.单独的 mermaid/excalidraw 这种暂时不考虑,我只想在终端下能够快速展示
大家好,现在使用 CLI 的 ai agent ,用它通过各种图表、流程图的方式来展示解决方案 但因为中英文混搭,所以 ascii 输出的时候经常会出现漂移 请问大家碰到这种情况是怎么解决的 ps.单独的 mermaid/excalidraw 这种暂时不考虑,我只想在终端下能够快速展示
本帖使用社区开源推广,符合推广要求。我申明并遵循社区要求的以下内容: 我的帖子已经打上 开源推广 标签: 是 我的开源项目完整开源,无未开源部分: 是 我的开源项目已链接认可 LINUX DO 社区: 是 我帖子内的项目介绍,AI生成、润色内容部分已截图发出: 是 以上选择我承诺是永久有效的,接受社区和佬友监督: 是 以下为项目介绍正文内容,AI生成、润色内容已使用截图方式发出 目前我在之前的讨论中,讨论过关于 claude code 缓存的问题 OpenAI Response 缓存字段分析,OpenCode,Codex,CC-Switch,中转厂商,New API 开发调优 经过我的一些调研,OpenAI Response 接口可以使用 prompt_cache_key 的字段来路由启用缓存,提供命中率。 目前 OpenCode 中已经可以通过 setCacheKey 的字段来设置了,然后 codex cli 是默认带这个功能的,并且不知道什么原因 codex cli 的支持貌似是最好的。当然他是原生支持,肯定最好。 举个例子就是我用 rightcodes 家的 … 对于 gpt 模型和 claude code 上缓存的思考 / auto prefix cache vs. cache control 开发调优 关于之前的帖子,我有过关于 claude code 缓存的疑问,我后面更新了一下,决定再开一篇帖子,转述一遍,从评论区转述我自己哈哈 原来的帖子如上,考虑到内容一样不太行,决定不在原来的帖子上发评论了 目前已确认,是 claude code 本身的问题,只能命中少数缓存是因为 claude code 的缓存是 anthropic 他们自定义的一套,他们采用了分段分块缓存的策略,就是 c… 后来根据我的后续的一些搜索和观察,发现在 Bilibili 上还有小红书上,都或多或少有不少前辈发现了这个问题,并且提出了一些解决方案,这里我就不再把他们的东西搬移过来了 大致的意思是这样的 claude code 为了统计用户的请求特征,会在每次请求前面,添加一个 cch 的字段,这是一个随机字符串。 然后国产模型会主动兼容 claude code 应用 他们在服务端识别到这个随机字符串会给他过滤掉,于是他们就能命中缓存。 这也是为什么他们官方都提供了 /anthropic 这种 claude code 兼容端点 而现在的协议转换网关( anthropic message → openai response),比如 new api,cc-switch 之类的。 会自动把这个随机字符串,转换打包进 openai 协议中的 system prompt 中 从而导致 openai 协议这边无法高效命中缓存,因为在 system prompt 这边就 被随机字符串污染 了, 只能命中 前面的一些 tools skills 的固定文本 然后各位前辈提出来的解决方案就是,在 claude code 里面设置环境变量 CLAUDE_CODE_ATTRIBUTION_HEADER 为 "0" 就可以了。 这个是从泄露出来的 2.1.88 版本的 claude code 源码中 找到的 使用了这个环境变量后,会在应用客户端这里,取消这个 cch 字符串的注入,进而也能命中缓存 接下来是我个人的带货环节 我做(vibe coding)了一个 github 开源项目 github.com GitHub - brilliantrough/responses-api-compat-proxy: Compatibility proxy for OpenAI-style Responses API... Compatibility proxy for OpenAI-style Responses API providers with SSE normalization, fallback routing, and local admin tools. 这个项目是我买了市面上很多家的 openai codex 的 api 但是因为毕竟来路不明,这些 api 都不稳,用起来总是会报错。这也很正常,毕竟人力维护。但是会使人大动肝火,乳腺不畅 于是乎我自己 vibe coding 了一个自动 fallback 的微型中转平台 对外暴露一个统一的 openai response 接口 在 json 文件中从前往后配置各家的 api 运行时自动从前往后进行请求,成功则返回,失败则 fallback 另外我还设置了熔断,比如某一家的 api 请求失败了,禁用几分钟,状态置为 open,就是 fallback 的时候会跳过这个条目 几分钟时间过后状态置为 half_open 然后后面的请求继续 fallback 到 half_open 的条目时不会跳过,尝试重新请求,一旦成功,则把条目状态置为 close close 就代表条目的状态正常,继续使用 平台摆铺的策略就是 前面放一些量大管饱的平台,比如 rawchat micu ikun 等等 后面放一些稳定的平台,比如几个小伙伴一起拼拼凑凑的 openai pro 账号之类的 这个项目和这篇小文章的联系就是 我发现了存在 cch 随机字符串这个行为,并且认为让客户端去进行一个环境变量的更改,是一件非常困难的事情, 毕竟这类信息都是少数人的智慧,大多数人仍然被蒙在鼓里 于是乎我在我这个 response proxy 层,从 system prompt 中拿到这个 cch ,然后把他 strip 掉 效果就是 确实能够让客户端(claude code)不用做任何更改就能实现 openai 模型的高效缓存 和其他项目的联动,作用到 claude code,opencode,codex 当中 我直接在本地另外起一个 sub2api 项目,然后把这个 response 接口接进去 sub2api 的 openai response 接口接入到 new api 中, 取名为 codex 分组 ,进行统一分发 将 sub2api 的接口接入给 cc-switch,用于协议转换 之所以使用 cc-switch 再套一层,是我觉得 sub2api 实现的模型转换还有些小问题,懒得折腾了,干脆再套一层 cc-switch 专职做这个, response -> anthropic 这一块的转换我还挺放心的 将 cc-switch 的 anthropic 接口接入到 new api 中, 取名为 codex anthropic 分组 ,进行统一分发 codex 分组 用于 opencode, codex 中,能够通过 prompt_cache_key 进行高效缓存 codex anthropic 分组 用于 claude code 中,能够通过 cc-switch 自动添加 prompt_cache_key 的功能,以及 response proxy 自动 strip cch 字段的功能,实现高效缓存 至此,我的项目管理如下 在 sub2api 中我用于全局的监控 在 reponse proxy 中,我能看到各个上游的调用情况 在 new api 中,我能看到 codex 分组和 codex anthropic 分组的调用情况 以下是战绩汇报 在这些监控的同时,我收获了一个 在 Agent 中调用 4000 次 ,可能 只出现 1 次报错甚至 0 次报错 的高贵体验(SLA 级别服务!!!芜湖!!起飞!!!) 当然上面这个是在 Agent 中调用就是这样的体验 如果你分发到了 chat 端 以及 gpt-5.5 本身还有一些 258K 上下文限制 以及 openai 官方还有报错的情况下 那么还是会出现一些正常报错的,这就比较难避免了,不过我的目标场景也不是要解决这些问题,官方出错我还能咋地呢? 再说,上次 官方出现连续报错的时候 ,我这个项目一天下来的 几千次 监控,仍然就 只出现了一两次报错 ,因为 有连续的 fallback 规则兜底 , 总能 fallback 到当前不报错的那个请求 (继续吹牛)当时啊,我正在用我的这个 api,然后我的同学跑过来跟我说他的 plus 老是报错是怎么回事。我一打开我常年混迹的各家中转API的QQ群才发现,到处都在哀嚎。但是呢,我用起来完全没有感觉这天出现了大变故。算是直观感受到这个项目带给我的容灾能力,心里美滋滋~~ 总结部分 总之一方面,claude code 应用端会自动注入随机字符串,可以通过 CLAUDE_CODE_ATTRIBUTION_HEADER 设置为 "0" 来解决。 另一方面,主包做了一个微型网关,用于 response proxy,其中规避了这个随机字符串的问题,当然更多的是为了 SLA 体验。 欢迎大家来发表评论和见解 1 个帖子 - 1 位参与者 阅读完整话题