news 2026/10/5 9:29:52

AI Agent 接入 Redis 缓存实战:四层缓存架构与性能优化

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
AI Agent 接入 Redis 缓存实战:四层缓存架构与性能优化

1. AI Agent 接入 Redis 缓存,到底在解决什么问题

做 AI Agent 开发的人,迟早会撞上一堵墙:响应慢、Token 烧得快、并发一上来就崩。我最早搭的一个基于大模型的问答 Agent,单机跑着挺舒服,一旦放到线上让几十个人同时用,接口平均响应从 2 秒飙到 15 秒,账单也跟着翻倍。后来把 Redis 缓存这一层加进去,同样的机器配置,QPS 翻了将近 6 倍,Token 消耗直接砍掉四成。这篇文章就把我这套“AI Agent + Redis 缓存”的实战思路完整拆开讲,从为什么缓存、缓存什么、怎么缓存,到踩过的坑和排查技巧,全部摊开说。

先说清楚这套东西适合谁看。如果你正在用 LangChain、LangGraph、Spring AI、扣子这类框架搭 Agent,或者自己用 Python、Rust、Java 手搓 Agent 编排逻辑,并且已经遇到了性能瓶颈,那这篇内容基本能直接抄作业。如果你还在 Agent 的 Demo 阶段,也可以先了解缓存层的设计思路,等业务量起来再落地,避免后期重构。核心关键词就三个:AI Agent、Redis、缓存,但真正值钱的是这三个词背后的工程取舍。

很多人对 AI Agent 的缓存有个误解,觉得“缓存不就是把结果存起来下次直接返回吗”。放在普通 Web 接口上这话没错,但 Agent 的场景复杂得多。一个 Agent 的一次调用,内部可能包含多轮 LLM 推理、多次工具调用(Tool Calling)、向量检索、外部 API 请求,每一环的耗时和成本都不一样。你缓存整个最终答案,命中率可能很低;你缓存中间步骤,又要处理状态一致性问题。所以 Agent 的缓存设计,本质上是一道分层缓存 + 键设计 + 失效策略的综合题,Redis 只是那个最趁手的工具。

我个人的判断是:没有缓存层的 AI Agent,只能算玩具;有了合理缓存层的 AI Agent,才具备上线扛并发的资格。下面我从整体设计思路开始,一层层往下拆。

2. 整体设计思路:Agent 的缓存该分几层

2.1 为什么不能只缓存最终结果

先讲个我踩过的坑。最开始我图省事,直接把用户问题做 key,Agent 最终回答做 value,塞进 Redis 就完事了。上线第一天命中率看着还行,大概 30%,但很快发现问题:用户问“帮我查下北京明天天气”,和“北京明天天气怎么样”,语义完全一样,字符串却不同,缓存直接 miss。更麻烦的是,Agent 的回答里往往带时间戳、随机 ID、个性化称呼,同一个问题两次回答的字符串根本对不上,你拿什么做 key 都别扭。

所以 Agent 缓存的第一个认知升级是:缓存粒度要下沉,不能只盯着最终输出。一次 Agent 调用可以拆成几个可缓存的层次,每一层的命中收益和失效风险都不一样。

2.2 四层缓存结构拆解

我把 Agent 的缓存分成四层,从外到内依次是:

缓存层级缓存内容典型 TTL命中收益失效风险
L1 语义缓存用户问题的语义向量 → 最终答案10 分钟~1 小时极高,直接省掉整条链路中,语义相似但意图不同会答错
L2 推理缓存Prompt 哈希 → LLM 原始输出5~30 分钟高,省掉最贵的 LLM 调用低,Prompt 一致输出基本一致
L3 工具缓存工具名 + 参数哈希 → 工具返回1 分钟~数小时中高,省掉外部 API 调用取决于数据实时性
L4 检索缓存查询向量 → 向量库召回结果数分钟~数小时中,省掉向量检索耗时低,知识库不常变

这四层不是每层都必须上,而是根据你的业务特点选。比如做客服 Agent,L1 语义缓存收益最大;做数据分析 Agent,L3 工具缓存更关键;做 RAG 知识问答,L4 检索缓存能省不少向量库压力。

2.3 为什么选 Redis 而不是本地缓存

有人会问,用进程内的本地缓存(比如 Python 的functools.lru_cache、Java 的 Caffeine)不行吗?行,但有几个硬伤。第一,Agent 服务通常要水平扩容,本地缓存各存各的,命中率被稀释得厉害,10 个实例每个都只有 1/10 的命中机会。第二,本地缓存没法做统一的失效控制,你更新了知识库,还得挨个实例去清。第三,Agent 的中间状态(比如多轮对话的 session)本来就需要一个共享存储,Redis 顺手就承担了。

Redis 的优势在于:亚毫秒级读写、丰富的数据结构、原生 TTL、支持分布式锁和原子操作。尤其是它的SETEX、HSET、ZADD这些命令,配合 Agent 的各种缓存形态非常顺手。至于redis command timed out这类报错,后面排查章节我会专门讲。

2.4 键设计:Agent 缓存最容易翻车的地方

键设计是整套方案的地基。我见过太多人用question直接当 key,结果中文、空格、大小写、标点一变就 miss。我的做法是统一做规范化 + 哈希:

import hashlib import re def normalize_query(text: str) -> str: # 去首尾空白、转小写、压缩连续空白、去掉常见标点 text = text.strip().lower() text = re.sub(r'\s+', ' ', text) text = re.sub(r'[,。!?,.!?;;::]', '', text) return text def build_cache_key(prefix: str, *parts) -> str: raw = "|".join(str(p) for p in parts) digest = hashlib.sha256(raw.encode("utf-8")).hexdigest()[:16] return f"agent:{prefix}:{digest}"

这样agent:l2:9f3a2b...就是一个稳定的推理缓存键。前缀分层的好处是,你可以用SCAN agent:l2:*批量清理某一层,而不用KEYS *把 Redis 堵死(KEYS在生产环境是禁忌,后面细说)。

提示:键名一定要带业务前缀和层级标识,否则后期运维根本分不清哪个 key 属于哪个 Agent、哪一层缓存,清理时只能全库删,风险极大。

3. 核心细节解析:Redis 数据类型怎么选、TTL 怎么定

3.1 五种数据类型在 Agent 缓存里的分工

Redis 的数据类型不是随便挑的,选错了要么浪费内存,要么操作别扭。结合 Agent 场景,我总结了一张对照表:

数据类型Agent 场景用途关键命令注意事项
String单条推理结果、工具返回SETEX/GET大 value 要压缩,别超 1MB
Hash多轮对话 session、Agent 状态HSET/HGETALL字段多时注意内存碎片
List对话历史、消息队列LPUSH/LRANGE用LTRIM控制长度
Set去重、已处理任务标记SADD/SISMEMBER适合幂等控制
ZSet带权重的缓存淘汰、热度排序ZADD/ZRANGEBYSCORE适合做 LRU 近似

举个实际例子。多轮对话的 session,我用 Hash 存:HSET agent:session:{sid} role user content "...",再配一个EXPIRE设 30 分钟。这样每轮对话追加字段,读取时HGETALL一次拿全,比用多个 String 键省内存,也方便整体过期。

3.2 TTL 到底设多久:一个可落地的计算方法

TTL 设太短,命中率上不去;设太长,数据陈旧答非所问。我的经验公式是:

TTL = 数据可容忍陈旧时间 × 0.7

比如天气数据,用户能接受 10 分钟内的旧数据,那 TTL 设 7 分钟。为什么乘 0.7?因为要给缓存穿透和雪崩留缓冲,避免大量 key 在同一秒集中过期。同时我会给 TTL 加一个随机抖动:

import random def ttl_with_jitter(base_ttl: int, jitter_ratio: float = 0.2) -> int: jitter = int(base_ttl * jitter_ratio) return base_ttl + random.randint(-jitter, jitter)

这样 600 秒的 TTL 实际落在 480~720 秒之间,过期时间被打散,Redis 不会出现“整点雪崩”。这个技巧在 Agent 高并发场景下特别重要,我实测过,不加抖动时,每到整点缓存集中失效,后端 LLM 调用量会瞬间冲高 3 倍。

3.3 序列化方式:别让 JSON 拖慢你的 Agent

缓存 value 的序列化方式直接影响读写速度和内存占用。常见几种对比:

  • JSON:可读性好,跨语言通用,但体积大、解析慢,适合调试期。
  • MessagePack:二进制、体积小、速度快,Python/Java/Rust 都有成熟库,我线上首选。
  • Protobuf:体积最小、速度最快,但需要定义 schema,改字段麻烦,适合结构稳定的场景。
  • Pickle:Python 专用,快但跨语言差,还有安全风险,不建议存不可信数据。

我线上用的是 MessagePack,同样的推理结果,JSON 序列化后 2.3KB,MessagePack 只有 1.4KB,读取耗时从 0.8ms 降到 0.3ms。别小看这点差距,Agent 一次调用可能读十几个缓存键,累积起来就是几十毫秒。

注意:无论用哪种序列化,都要在 value 里带一个版本号字段。Agent 的 Prompt 模板、输出格式一旦升级,旧缓存就失效了,靠版本号可以快速区分,避免读到不兼容的旧数据。

3.4 缓存穿透、击穿、雪崩:Agent 场景的三种死法

这三个词是缓存面试题的常客,但放到 Agent 场景有特殊表现:

缓存穿透:用户故意问一些不存在的问题,每次都绕过缓存打到 LLM。Agent 场景下这特别烧钱,因为每次穿透都是一次真实的 LLM 调用。我的对策是空值缓存:查不到结果时,也往 Redis 写一个__EMPTY__标记,TTL 设短一点(比如 60 秒),挡住短时间内的重复穿透。

缓存击穿:某个热点 key 刚好过期,瞬间大量请求同时打到后端。Agent 里常见于热门问题。对策是互斥锁重建:只让一个请求去调 LLM,其他请求等待或返回旧值。用 Redis 的SET NX实现:

def get_with_lock(redis_client, key, rebuild_func, ttl=600): value = redis_client.get(key) if value is not None: return value lock_key = f"{key}:lock" # 抢锁,10 秒自动释放,防止死锁 if redis_client.set(lock_key, "1", nx=True, ex=10): try: value = rebuild_func() redis_client.setex(key, ttl, value) return value finally: redis_client.delete(lock_key) else: # 没抢到锁,短暂等待后重试读缓存 time.sleep(0.05) return redis_client.get(key)

缓存雪崩:大量 key 同时过期,后端被瞬间打垮。对策就是前面说的TTL 加随机抖动,再配合多级缓存兜底。

4. 实操过程:从零搭一套 Agent 缓存层

4.1 环境准备与 Redis 安装

先解决环境。Linux 上装 Redis 最省事:

# Ubuntu/Debian sudo apt update sudo apt install redis-server -y sudo systemctl enable redis-server sudo systemctl start redis-server # 验证 redis-cli ping # 返回 PONG 就说明通了

macOS 上用 Homebrew:

brew install redis brew services start redis redis-cli ping

Windows 用户建议直接用 Docker,避免各种编译问题:

docker run -d --name redis-agent \ -p 6379:6379 \ -v /data/redis:/data \ redis:7-alpine \ redis-server --appendonly yes --maxmemory 2gb --maxmemory-policy allkeys-lru

这里几个参数值得说:--appendonly yes开启 AOF 持久化,防止重启丢缓存(缓存丢了其实也能重建,但 Agent 的 session 丢了用户体验差);--maxmemory 2gb限制内存上限,防止 Redis 吃光机器内存;--maxmemory-policy allkeys-lru是淘汰策略,内存满了按 LRU 淘汰,Agent 缓存场景用这个最合适。

4.2 连接池配置:别每次请求都新建连接

新手最容易犯的错是每次操作都redis.Redis()新建连接,高并发下连接数爆炸。正确做法是用连接池:

import redis from redis import ConnectionPool pool = ConnectionPool( host="127.0.0.1", port=6379, db=0, max_connections=50, socket_timeout=2, socket_connect_timeout=1, health_check_interval=30, decode_responses=False, # 二进制序列化时设 False ) redis_client = redis.Redis(connection_pool=pool)

socket_timeout=2这个参数很关键。Agent 调用链本来就长,如果 Redis 卡住不返回,整个请求会被拖死。设 2 秒超时,超时后走降级逻辑(直接调 LLM),保证服务可用性。health_check_interval=30让连接池定期探活,避免拿到已经断掉的死连接。

4.3 封装一个通用的 Agent 缓存装饰器

把缓存逻辑封装成装饰器,业务代码里一行就能用:

import functools import msgpack from typing import Callable def agent_cache(prefix: str, ttl: int = 600, jitter: float = 0.2): def decorator(func: Callable): @functools.wraps(func) def wrapper(*args, **kwargs): key = build_cache_key(prefix, *args, *sorted(kwargs.items())) cached = redis_client.get(key) if cached is not None: return msgpack.unpackb(cached, raw=False) result = func(*args, **kwargs) real_ttl = ttl_with_jitter(ttl, jitter) redis_client.setex(key, real_ttl, msgpack.packb(result, use_bin_type=True)) return result return wrapper return decorator # 使用示例 @agent_cache(prefix="l2", ttl=900) def call_llm(prompt: str, model: str = "gpt-4"): # 真实的 LLM 调用逻辑 return llm_client.invoke(prompt, model=model)

这个装饰器的精髓在于:参数自动参与 key 生成,TTL 自动加抖动,序列化统一用 MessagePack。业务方完全不用关心缓存细节,专注写 Agent 逻辑就行。

4.4 语义缓存的实现:向量相似度匹配

L1 语义缓存是收益最高但也最难做的一层。核心思路是:把用户问题转成向量,在 Redis 里找相似度超过阈值的已有问题,命中就直接返回答案。Redis 7 之后可以用RediSearch模块做向量检索,或者用 Redis 的 ZSet 做近似。

简化版实现(用向量库配合 Redis 存映射):

import numpy as np SIMILARITY_THRESHOLD = 0.92 def semantic_cache_lookup(question: str, embed_func, redis_client): vec = embed_func(question) # 从 Redis 取出候选问题的向量集合(实际项目用 RediSearch 更高效) candidates = redis_client.hgetall("agent:semantic:index") best_score, best_key = 0, None for key, packed_vec in candidates.items(): cand_vec = np.frombuffer(packed_vec, dtype=np.float32) score = np.dot(vec, cand_vec) / (np.linalg.norm(vec) * np.linalg.norm(cand_vec)) if score > best_score: best_score, best_key = score, key if best_score >= SIMILARITY_THRESHOLD: return redis_client.get(f"agent:l1:{best_key.decode()}") return None

阈值 0.92 是我反复调出来的经验值。设 0.95 太严,很多同义问法命中不了;设 0.85 太松,会把“北京天气”和“上海天气”误判成同一个问题。这个值跟你的 embedding 模型强相关,换模型一定要重新标定。

提示:语义缓存一定要加“意图校验”兜底。我遇到过用户问“帮我取消订单”和“帮我查询订单”,向量相似度高达 0.94,差点误命中。后来加了一层意图分类器,只有意图一致才允许命中语义缓存。

4.5 分布式锁:防止 Agent 重复执行副作用操作

Agent 里有些操作不能重复执行,比如下单、发消息、写数据库。这时候 Redis 分布式锁就派上用场:

import uuid def acquire_lock(redis_client, lock_name: str, timeout: int = 10): token = str(uuid.uuid4()) ok = redis_client.set(f"lock:{lock_name}", token, nx=True, ex=timeout) return token if ok else None def release_lock(redis_client, lock_name: str, token: str): # Lua 脚本保证原子性:只有 token 匹配才删 lua = """ if redis.call('get', KEYS[1]) == ARGV[1] then return redis.call('del', KEYS[1]) else return 0 end """ redis_client.eval(lua, 1, f"lock:{lock_name}", token)

释放锁必须用 Lua 脚本,保证“判断 token + 删除”是原子操作。否则可能出现:A 的锁超时自动释放,B 拿到锁,A 执行完又把 B 的锁删了,导致并发失控。这个坑我在早期项目里踩过,排查了半天才发现是锁释放逻辑有问题。

5. 常见问题与排查技巧实录

5.1 redis command timed out 到底怎么排查

redis command timed out; nested exception is io.lettuce.core.RedisCommandTimeoutException这个报错,用 Lettuce 客户端(Spring 生态常见)的人几乎都遇到过。我总结的排查顺序是:

  1. 先看是不是大 key。用redis-cli --bigkeys扫一遍,如果某个 key 有几 MB,读写它就会阻塞。Agent 缓存里常见的是把整个对话历史塞进一个 String,越滚越大。对策是拆分或用 List + LTRIM 控制长度。

  2. 再看是不是慢命令。SLOWLOG GET 10看最近 10 条慢查询。KEYS *、HGETALL大 Hash、SMEMBERS大 Set 都是重灾区。生产环境禁用KEYS,改用SCAN游标遍历。

  3. 检查网络和连接池。redis-cli --latency看网络延迟,如果延迟本身很高,那是网络问题。连接池太小也会导致等待超时,max_connections要按并发量估算。

  4. 看 Redis 内存和淘汰。INFO memory看used_memory是否接近maxmemory,如果频繁触发淘汰,读写都会变慢。INFO stats看evicted_keys,如果这个数一直涨,说明内存不够,要么扩容要么调淘汰策略。

我遇到过一次线上超时,最后定位到是某个 Agent 把 5MB 的向量检索结果整个塞进了一个 String,每次读都要几秒。改成只缓存 top-10 结果后,问题消失。

5.2 缓存与数据不一致怎么办

Agent 场景的不一致主要来自:知识库更新了,但 L4 检索缓存还是旧的。我的处理策略是主动失效 + 版本号。知识库更新时,发一条消息到 Redis 的 Pub/Sub 频道,所有 Agent 实例订阅后清理对应的 L4 缓存。同时给缓存键带上知识库版本号,版本一变,旧键自然失效。

# 发布失效消息 redis_client.publish("cache:invalidate", "l4:knowledge_base") # 订阅端 pubsub = redis_client.pubsub() pubsub.subscribe("cache:invalidate") for message in pubsub.listen(): if message["type"] == "message": pattern = message["data"].decode() # 用 SCAN 批量清理,避免阻塞 cursor = 0 while True: cursor, keys = redis_client.scan(cursor, match=f"agent:{pattern}:*", count=100) if keys: redis_client.delete(*keys) if cursor == 0: break

5.3 常见问题速查表

现象可能原因排查命令解决方向
命中率低key 设计不合理、TTL 太短INFO stats看 keyspace_hits/misses规范化 key、延长 TTL
内存暴涨大 key、无淘汰策略--bigkeys、INFO memory拆分 key、设 maxmemory
响应变慢慢命令、网络延迟SLOWLOG GET、--latency禁用 KEYS、优化命令
连接超时连接池太小、连接泄漏INFO clients看 connected_clients调大连接池、检查释放
数据陈旧TTL 太长、未主动失效抽样对比缓存与源数据缩短 TTL、Pub/Sub 失效
缓存雪崩TTL 集中、无抖动观察过期时间分布加随机抖动、多级缓存

5.4 几个只有踩过才知道的坑

坑一:decode_responses=True和二进制序列化冲突。如果你用 MessagePack 存二进制,连接必须设decode_responses=False,否则读出来是乱码。我一开始没注意,调试了半天以为序列化库有问题。

坑二:Redis 的EXPIRE对已存在的 key 是覆盖而非累加。想延长 TTL 要重新EXPIRE,别指望它自动续期。Agent 的 session 场景要特别注意,每次交互后手动续期。

坑三:SCAN不保证返回所有 key。它是游标遍历,期间如果有 key 增删,可能漏掉。清理缓存时如果要求严格,得配合版本号机制,别只依赖 SCAN。

坑四:集群模式下多 key 操作受限。MGET、MSET跨 slot 会报错,得用 hash tag({user}:1、{user}:2)把相关 key 映射到同一 slot。Agent 的 session 相关键建议都带同一个 tag。

坑五:别把 Redis 当数据库用。缓存就是缓存,丢了能重建。我见过有人把 Agent 的唯一状态存 Redis 且不开持久化,重启后全丢。关键状态要么落库,要么开 AOF。

6. 性能调优与并发扛压的实战经验

6.1 用 Pipeline 批量读写,减少 RTT

Agent 一次调用可能要读多个缓存键,如果一个个GET,网络往返次数太多。用 Pipeline 打包:

def batch_get(redis_client, keys): pipe = redis_client.pipeline() for key in keys: pipe.get(key) return pipe.execute()

实测下来,读 10 个键,逐个读耗时约 5ms,Pipeline 只要 1ms 左右。在高并发下这个差距会被放大很多倍。

6.2 热点 key 的本地二级缓存

有些 Agent 的热点问题会被反复问,比如“你们几点上班”。这种 key 可以在进程内再缓存一层,用 Caffeine 或cachetools,TTL 设 5~10 秒。这样绝大部分请求连 Redis 都不用访问,直接内存返回。注意本地缓存 TTL 要短,否则数据不一致窗口太大。

6.3 压测数据参考

我在 4 核 8G 的机器上做过对比测试,Agent 处理一个中等复杂度问题(含 2 次 LLM 调用 + 1 次工具调用):

方案平均响应P99 响应QPSLLM 调用次数/分钟
无缓存3.2s8.5s12720
仅 L2 推理缓存1.8s4.2s28380
L2 + L3 + L40.9s2.1s55210
四层全开0.4s1.3s78130

数据很直观:每加一层缓存,QPS 都有明显提升,LLM 调用次数大幅下降。四层全开相比无缓存,QPS 提升 6.5 倍,LLM 调用减少 82%。这就是缓存层对 Agent 成本控制的直接价值。

6.4 监控指标:上线后必须盯的几个数

缓存上线不是终点,得持续监控。我必看的几个指标:

  • 命中率:keyspace_hits / (keyspace_hits + keyspace_misses),低于 60% 就要反思 key 设计。
  • 内存使用率:used_memory / maxmemory,超过 80% 要警惕。
  • 淘汰速率:evicted_keys的增长速度,持续增长说明内存不够。
  • 慢查询数:SLOWLOG LEN,非零就要查。
  • 连接数:connected_clients,接近maxclients要扩容。

这些指标我接入了 Prometheus + Grafana,设了告警阈值。有一次命中率突然从 75% 掉到 40%,告警响了,一查是某个 Agent 的 Prompt 模板改了,但缓存 key 没带版本号,导致新旧数据混在一起。加上版本号后恢复正常。

7. 不同技术栈下的落地差异

7.1 Python 生态:LangChain + Redis

LangChain 自带RedisCache,可以直接接:

from langchain.cache import RedisCache from langchain.globals import set_llm_cache import redis set_llm_cache(RedisCache(redis.Redis(host="localhost", port=6379)))

但自带的缓存粒度比较粗,只缓存 LLM 调用,不覆盖工具和检索。我的做法是保留它做 L2,自己再实现 L1、L3、L4。

7.2 Java 生态:Spring AI + Redis

Spring AI 里可以用@Cacheable注解配合 Redis:

@Cacheable(value = "agentLlm", key = "#prompt.hashCode()", unless = "#result == null") public String callLlm(String prompt) { return chatClient.call(prompt); }

注意key的生成要稳定,hashCode()在 Java 里对同一字符串是稳定的,但跨语言就不行了。如果 Agent 是多语言混布,还是统一用 SHA-256。

7.3 Rust 生态:性能敏感场景的选择

Rust 写 Agent 的人越来越多,redis-rs是主流客户端:

use redis::Commands; let client = redis::Client::open("redis://127.0.0.1/")?; let mut con = client.get_connection()?; let _: () = con.set_ex("agent:l2:abc", "result", 600)?; let val: String = con.get("agent:l2:abc")?;

Rust 的优势是零成本抽象和内存安全,配合tokio异步运行时,单机 QPS 能比 Python 高一个数量级。但开发效率低,适合对性能极致要求的核心链路。

8. 我个人的几条实战建议

第一,缓存层要能一键降级。Redis 挂了,Agent 不能跟着挂。我的做法是加一个开关,Redis 异常时自动跳过缓存直接走原链路,同时打日志告警。可用性永远优先于性能。

第二,缓存 key 一定要带版本号。Agent 迭代快,Prompt、模型、工具都可能变,版本号是防止读到脏数据的最简单手段。我一般用v1、v2这种,升级时改一下就行。

第三,别过度缓存。有些数据实时性要求高,缓存了反而添乱。判断标准是:这个数据陈旧几分钟,用户能接受吗?能就缓存,不能就别碰。

第四,压测一定要做。我见过太多人本地跑得好好的,上线就崩。用redis-benchmark压 Redis,用locust或wrk压 Agent 接口,把 P99 和错误率摸清楚再上线。

第五,缓存命中率是核心 KPI。低于 60% 说明设计有问题,要么 key 太细,要么 TTL 太短,要么业务本身就不适合缓存。定期复盘命中率,比什么都重要。

这套方案我在三个不同规模的 Agent 项目里落地过,从日活几百到日活几十万,核心思路没变,变的只是参数和层级取舍。Redis 这个工具本身不复杂,难的是想清楚缓存什么、缓存多久、怎么失效。把这三个问题回答好,你的 Agent 就能从“能跑”进化到“能扛”。

版权声明: 本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若内容造成侵权/违法违规/事实不符,请联系邮箱:809451989@qq.com进行投诉反馈,一经查实,立即删除!
网站建设 2026/10/5 9:28:50

959张药品盒检测数据集实战:VOC与YOLO格式解析及小样本训练避坑指南

简介:这是一份面向目标检测初学者与药品识别应用开发者的感冒药品分类检测数据集,可用于训练和验证药品包装检测模型,适用于零售药房自动盘点、智能货架识别等场景。压缩包共约2000个文件,以960个VOC格式xml标注、962个YOLO格式tx…

作者头像 李华
网站建设 2026/10/5 9:28:34

Agent结构化输出实战:用LangChain与Pydantic打通最后一公里

在Agent开发这条路上摸爬滚打了一段时间之后,我发现一个特别有意思的现象:很多人能把Agent跑起来,能调工具、能对话、能查资料,但一到要拿它的输出对接下游系统,就全乱套了。模型返回一段洋洋洒洒的自然语言&#xff0…

作者头像 李华
网站建设 2026/10/5 9:28:32

基于YOLOv5+OpenPose的人体姿态识别算法工程实践与优化

简介:一套结合OpenPose与YOLOv5的人体姿态识别完整项目,面向具备计算机视觉与机器学习基础的开发者、研究者,用于解决多人关键点检测、实时姿态估计及工程化部署等实际问题。压缩包共716个文件、约85.59MB,内部以C头文件/源文件&a…

作者头像 李华
网站建设 2026/10/5 9:28:18

通达信主力吸筹猛攻指标:源码拆解与实战用法

很多人拿到所谓“主力吸筹猛攻指标”,第一反应是看它能不能让自己买在起爆点。我的看法很直接:这类指标真正的价值,不在于那个红红绿绿的信号箭头,而在于它背后对“量、价、资金”三者关系的刻画方式。今天我把自己多年折腾通达信…

作者头像 李华
网站建设 2026/10/5 9:27:57

从闭源到开源:本地部署NeoHorse-Jev-4B决策模型实战指南

最近圈子里讨论最多的模型,除了各种Chat类大模型,还有一个叫Jev的决策模型。它不写诗、不聊天,专干“判断”这活,比如“这条工单该分给哪个组”“这笔交易要不要人工审核”。老实说,第一次看到Demo的时候我也觉得只是又…

作者头像 李华
网站建设 2026/10/5 9:27:16

让AI编程从“快”到“可靠”:Superpowers工作流全解析

在AI编程工具越来越普及的圈子里,Superpowers这个名字最近被频繁提起。它不是某个大厂发布的新IDE,也不是又一款“AI编程软件”,而是一套针对AI编程代理设计的开源技能与工作流集合。我最初接触它,是因为自己用命令行AI写代码时觉…

作者头像 李华