Showing Posts From
AI
OpenAI Videos API:Sora 2 视频生成 Python 调用指南
Python 调用示例 from openai import OpenAIclient = OpenAI(api_key="YOUR_API_KEY")# 提交视频生成任务(异步) job = client.videos.create( model="sora-2", prompt=""" A cinematic drone shot of Tokyo at night. Neon lights reflecting on wet streets. Ultra realistic. """, seconds=8, size="1280x720" )print(job.id)视频生成是异步任务,需要轮询状态: import timewhile True: result = client.videos.retrieve(job.id) print(result.status) if result.status == "completed": print(result.output_url) break elif result.status == "failed": print("生成失败") break time.sleep(5)图片转视频 已有参考图片时,使用 input_reference 保持人物和风格一致: job = client.videos.create( model="sora-2", prompt="The girl smiles and walks forward.", input_reference=open("girl.png", "rb"), seconds=8 )REST API curl https://api.openai.com/v1/videos \ -H "Authorization: Bearer YOUR_API_KEY" \ -F "model=sora-2" \ -F "prompt=A cute panda drinking coffee" \ -F "seconds=8"参数说明参数 说明model sora-2 或 sora-2-proprompt 视频内容描述(英文效果更好)input_reference 参考图片(可选,用于图生视频)seconds 视频时长:4、8、12 秒size 分辨率,如 1280x720、720x1280(竖屏)、1792x1024价格模型 价格Sora 2 约 $0.10 / 秒Sora 2 Pro 约 $0.30~$0.70 / 秒(随分辨率变化)生成 8 秒 1280x720 视频:Sora 2 约 $0.80,Sora 2 Pro 约 $2.40~5.60。 Prompt 写法参考 视频 prompt 建议包含:镜头类型、光线、风格、质量要求。 # 电影风格 A cinematic shot of a samurai walking through a bamboo forest. Golden sunlight. Slow motion. 35mm film. Ultra realistic.# 产品广告 A luxury mechanical watch rotating on a black reflective table. Studio lighting. 8K. Commercial quality.# 动漫风格 Anime style. Cherry blossoms falling. Girl running on a school campus. Beautiful sunset. Highly detailed.英文 prompt 效果稳定,中文可能出现理解偏差。 后端架构(完整平台) 如果需要支持多用户、异步进度追踪,典型架构: 用户请求 → FastAPI → Celery 任务队列 → OpenAI Videos API ↓ Redis 存储 job.id ↓ WebSocket 推送进度 → 前端 ↓ 完成后存储到 OSS/S3
Claude Code 配置项解析:ANTHROPIC_MODEL、showThinkingSummaries 和 skipDangerousModePermissionPrompt
配置示例 { "env": { "ANTHROPIC_MODEL": "claude-opus-4-7" }, "showThinkingSummaries": true, "skipDangerousModePermissionPrompt": true }各字段说明 env.ANTHROPIC_MODEL 指定 Claude Code 使用的模型。Claude Code 会优先读取这个环境变量,没有则使用默认模型。 合法的模型名格式: claude-opus-4-7 claude-sonnet-4-6 claude-haiku-4-5-20251001常见问题:ANSI 控制码污染 从终端输出复制模型名时,可能夹带了 ANSI 颜色控制码: opus 4.7[1m]这里 [1m] 是 \x1b[1m(加粗)的残留,程序无法识别这个模型名,会静默回退到默认模型。复制模型名后需要手动确认字段只包含纯 ASCII 字符,不含 [、]、\x1b 等控制字符。showThinkingSummaries "showThinkingSummaries": true控制是否在对话界面显示模型的思考摘要(Thinking Summary)。 注意区分:思考摘要:Claude 内部推理的简短摘要,由模型生成后可选择性暴露给用户 完整思维链:模型的逐步推理过程,不对外公开设为 true 时,Claude Code 会在回复上方展示推理摘要区域(折叠)。如果不需要可以设为 false 减少界面噪声。skipDangerousModePermissionPrompt "skipDangerousModePermissionPrompt": trueClaude Code 在执行某些高风险操作(如删除文件、运行 shell 命令、修改系统配置)时默认会弹出确认提示: This action may be dangerous. Continue? [Y/N]设为 true 后跳过该提示,直接执行。适合在受控环境下(如 CI、已备份工作目录)提升效率,不适合在生产环境使用。 完整配置结构 Claude Code 的用户配置文件通常位于:Windows: %APPDATA%\Claude\settings.json macOS/Linux: ~/.claude/settings.json{ "env": { "ANTHROPIC_MODEL": "claude-sonnet-4-6", "ANTHROPIC_BASE_URL": "https://api.anthropic.com" }, "showThinkingSummaries": false, "skipDangerousModePermissionPrompt": false, "theme": "dark" }修改配置后重启 Claude Code 生效。
波士顿房价预测是回归还是分类?多元 vs 多输出的区别
有人问:"波士顿房价预测(Boston Housing)是多分类问题吧?" 不是。这是回归问题(Regression)。顺带把三个常混的概念都拆一下——多元回归、多输出回归、多分类。 波士顿房价预测的本质 数据集大致:CRIM RM LSTAT PTRATIO ... MEDV(房价,单位万美元)0.00632 6.575 4.98 15.3 ... 24.00.02731 6.421 9.14 17.8 ... 21.60.03237 6.998 2.94 18.7 ... 33.4输入:13 个特征 输出:MEDV = 房价,一个连续值(可以是 18.3、24.7、33.4...)输出是连续数字 → 回归,不是分类。 什么时候会变成分类 自己把房价切段: 0 – 15 → "低价" 15 – 30 → "中价" 30+ → "高价"这样任务就变成了三分类——但这已经不是原始 Boston Housing 任务了,是你人为改造的。原任务永远是回归。 三个概念区分 1. 多元回归(Multiple Regression) 多个输入特征 → 一个输出。 波士顿房价就是这种:13 个特征 → 1 个房价。 import torch.nn as nnmodel = nn.Sequential( nn.Linear(13, 64), nn.ReLU(), nn.Linear(64, 1), # 输出 1 维 ) loss_fn = nn.MSELoss()"多元"指的是输入的元数(features 多),不是输出多。 2. 多输出回归(Multi-output Regression) 多个输入 → 多个连续输出。 例子:预测未来一栋房子的售价 + 出租金 + 涨幅百分比——3 个连续输出。 model = nn.Sequential( nn.Linear(13, 64), nn.ReLU(), nn.Linear(64, 3), # 输出 3 维 ) loss_fn = nn.MSELoss() # 依然是 MSE,输出是向量3. 多分类(Multi-class Classification) 输入 → 多个类别中选一个。 MNIST 手写数字识别是典型: model = nn.Sequential( nn.Linear(784, 128), nn.ReLU(), nn.Linear(128, 10), # 10 类 ) loss_fn = nn.CrossEntropyLoss() # 内部含 softmax标签是类别编号(整数 0-9),损失是 CrossEntropy。 4. 顺带:多标签分类(Multi-label Classification) 输入 → 多个类别可同时为真。 例子:一张图片可能同时含"猫、狗、汽车"三个标签。 model = nn.Sequential( nn.Linear(784, 128), nn.ReLU(), nn.Linear(128, 3), nn.Sigmoid(), # 每维独立 0-1 ) loss_fn = nn.BCELoss() # 二元交叉熵每维独立判 0 或 1。 四类对照表任务类型 输出个数 输出类型 最后一层 损失 例子多元回归 1 连续 Linear(_, 1) MSELoss Boston Housing 房价多输出回归 K 连续 Linear(_, K) MSELoss 同时预测房价 + 租金二分类 1 0/1 Linear(_, 1)+Sigmoid BCELoss 垃圾邮件识别多分类 K 类别编号 Linear(_, K) CrossEntropyLoss MNIST 数字识别多标签分类 K K 个 0/1 Linear(_, K)+Sigmoid BCELoss 图片多标签Boston Housing 数据集的争议 顺带一提——波士顿房价数据集本身有伦理问题。数据里有个特征 B(黑人人口相关变量)设计上带有种族偏见,2022 年 scikit-learn 明确 deprecated 了这个数据集: # 老代码,会警告 from sklearn.datasets import load_boston# 新推荐 from sklearn.datasets import fetch_california_housing现在教学上一般用 California Housing 或 Ames Housing 数据集替代——同样是回归任务,没有伦理争议、样本更多。 用 California Housing 的替代示例 from sklearn.datasets import fetch_california_housing import torch, torch.nn as nn from torch.utils.data import DataLoader, TensorDatasetdata = fetch_california_housing() X = torch.tensor(data.data, dtype=torch.float32) y = torch.tensor(data.target, dtype=torch.float32).unsqueeze(1)loader = DataLoader(TensorDataset(X, y), batch_size=64, shuffle=True)model = nn.Sequential( nn.Linear(8, 64), nn.ReLU(), nn.Linear(64, 32), nn.ReLU(), nn.Linear(32, 1), ) optim = torch.optim.Adam(model.parameters(), lr=1e-3) loss_fn = nn.MSELoss()for epoch in range(20): for x, target in loader: optim.zero_grad() pred = model(x) loss = loss_fn(pred, target) loss.backward() optim.step() print(f"epoch {epoch}: loss={loss.item():.4f}")跑起来 20 轮 loss 会稳定下降——回归任务的经典流程。 一句话总结 波士顿房价 = 回归任务(输出连续价格),属于"多元回归"(多个输入 → 一个输出),不是"多输出回归"、也不是"多分类"。教学优先用 California Housing 数据集,避开原数据集的伦理争议。
矩阵运算的几何意义:变换、旋转与神经网络中的线性层
矩阵是"变换机器" 标量乘法 3 x 5 = 15 只是把一个数放大 3 倍。要对一个二维点进行缩放、旋转、镜像,一个数字不够用,需要矩阵。 矩阵乘以向量 = 对该点执行一次变换: import numpy as npA = np.array([[2, 0], [0, 2]]) # 缩放矩阵x = np.array([2, 3]) # 原始点 (2, 3)print(A @ x) # [4, 6] -> 放大 2 倍常见变换矩阵 缩放(Scaling): [sx 0 ] 把 x 缩放 sx 倍 [0 sy] 把 y 缩放 sy 倍旋转 angle(Rotation): [cos a -sin a] [sin a cos a]逆时针旋转 90 度: import math theta = math.pi / 2R = np.array([[math.cos(theta), -math.sin(theta)], [math.sin(theta), math.cos(theta)]])x = np.array([1, 0]) print(R @ x) # [0, 1] — (1,0) 逆时针旋转到 (0,1)镜像(y 轴翻转): [-1 0] [ 0 1]为什么矩阵乘法是那个规则 [1 2] [5] = [1x5 + 2x6] = [17] [3 4] x [6] [3x5 + 4x6] [39]不是人为规定,而是"两次变换合并"的自然结果:矩阵的每一行定义输出的一个维度,该维度由输入向量的线性组合得出。 矩阵乘法 = 变换的复合 两个矩阵连乘等于先做 B 变换再做 A 变换: A = np.array([[2, 0], [0, 2]]) # 放大 2 倍 B = np.array([[0, -1], [1, 0]]) # 旋转 90 度C = A @ B # 先旋转再缩放 x = np.array([1, 0]) print(C @ x) # [0, 2]神经网络中的矩阵 全连接层(Linear 层)的本质就是矩阵乘法加偏置: output = W x input + b一个隐藏层有 128 个神经元、输入维度为 64: import torch import torch.nn as nnlinear = nn.Linear(64, 128) # 内部持有 weight: Tensor (128, 64) 和 bias: Tensor (128,)x = torch.randn(32, 64) # batch_size=32, input_dim=64 y = linear(x) # y.shape = (32, 128)每一层做的都是:把输入向量从一个向量空间线性映射到另一个向量空间。激活函数(ReLU、Sigmoid 等)引入非线性,才让网络能拟合复杂函数。 PyTorch 矩阵运算 import torchA = torch.tensor([[1., 2.], [3., 4.]]) B = torch.tensor([[5., 6.], [7., 8.]])# 矩阵乘法 print(A @ B) # torch.matmul print(torch.mm(A, B)) # 二维矩阵专用# 转置 print(A.T)# 行列式 print(torch.det(A)) # -2.0# 逆矩阵 print(torch.inverse(A))高维 Tensor = 批量矩阵运算 深度学习中输入通常是 3D 以上的 Tensor(batch x dim): # batch matmul:对每个样本独立做矩阵乘法 A = torch.randn(32, 4, 4) # 32 个 4x4 矩阵 B = torch.randn(32, 4, 1) # 32 个列向量 C = torch.bmm(A, B) # (32, 4, 1)torch.bmm 对 batch 中每个矩阵独立相乘,是卷积、Attention 等操作的底层基础。
PyTorch 学习路线:从 Tensor 到训练完整模型
学习阶段规划阶段 时间 目标Python 基础 3~5 天 能写循环、函数、类NumPy 基础 2 天 理解矩阵运算PyTorch Tensor 3 天 会张量计算和 GPU 迁移Autograd 自动求导 2 天 理解梯度和 backwardnn.Module 基础 3 天 会定义 MLP训练流程 3 天 会完整训练和评估CNN 5 天 图片分类Transformer 基础 7 天 理解 Attention项目实战 长期 YOLO、PointNet 等约一个月可以达到能读懂主流论文代码的水平。 为什么从线性回归开始 # 目标:给出面积和房间数,预测房价 area = [80, 100, 120, 150] rooms = [2, 3, 3, 4] price = [120, 180, 220, 300]神经网络就是找一个函数 f,使得 f(area, rooms) ≈ price。PyTorch 的作用是:定义 f 的结构(model) 自动计算 f 的梯度(autograd) 按梯度更新参数,让预测更准确(optimizer)核心训练循环 import torch import torch.nn as nn# 1. 数据 x = torch.tensor([[80, 2], [100, 3], [120, 3], [150, 4]], dtype=torch.float32) y = torch.tensor([120, 180, 220, 300], dtype=torch.float32)# 2. 定义模型 model = nn.Sequential( nn.Linear(2, 16), nn.ReLU(), nn.Linear(16, 1) )# 3. 定义 loss 和 optimizer criterion = nn.MSELoss() optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)# 4. 训练循环 for epoch in range(200): pred = model(x).squeeze() # 前向传播 loss = criterion(pred, y) # 计算 loss optimizer.zero_grad() # 清空上一步的梯度 loss.backward() # 反向传播,计算梯度 optimizer.step() # 按梯度更新参数 if epoch % 50 == 0: print(f"Epoch {epoch}: loss = {loss.item():.2f}")四步缺一不可:zero_grad() → 清除旧梯度(PyTorch 默认累积梯度) backward() → 计算所有参数对 loss 的偏导数 step() → 把参数沿梯度方向更新一步Tensor 基础操作 import torcha = torch.tensor([1.0, 2.0, 3.0]) b = torch.zeros(3, 4) c = torch.randn(2, 3) # 标准正态分布# 形状操作 c.shape # torch.Size([2, 3]) c.reshape(3, 2) c.unsqueeze(0) # 增加维度: [1, 2, 3] c.squeeze() # 去掉维度为 1 的维# GPU device = "cuda" if torch.cuda.is_available() else "cpu" c = c.to(device)常用 Loss 函数任务 Loss 调用回归 MSELoss nn.MSELoss()二分类 BCELoss nn.BCEWithLogitsLoss()多分类 CrossEntropy nn.CrossEntropyLoss()常用 Optimizer # Adam:自适应学习率,大多数情况首选 optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)# AdamW:Adam + 权重衰减,Transformer 常用 optimizer = torch.optim.AdamW(model.parameters(), lr=1e-3, weight_decay=1e-2)# SGD:经典,配合 momentum optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)保存和加载模型 # 保存权重 torch.save(model.state_dict(), "model.pth")# 加载权重 model.load_state_dict(torch.load("model.pth")) model.eval() # 推理时关闭 dropout 和 BatchNorm 的训练行为入门建议用 model.state_dict() 而不是直接 torch.save(model, ...),后者会把整个模型类序列化,跨环境加载容易出问题。
PyTorch 点云分割:PointNet 到 Point Transformer 的模型选型
三种任务类型任务 输入 输出 典型场景语义分割 点云 每个点的类别 地面/树木/汽车/行人实例分割 点云 每个点的实例 ID 区分两辆不同车辆部件分割 单个物体点云 零件归属 椅子的腿/靠背/坐垫主流模型 PointNet(最经典) 输入 N×3,直接用 MLP 逐点提取特征,全局池化后再输出分割结果: import torch import torch.nn as nnclass PointNet(nn.Module): def __init__(self, num_classes): super().__init__() self.mlp = nn.Sequential( nn.Linear(3, 64), nn.ReLU(), nn.Linear(64, 128), nn.ReLU(), nn.Linear(128, 256) ) self.cls = nn.Linear(256, num_classes) def forward(self, x): # x: [B, N, 3] feature = self.mlp(x) # [B, N, 256] out = self.cls(feature) # [B, N, num_classes] return out预测时取 argmax 得到每个点的标签: pred = out.argmax(dim=-1) # [B, N]其他模型选型模型 核心 适合场景PointNet++ 局部邻域分层学习 室内、激光雷达、工业检测DGCNN KNN 建图 + EdgeConv 精度要求高的分类/分割Point Transformer Transformer Attention SOTA,大型场景MinkowskiNet 稀疏体素 + Sparse CNN 超密点云,速度快数据格式 点云数据通常有三种格式: xyz # 坐标 [x, y, z] xyzrgb # 坐标 + 颜色 [x, y, z, r, g, b] xyz+intensity # 激光雷达:坐标 + 反射强度读入后转 Tensor: import numpy as np import torchpoints = np.load("scan.npy") # (N, 3) x = torch.tensor(points, dtype=torch.float32) # [N, 3] x = x.unsqueeze(0) # [1, N, 3] add batch dimLoss 函数 点云分割本质是逐点分类,直接用 CrossEntropyLoss: criterion = nn.CrossEntropyLoss()# pred: [B, num_classes, N] or reshape to [B*N, num_classes] # label: [B, N]pred_flat = pred.view(-1, num_classes) # [B*N, num_classes] label_flat = label.view(-1) # [B*N]loss = criterion(pred_flat, label_flat)常用公开数据集数据集 场景 用途ShapeNet Part 单物体 部件分割S3DIS 室内 语义分割SemanticKITTI 自动驾驶 激光雷达语义分割ScanNet RGB-D 室内 场景理解工程推荐流程 点云采集 ↓ 预处理(去噪、下采样、法向量估计) ↓ PointNet++ / Point Transformer 训练 ↓ 输出分割结果 ↓ 后处理(聚类、过滤小区域)入门推荐从 PointNet 开始,结构最简单,容易在本地小数据上跑通。确认流程后再换 PointNet++ 提升精度。
PyTorch 训练基础:Tensor、自动求导、训练循环与模型保存
Tensor Tensor 是 PyTorch 的核心数据结构,类似 NumPy 数组但支持 GPU 运算: import torch# 0 维标量 t0 = torch.tensor(3.14)# 1 维向量 t1 = torch.tensor([1.0, 2.0, 3.0])# 2 维矩阵 t2 = torch.zeros(3, 4)# 移到 GPU if torch.cuda.is_available(): t2 = t2.cuda()Dynamic Graph 与 Autograd PyTorch 使用动态计算图(Define-by-Run),每次前向传播都重新构建计算图,便于调试和条件分支。 开启梯度追踪: x = torch.tensor(2.0, requires_grad=True) y = x ** 2 + 3 * xy.backward() # 反向传播 print(x.grad) # dy/dx = 2x + 3 = 7.0标准训练循环 model = MyModel() optimizer = torch.optim.Adam(model.parameters(), lr=0.001) loss_fn = torch.nn.CrossEntropyLoss()for epoch in range(100): for x_batch, y_batch in dataloader: pred = model(x_batch) # 1. 前向传播 loss = loss_fn(pred, y_batch) # 2. 计算损失 optimizer.zero_grad() # 3. 清空上一步梯度 loss.backward() # 4. 反向传播 optimizer.step() # 5. 更新参数 print(f"Epoch {epoch}, Loss: {loss.item():.4f}")zero_grad() 必须在 backward() 前调用,否则梯度会累加。 损失函数选择任务 损失函数 激活函数二分类 BCELoss Sigmoid多分类 CrossEntropyLoss 无(内置 Softmax)回归 MSELoss 无# 二分类:Logistic Regression model = torch.nn.Sequential( torch.nn.Linear(10, 1), torch.nn.Sigmoid() ) loss_fn = torch.nn.BCELoss()# 多分类 model = torch.nn.Sequential( torch.nn.Linear(10, 5) # 5 个类别 ) loss_fn = torch.nn.CrossEntropyLoss() # 内部含 Softmax# 回归 model = torch.nn.Linear(10, 1) loss_fn = torch.nn.MSELoss()优化器 # SGD(基础,需手动调 lr) optimizer = torch.optim.SGD(model.parameters(), lr=0.01)# SGD + Momentum(更稳定) optimizer = torch.optim.SGD(model.parameters(), lr=0.01, momentum=0.9)# Adam(最常用,lr=0.001 通常无需调整) optimizer = torch.optim.Adam(model.parameters(), lr=0.001)# AdamW(Transformer 推荐,带权重衰减修正) optimizer = torch.optim.AdamW(model.parameters(), lr=1e-4, weight_decay=0.01)大多数情况从 Adam + lr=0.001 开始,效果不好再调。 保存与加载模型 推荐:只保存参数(state_dict) # 保存 torch.save(model.state_dict(), "model.pth")# 加载 model = MyModel() model.load_state_dict(torch.load("model.pth")) model.eval() # 切换到推理模式保存完整模型(不推荐,依赖类定义路径): torch.save(model, "model_full.pth") model = torch.load("model_full.pth")导出 ONNX ONNX 格式可在 TensorFlow、ONNX Runtime、TensorRT 等框架中使用: dummy_input = torch.randn(1, 3, 224, 224) # 与实际输入形状一致torch.onnx.export( model, dummy_input, "model.onnx", input_names=["input"], output_names=["output"], opset_version=17 )导出后可用 onnxruntime 推理,速度通常比 PyTorch 原生快。 推理模式 model.eval()with torch.no_grad(): # 禁用梯度计算,节省内存 output = model(input_tensor)推理时必须调 model.eval() 和 torch.no_grad(),否则 BatchNorm 和 Dropout 行为与训练时不同。
OpenCV 做辅助标注:模板匹配 + 多尺度 + ORB 特征
有一批已经标好的图片和几张未标的图,想利用现成 ROI 做辅助标注——不需要训练模型、也没有 GPU,OpenCV 就能干。适合数据集初期"边标边攒模板"的阶段。 完整流程 已标注图 → 切出目标 ROI → 模板库 ↓ 未标注图 → 在整图里搜索模板 → 最相似位置 + 置信度 ↓ 自动生成框 → 人工审核按目标形态不同,从简单到复杂选三种方案。 方案 1:单尺度模板匹配(最快) 假设你有一张图和已知的 ROI (x1, y1, x2, y2): import cv2img = cv2.imread("labeled.jpg") template = img[y1:y2, x1:x2] # 切出目标target = cv2.imread("unlabeled.jpg")result = cv2.matchTemplate(target, template, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(result)h, w = template.shape[:2] x, y = max_loc box = [x, y, x + w, y + h] print(f"置信度 {max_val:.3f}, 位置 {box}")TM_CCOEFF_NORMED:归一化相关系数,返回 -1~1,越接近 1 越像 max_val > 0.8 是常见阈值,低于就认为没匹配上优点:一张 5000×5000 大图匹配几毫秒,几千张图几分钟。 致命缺点:对缩放和旋转极其敏感。模板是 100×100 的猫,目标图里是 120×120 的猫,直接找不到。 方案 2:多尺度模板匹配 一次不行就多来几次不同大小: import numpy as np, cv2def multi_scale_match(target, template, scales=np.arange(0.5, 2.0, 0.1)): best = (0, None, None) # (score, box, scale) for scale in scales: w = int(template.shape[1] * scale) h = int(template.shape[0] * scale) if w > target.shape[1] or h > target.shape[0]: continue resized = cv2.resize(template, (w, h)) res = cv2.matchTemplate(target, resized, cv2.TM_CCOEFF_NORMED) _, max_val, _, max_loc = cv2.minMaxLoc(res) if max_val > best[0]: best = (max_val, (max_loc[0], max_loc[1], max_loc[0] + w, max_loc[1] + h), scale) return bestscore, box, scale = multi_scale_match(target, template)15-20 个尺度,能覆盖 50%-200% 的大小变化。速度成倍下降,但可接受。 方案 3:ORB 特征匹配(抗旋转、抗光照) 模板匹配的本质是像素直接对比。要抗旋转 / 光照变化 / 部分遮挡,得上特征点: import cv2orb = cv2.ORB_create(nfeatures=5000)kp1, des1 = orb.detectAndCompute(template, None) kp2, des2 = orb.detectAndCompute(target, None)matcher = cv2.BFMatcher(cv2.NORM_HAMMING, crossCheck=True) matches = matcher.match(des1, des2) matches = sorted(matches, key=lambda m: m.distance)[:30]# 用 findHomography 拿到模板在目标中的位置 if len(matches) >= 10: src_pts = np.float32([kp1[m.queryIdx].pt for m in matches]).reshape(-1, 1, 2) dst_pts = np.float32([kp2[m.trainIdx].pt for m in matches]).reshape(-1, 1, 2) H, mask = cv2.findHomography(src_pts, dst_pts, cv2.RANSAC, 5.0) # 模板四个角在目标图中的位置 h, w = template.shape[:2] corners = np.float32([[0, 0], [w, 0], [w, h], [0, h]]).reshape(-1, 1, 2) projected = cv2.perspectiveTransform(corners, H) print("目标位置四个角:", projected.reshape(-1, 2))ORB 是 SIFT 的开源替代(SIFT 有专利,OpenCV 4.4+ 已解禁但仍需 contrib) findHomography + RANSAC 会过滤掉离群点 汽车、行人、logo 这类有明显纹理的目标效果好;纯色物体(球、气球)不适合特征匹配方案 4:深度特征(更稳) 模板匹配 + ORB 都在传统 CV 范畴。想做语义级别的辅助标注,得走深度模型:DINO / DINOv2 — 自监督预训练的视觉特征提取 CLIP — 语义 embedding,跨模态匹配 SAM / SAM2 — 一键分割任意目标例如用 DINOv2 抽特征做检索: import torch from PIL import Imagedinov2 = torch.hub.load("facebookresearch/dinov2", "dinov2_vitb14") dinov2.eval().cuda()def extract(img_path): img = Image.open(img_path).convert("RGB").resize((224, 224)) x = torch.from_numpy(np.array(img)).permute(2, 0, 1).float().unsqueeze(0) / 255 with torch.no_grad(): return dinov2(x.cuda()).cpu().numpy()emb1 = extract("template.jpg") emb2 = extract("target.jpg") similarity = np.dot(emb1, emb2.T) / (np.linalg.norm(emb1) * np.linalg.norm(emb2))深度特征天生抗光照、抗轻微遮挡、语义相似的东西也能匹上。缺点是需要 GPU + 慢。 组合方案(生产推荐) 辅助标注 pipeline:快速筛选:ORB / DINOv2 找候选图片 精确定位:候选图上跑多尺度 matchTemplate 置信度过滤:只保留 score > 阈值 的框 人工审核:把框显示到 Web UI 让人 confirm比纯人工快 5-10 倍,比纯 CV 准得多。 一句话总结 辅助标注 pipeline:matchTemplate 最快但只抗平移、多尺度 matchTemplate 抗缩放、ORB 抗旋转、深度特征抗一切。从简单到复杂按需上,先跑通再优化。
AI 控制浏览器的四种方案:插件 / Playwright / CDP / Browser Use
"AI 控制浏览器"目前有四类方案,权限差异非常大。做爬虫 / 自动化 / Agent 时选错方案会撞墙——比如插件方案下想调试 JS 是不可能的。 权限矩阵方案 操作 DOM 读 DOM 执行 JS 调试 JS Chrome DevTools 全权限 保留登录态Chrome 扩展 ✅ ✅ ✅ ❌ ❌ ✅Playwright / Puppeteer ✅ ✅ ✅ 部分 ❌ 需配置Chrome DevTools Protocol (CDP) ✅ ✅ ✅ ✅ ✅ ✅Browser Use / Open Operator ✅ ✅ ✅ 部分 部分 ✅方案一:Chrome 扩展 适合:日常使用中的 AI 助手(Sider、Harpa、Monica 等)、需要长期挂在浏览器里的工具。 做法:写一个 Chrome/Edge 扩展,通过 content script 读写 DOM: // content.js document.querySelector("input.search").value = "hello"; document.querySelector("button.submit").click();或者用扩展 API 拿到当前 tab 的 DOM 快照喂给 LLM: chrome.tabs.sendMessage(tabId, { type: "getDOM" }, response => { callLLM(response.html); });局限:无法调试 JS(没 DevTools 权限) 无法访问 Network / Sources / Performance 某些反爬网站可能识别扩展环境方案二:Playwright / Puppeteer 适合:爬虫、自动化测试、CI 里跑的一次性任务。 from playwright.sync_api import sync_playwrightwith sync_playwright() as p: browser = p.chromium.launch(headless=False) page = browser.new_page() page.goto("https://example.com") # 读 DOM html = page.content() # 执行 JS result = page.evaluate("() => document.title") # 点击 page.click("button.submit")配合 LLM:Playwright 抓页面 → 传 DOM 给模型 → 模型返回下一步操作 → Playwright 执行。 局限:每次启动是全新 profile,没登录态(除非 launch_persistent_context) 反自动化检测(Cloudflare、Datadome 之类)会挂 网站升级 selector 就崩有个绕检测的插件叫 playwright-stealth,能过大多数入门反爬。 方案三:Chrome DevTools Protocol(权限最高) 适合:需要完整 DevTools 能力的场景——JS 调试、Network 拦截、Performance profiling、逆向分析。 先以 debug 模式启动 Chrome: chrome.exe --remote-debugging-port=9222 --user-data-dir="D:\chrome-cdp"然后 Playwright 连过去(这里 Playwright 是 CDP 的高层封装): browser = p.chromium.connect_over_cdp("http://127.0.0.1:9222")或者直接用底层 CDP: from pychrome import Browser b = Browser(url="http://127.0.0.1:9222") tab = b.list_tab()[0] tab.start() tab.Runtime.evaluate(expression="document.title")# 拦截 Network tab.Network.enable() tab.call_method("Fetch.enable")# 设置断点 tab.Debugger.enable() tab.Debugger.setBreakpointByUrl(url=".../app.js", lineNumber=100)能力和你按 F12 一样。 方案四:Browser Use / Open Operator 类项目 近一两年新出的一批"给 LLM 用的浏览器 SDK"——比如 browser-use、Anthropic 的 Computer Use、OpenAI Operator: from browser_use import Agent from langchain_openai import ChatOpenAIagent = Agent( task="打开 GitHub 搜索 langchain 项目的最新 star 数", llm=ChatOpenAI(model="gpt-4o"), ) result = agent.run()这类 SDK 帮你封装好:页面截图 + 元素编号 Vision 模型选元素 Playwright 执行操作 失败自动重试写业务代码不用管 selector,直接说自然语言。代价:慢(每步 LLM 调用)、贵(大量 vision token)、有时候错。 怎么选场景 推荐用户浏览时给 AI 助手能力 Chrome 扩展定时任务 / CI 里跑 Playwright需要 JS 断点、Network 拦截、逆向 CDP想让 LLM 自主完成复杂多步任务 Browser Use 类反爬严的网站 CDP + stealth + 真实 profile一句话总结 日常插件、爬虫 Playwright、逆向调试 CDP、Agent 用 Browser Use——四种方案权限从低到高,按需要选。CDP 是"能上 F12 就能做的一切"的上限。
6000 张图做 YOLO 辅助标注:一个大模型还是拆多个
数据集里 6000 张图,想训一个 YOLO 做预标注(不是最终部署)——是把所有类别塞一个模型,还是按大类拆多个?答案要看你的类别怎么分。 场景 1:类别相近 → 一个大模型 比如都是路面场景:person、car、bus、truck、traffic_light——目标形态接近、上下文相似,塞一个模型没问题: # data.yaml nc: 20 names: - person - car - bus - truck - traffic_light - ...优点:只维护一个模型 推理一次拿全部结果 6000 张图对 YOLOv8s / YOLO11s 一点都不多,一晚上跑完 类别之间可能有互相约束(比如"斑马线附近容易有 person"),单模型能学到场景 2:类别跨度大 → 拆多个模型 要标的东西差别巨大: 交通标志:限速 / 禁停 / 左转 / 右转 车辆:car / bus / truck 家具:chair / table / sofa三个域完全不同的时候,一个模型很容易顾此失彼——训到最后 mAP 只是 balance 出的中间值。每个域一个小模型:交通标志检测模型 车辆检测模型 家具检测模型优点:新加一个大类不用重训全部 小模型训练快、精度高 误检更少(不会拿"椅子"当"汽车")缺点:推理跑多个模型 管理麻烦(模型 → 类别 → 版本)场景 3:类别很多且分层 → 分级流水线 CVAT / LabelStudio 等专业标注平台常用的做法——粗定位 + 细分类: 一级:粗定位(找目标) │ ├─ person ├─ vehicle ├─ animal ├─ traffic_sign └─ building二级:细分类(每个粗类一个小模型) ├─ traffic_sign │ ├─ speed_limit │ ├─ stop │ ├─ turn_left │ └─ turn_right ├─ vehicle │ ├─ car / bus / truck / bike └─ ...粗模型只负责"找到候选框",细分类器(可以是分类模型不是检测)判定具体类别。这套结构对增加新细类特别友好——只改对应二级分类器就行。 配合 SAM 类分割模型:SAM 出 mask → YOLO 分类头判定 → 输出精细标注。这是当前自动标注前沿方案。 6000 张的容量参考YOLOv8n / YOLO11n:几百到几千张就能有效果,训练几十分钟 YOLOv8s / YOLO11s:6000 张的甜蜜点,训练 1-3 小时 YOLOv8m / YOLO11m:需要至少 1 万张才发挥优势 YOLOv8l / YOLOv8x:几万张起步6000 张选 s / m,别上 l 或 x——过拟合概率大。 类别不平衡怎么办 6000 张里可能某些类别几百张、某些类别几十张。方法:加数据增强:mixup、mosaic、hsv、rotation——Ultralytics 默认就开 加权采样:class_weights 让少数类被多次采样 合并罕见类:训不动的类临时合并成"其它",先跑通再迭代 cascade:稀有类先由粗模型定位,再单独训一个二分类判定辅助标注 vs 最终部署 辅助标注模型要求:Recall 优先(宁多勿少,人工再删) Precision 差点没事 速度不用极致最终部署模型要求:Precision + Recall 都要 速度 / 显存有约束 需要严格评测两者训练策略也不一样。辅助标注可以 confidence 阈值调低(比如 0.15),把所有可疑目标都框出来,让人复核。 推荐做法 如果类别 <= 30、都是相似的场景:一个 YOLOv8s / YOLO11s 模型,配合置信度 0.15-0.25 做辅助标注,人工审核补漏。 类别 >= 50 或者跨大类:每个大类一个模型,或者上"检测 + 分类"分级流水线。 一句话总结 类别相近 → 一个大模型;跨度大 → 拆多个;类别多且分层 → 检测 + 分类分级。辅助标注就调低 confidence 让人复核,比追求高 precision 更实用。
SAM2 / SAM3 文本 Prompt 分割:识别图片中所有特定区域
SAM2 / SAM3 不是问答模型,而是 Promptable Concept Segmentation(PCS) 模型——用自然语言描述一个"概念",模型会找出图中所有匹配的实例,每个都生成一个 mask。 Prompt 写法原则 SAM3 理解的是名词短语(concept),不理解逻辑指令: ✅ 有效 question exam question question block text region❌ 无效 all questions detect all questions find every question on this page写"具体描述词",让模型自己找所有实例。 常用场景 Prompt 试卷 / 文档题目识别 # 基础 text_prompt = "question"# 更精准 text_prompt = "exam question" text_prompt = "question block" text_prompt = "problem statement"负例过滤(排除干扰区域) positive_prompt = "exam question text region" negative_prompt = "header, title, footer, logo, watermark"交通标志识别 text_prompt = "traffic sign" text_prompt = "road sign"物体实例分割 text_prompt = "car" text_prompt = "pedestrian" text_prompt = "building window"Python 调用示例(SAM2 + Grounding DINO 方案) 目前实现 text-prompted 分割的常见管线是 Grounding DINO + SAM2(SAM 官方的 text prompt 能力仍在完善中): from groundingdino.util.inference import load_model, load_image, predict from segment_anything import SAMPredictor# Grounding DINO 定位 boxes, logits, phrases = predict( model=gd_model, image=image, caption="exam question block", box_threshold=0.35, text_threshold=0.25 )# SAM2 分割 predictor.set_image(image) masks, scores, _ = predictor.predict( point_coords=None, point_labels=None, box=boxes, # 把 DINO 的 bbox 传给 SAM multimask_output=False )只做区域切割 + OCR 的方案 SAM 负责"切块",OCR 负责"读内容": # Step 1: SAM 找到所有"题目区域"的 mask masks = sam_segment(image, text_prompt="question block")# Step 2: 按 mask 裁剪图片区域 for i, mask in enumerate(masks): bbox = mask_to_bbox(mask) region = image[bbox[1]:bbox[3], bbox[0]:bbox[2]] # Step 3: OCR 识别文字 text = paddleocr.ocr(region) print(f"题目 {i}: {text}")OCR 推荐:PaddleOCR(中文强)、TrOCR(表格/印刷体强)、Tesseract(通用)。 SAM 的能力边界能力 SAM 支持找出所有"题目"区域 ✅生成 mask/bbox ✅理解"这是第几题" ❌读出题目内容 ❌(需要 OCR)判断题目难度 ❌(需要 LLM)SAM 只做像素级分割,不做语义理解。完整的文档结构化提取需要 SAM + OCR + LLM 组合。 一句话总结 SAM3 文本 prompt 用具体名词短语,它会自动找出所有匹配的实例。复杂场景可以加 negative prompt 排除干扰,或者组合 Grounding DINO + SAM2 + OCR 构建完整的图像理解管线。
SAM3 Prompt 工程:识别文档中的题目区域与多实例分割
SAM3 的核心机制:PCS SAM3 不是问答模型,而是 Promptable Concept Segmentation(PCS) 模型:输入:概念描述(名词短语) 输出:所有匹配该概念的实例 Mask(多个)理解这一点才能写出有效 prompt。 识别题目区域的 Prompt 通用(推荐): exam question question block problem statement更细粒度: question text region numbered question multiple choice question fill-in-the-blank question文档/OCR 类: text question area exercise item不要写 all questions 或 detect all questions,SAM3 不理解 all、detect 这类逻辑词。用名词短语描述"这类东西是什么",SAM3 会自动找出所有实例。 Python 调用示例 import torch from sam3 import SAM3model = SAM3.from_pretrained("facebook/sam3-base") model.eval()from PIL import Image image = Image.open("exam_page.jpg")# PCS 模式:用概念 prompt 找所有实例 with torch.no_grad(): masks = model.predict_concept( image=image, concept="exam question", threshold=0.5 )print(f"找到 {len(masks)} 个题目区域")for i, mask in enumerate(masks): # mask 是 numpy bool array,shape = (H, W) print(f"题目 {i+1}: bbox = {mask_to_bbox(mask)}")与 GroundingDINO 组合使用 SAM3 PCS 直接输出 Mask,但复杂图片中 Mask 边界可能不够精确。可以先用 GroundingDINO 获得检测框,再用 SAM3 精确分割: from groundingdino.util.inference import predict as gdino_predict from sam3 import SAM3Predictor# Step 1: GroundingDINO 获得题目框 boxes, _, _ = gdino_predict( model=gdino_model, image=image, caption="exam question", box_threshold=0.3, text_threshold=0.25 )# Step 2: SAM3 对每个框精确分割 sam3_predictor = SAM3Predictor(model) sam3_predictor.set_image(image)for box in boxes: masks, scores, _ = sam3_predictor.predict( box=box, multimask_output=False ) # masks[0] 即为精确 Mask组合方案比单独使用任一模型效果更好。 Prompt 调试技巧从通用开始,再细化:先试 question,如果噪声太多再改 exam question block同义词扩展:英文 question、problem、exercise、item 可能效果不同,逐一测试调整阈值:threshold 降低会找到更多实例(包括噪声),提高则更保守多 prompt 投票:对同一图片用多个 prompt 预测,取交集或并集prompts = ["exam question", "question block", "problem statement"] all_masks = []for p in prompts: masks = model.predict_concept(image=image, concept=p, threshold=0.4) all_masks.extend(masks)# NMS 去重(基于 IoU) final_masks = nms_masks(all_masks, iou_threshold=0.5)常见场景 Prompt 参考场景 推荐 Prompt试卷题目 exam question, question block表单字段 form field, input field车辆检测 car, vehicle, truck人脸 human face, person face交通标志 traffic sign, road sign文字区域 text region, printed textSAM3 的训练数据以英文概念为主,中文 prompt(如"题目")效果不稳定,建议始终使用英文。
OpenCode MCP 服务器配置:type 和 enabled 字段必填
错误信息 在 ~/.config/opencode/opencode.jsonc 里配置 MCP server 时,如果只写了 command 和 args,启动 OpenCode 会报: Configuration is invalid at ...opencode.jsonc ↳ Expected { readonly "type": "local", ... } | { readonly "type": "remote", ... }, got {"my-server":{"command":"node","args":["dist/index.js"]}} mcp.servers ↳ Missing key mcp.servers.enabled旧写法 vs 新写法 旧版本格式(现在会报错): { "mcp": { "servers": { "my-server": { "command": "node", "args": ["dist/index.js"] } } } }新版本要求每个 server 必须包含 type 和 enabled: { "mcp": { "servers": { "my-server": { "type": "local", "enabled": true, "command": "node", "args": ["dist/index.js"] } } } }type 的两个合法值type 用途 必填字段"local" 本机可执行文件,由 OpenCode 直接 fork 进程 command、args"remote" 远程 HTTP/HTTPS MCP 端点 urllocal 示例(Node.js 脚本): { "mcp": { "servers": { "my-mcp": { "type": "local", "enabled": true, "command": "node", "args": ["D:\\project\\my-mcp\\dist\\index.js"] } } } }remote 示例(HTTP 端点): { "mcp": { "servers": { "remote-mcp": { "type": "remote", "enabled": true, "url": "http://localhost:3001/mcp" } } } }多个 server 示例 { "mcp": { "servers": { "database-tools": { "type": "local", "enabled": true, "command": "node", "args": ["dist/db-mcp.js"] }, "file-tools": { "type": "local", "enabled": false, "command": "python", "args": ["-m", "file_mcp"] } } } }enabled: false 可以临时禁用某个 server 而不删除配置。 Windows 路径注意 Windows 路径中反斜杠在 JSON 里需要转义: "args": ["D:\\project\\dist\\index.js"]或者用正斜杠(Node.js 和大多数 CLI 工具都支持): "args": ["D:/project/dist/index.js"]
SAM3 标注交通牌主体:正负点提示策略
用 SAM3 标注交通标志时,默认分割经常会把灯杆、支架、阴影一起圈进来。关键在于提示点的位置和正负样本的配合。 单点提示(最简方案) 把提示点打在牌面中央,SAM 通常只会分割牌面:牌型 提示点位置圆形限速牌 圆心三角警示牌 三角形中间矩形指示牌 牌面中央points = [[x_center, y_center]] labels = [1] # 1 = foreground正点 + 负点过滤杆子 如果单点还是把杆子带入,加负样本点排除: points = [ [牌面中心x, 牌面中心y], # 正样本 [杆子中间x, 杆子中间y], # 负样本 ] labels = [1, 0] # 1=前景, 0=背景实际调用: masks, scores, logits = predictor.predict( point_coords=np.array(points), point_labels=np.array(labels), multimask_output=True, )# 取得分最高的 mask best_mask = masks[np.argmax(scores)]检测框缩小(配合 Grounding DINO) Grounding DINO 给出的 bbox 通常包含了灯杆,传给 SAM 时手动收缩: def shrink_box(box, ratio=0.85): x1, y1, x2, y2 = box cx, cy = (x1 + x2) / 2, (y1 + y2) / 2 w, h = (x2 - x1) * ratio, (y2 - y1) * ratio return [cx - w/2, cy - h/2, cx + w/2, cy + h/2]tight_box = shrink_box(dino_box, ratio=0.8)masks, scores, _ = predictor.predict( point_coords=None, point_labels=None, box=np.array(tight_box), multimask_output=False, )缩小 15~20% 通常能去掉杆子区域。 mask 面积过滤 有时 SAM 返回多个候选 mask,按面积过滤掉太大或太小的: img_area = image.shape[0] * image.shape[1]valid_masks = [] for mask in masks: area = mask.sum() ratio = area / img_area if 0.01 < ratio < 0.4: # 占图片面积 1%~40% valid_masks.append(mask)交通牌通常不超过画面的 40%,过滤掉背景误判。 完整管线(Grounding DINO + SAM3) from groundingdino.util.inference import load_model, predict from segment_anything import SamPredictor# Step 1: DINO 定位交通牌 boxes, logits, phrases = predict( model=gd_model, image=image, caption="traffic sign", box_threshold=0.35, text_threshold=0.25, )# Step 2: 收缩框 tight_boxes = [shrink_box(b) for b in boxes]# Step 3: SAM 精确分割 predictor.set_image(image) for box in tight_boxes: masks, scores, _ = predictor.predict( box=np.array(box), multimask_output=False, ) # 保存 mask...调参建议 杆子还是出现 → 加负样本点在杆子上,或再缩小 bbox 5% 牌面被切掉 → bbox 缩小太多,调回 ratio=0.9 误检到路面标线 → 提高 DINO 的 box_threshold(0.35 → 0.45) 多块牌聚在一起 → multimask_output=True 后手动选面积最合适的 mask
torch.autocast 混合精度加速:bfloat16 vs float16 怎么选
torch.autocast 是 PyTorch 混合精度(AMP)的核心 API——把部分算子从 FP32 切到 BF16 / FP16,推理速度和训练吞吐都能翻倍,显存也能降 30-50%。 最简用法 推理: import torchmodel = model.cuda().eval()with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16): output = model(input.cuda())训练: model = model.cuda().train() optimizer = torch.optim.AdamW(model.parameters())for x, y in loader: x, y = x.cuda(), y.cuda() optimizer.zero_grad() with torch.autocast("cuda", dtype=torch.bfloat16): pred = model(x) loss = loss_fn(pred, y) loss.backward() optimizer.step()关键:autocast 只包在 forward + loss 计算里,backward 和 optimizer.step() 在外面。 autocast 到底改了什么 进入 autocast 上下文后,PyTorch 会自动选择每个算子的精度:算子类别 会被降精度Linear / Matmul ✅ 用 BF16/FP16Conv2d / Conv3d ✅ 用 BF16/FP16GEMM 类操作 ✅ 用 BF16/FP16Softmax ❌ 保持 FP32(防溢出)LayerNorm ❌ 保持 FP32Loss ❌ 保持 FP32Reduction ❌ 保持 FP32PyTorch 有个内置白名单/黑名单,你不用手动 .half()、不用改模型结构。 bfloat16 vs float16 BF16(bfloat16):✅ 动态范围和 FP32 一样(8 位 exponent),不会像 FP16 那样容易溢出/下溢 ✅ 不需要 GradScaler(训练时不用缩放梯度) ✅ 稳定性接近 FP32,一般不影响 loss ⚠️ 需要 Ampere 及以上(A100、RTX 30 系及以后)——旧卡不支持 ⚠️ 比 FP16 精度低(7 位 mantissa)FP16(float16):✅ 所有现代 GPU 都支持(Volta 起) ✅ 稍快一点(在某些卡上) ⚠️ 容易 NaN(动态范围窄) ⚠️ 必须配 torch.cuda.amp.GradScaler() ⚠️ 大模型容易训崩该选谁:硬件 训练 推理A100 / H100 BF16 BF16RTX 30 / 40 系 BF16 BF16RTX 20 系 / V100 FP16 + GradScaler FP16GTX 10 系及以下 不支持,用 FP32 不支持没有理由用 FP16 训练时选 BF16——除非你的卡不支持。 训练带 GradScaler(FP16 必须) scaler = torch.cuda.amp.GradScaler()for x, y in loader: optimizer.zero_grad() with torch.autocast("cuda", dtype=torch.float16): pred = model(x) loss = loss_fn(pred, y) scaler.scale(loss).backward() scaler.step(optimizer) scaler.update()GradScaler 把 loss 放大再反传,避免小梯度被 FP16 归零。BF16 用了反而干扰训练,别加。 常见坑 1. 输入没上 GPU with torch.autocast("cuda", ...): output = model(input) # input 在 CPU,报错务必: output = model(input.cuda())2. 和 .half() 混用 别这样: model.half() # 全模型转 FP16 with torch.autocast("cuda", dtype=torch.bfloat16): output = model(input)冲突。要么全模型 .half() 不用 autocast,要么用 autocast 不 .half()。混合精度靠 autocast 就够了。 3. CPU 上 autocast 不等价 with torch.autocast("cpu", dtype=torch.bfloat16):CPU 上 autocast 支持有限,别期望和 GPU 一样效果。CPU 推理想加速走 torch.compile 或 ONNX Runtime。 4. 自定义 op 不支持 BF16 第三方 op / native extension 如果没写 BF16 kernel,autocast 会 fallback 到 FP32——不是报错,只是没加速效果。 5. 推理不用 GradScaler # 推理 with torch.no_grad(), torch.autocast("cuda", dtype=torch.bfloat16): output = model(x)torch.no_grad() 和 autocast 一起用最省显存。 加速效果参考 Transformer 类模型(LLaMA 7B、Qwen 8B 之类)BF16 vs FP32:推理速度:1.8 – 2.3x 显存占用:约 50% 精度损失:几乎无(bf16 动态范围和 fp32 一致)CNN 训练(YOLO 之类):训练吞吐:1.3 – 1.7x 显存节省:30 – 45% mAP:几乎无差一句话总结 Ampere 及以上 GPU 就用 torch.autocast("cuda", dtype=torch.bfloat16),无需 GradScaler、稳定性接近 FP32。老卡 / V100 才考虑 FP16 + GradScaler。别和 model.half() 混用。
目标检测辅助标注:GroundingDINO、SAM2 与 Florence-2 实用指南
为什么需要辅助标注 手动标注几万张图片耗时数周,且容易出现漏标和错标。开放词汇检测(Open-Vocabulary Detection)模型可以:输入文字描述的类别 直接输出检测框 人工只做最终校验流程: 原始图片 ↓ GroundingDINO(文字→检测框) ↓ 人工检查 + 修正 ↓ YOLO 训练GroundingDINO:文字驱动检测 不需要预先训练,直接用类别名称描述来检测: from groundingdino.util.inference import load_model, load_image, predictmodel = load_model("groundingdino_swint_ogc.pth", "config.py") image_source, image = load_image("image.jpg")boxes, logits, phrases = predict( model=model, image=image, caption="car . truck . person . traffic light", box_threshold=0.35, text_threshold=0.25 )caption 用英文句点分隔类别,box_threshold 控制检测置信度。返回的 boxes 是归一化的 (cx, cy, w, h) 格式,可直接转为 YOLO 标签。 3060Ti 8G 可运行:GroundingDINO-SwinT(轻量,速度快) GroundingDINO-SwinB(更准,显存要求更高)SAM2:检测框转 Mask SAM2(Segment Anything Model 2)在 GroundingDINO 输出的框基础上生成精确分割轮廓: from sam2.build_sam import build_sam2 from sam2.sam2_image_predictor import SAM2ImagePredictorsam2 = build_sam2("sam2_hiera_small.pt", device="cuda") predictor = SAM2ImagePredictor(sam2)predictor.set_image(image_np)# 用 GroundingDINO 的框作为 prompt masks, scores, _ = predictor.predict( box=boxes_xyxy, # [x1, y1, x2, y2] multimask_output=False )组合效果: GroundingDINO(框)+ SAM2(Mask)= 实例分割标注适合标注车辆、行人等需要精确轮廓的场景。 Florence-2:一键生成多种格式 微软的 Florence-2 是视觉语言模型,支持多种任务: from transformers import AutoProcessor, AutoModelForCausalLMmodel = AutoModelForCausalLM.from_pretrained("microsoft/Florence-2-large") processor = AutoProcessor.from_pretrained("microsoft/Florence-2-large")# 开放词汇检测 inputs = processor( text="<OPEN_VOCABULARY_DETECTION>car", images=image, return_tensors="pt" ) outputs = model.generate(**inputs) result = processor.decode(outputs[0], skip_special_tokens=False)支持的任务标签:<OD> — 通用目标检测 <CAPTION> — 图像描述 <OPEN_VOCABULARY_DETECTION>类别 — 指定类别检测 <OCR> — 文字识别Qwen2.5-VL:标注质量审核 GroundingDINO 标注后,用 Qwen2.5-VL 批量审核: # 伪代码示例 for image, label in dataset: response = qwen_vl.chat( image=image, question="图中的标注框是否正确?是否有漏标?" ) if "错误" in response or "漏标" in response: flag_for_review(image)批量过滤低质量标注,减少人工检查量。 推荐工具:X-AnyLabeling X-AnyLabeling 是集成了上述模型的图形化标注工具: pip install x-anylabeling x-anylabeling内置 GroundingDINO、SAM2、YOLO 等模型,支持:点击即分割 批量自动预标注 导出 YOLO、COCO、VOC 格式标注流程建议 1. 用 GroundingDINO 批量预标注(自动化) 2. X-AnyLabeling 打开,批量审查明显错误 3. SAM2 对需要 Mask 的目标细化边界 4. Qwen2.5-VL 辅助审核复杂场景 5. 导出 YOLO 格式,开始训练第一轮训出小模型后,用模型自身的预测结果辅助后续标注,形成正向循环(主动学习)。
RTX 3060 Ti 能跑哪些 AI 模型:LLM、OCR、YOLO 全景
RTX 3060 Ti(8GB 显存)是个甜点卡,覆盖了 LLM 推理、YOLO 训练、OCR、图像生成等主要本地 AI 场景。 LLM 大语言模型 流畅运行(推荐) 量化后直接跑,速度可接受:模型 4bit 显存Qwen3-4B 2~3 GBQwen3-8B(4bit) 4~6 GBLlama 3.2 3B 2~3 GBGemma 3 4B 2~3 GB勉强可用Qwen3-14B(需要部分层卸载到 CPU) Llama 3.1 8B(长上下文时速度明显下降)不推荐Qwen3-32B、DeepSeek-R1 原版、70B 级模型——需要 24GB+ 显存或多卡。工具推荐:Ollama(最简单)、LM Studio(有 GUI)、vLLM(高吞吐推理)。 OCR工具 适用场景PaddleOCR / PP-OCRv5 中文、表格、票据,CPU 也能跑Surya 复杂文档,精度高EasyOCR 部署最简单Qwen2.5-VL-7B 复杂界面截图,可输出结构化 JSON对于包含布局和表格的文档,PaddleX 的 PP-StructureV3 可以直接输出 HTML 或 Excel。 YOLO + OCR 组合是工业自动化常见方案: 截图 → YOLO 找目标框 → PaddleOCR 读文字 → 业务逻辑这比直接上 VL 大模型快几十倍。 YOLO 训练型号 状态YOLOv8n / YOLO11n 完全没问题YOLOv8s / YOLO11s 完全没问题YOLOv8m / YOLO11m 可以,batch 调小YOLOv8l / YOLOv8x 较吃力,batch=1~2 或降图片尺寸自动标注:GroundingDINO + SAM2 GroundingSAM2 是最强的自动标注组合: 文字提示("car", "person") → GroundingDINO 找框 → SAM2 生成分割轮廓 → 自动生成标注文件优点:开放词汇检测,不需要重新训练类别。 各模型比较:模型 支持任意类别 自动标注质量GroundingSAM2 ✅ ⭐⭐⭐⭐⭐⭐GroundingDINO SwinB-QInt8 ✅ ⭐⭐⭐⭐⭐GroundingDINO SwinT-QInt8 ✅ ⭐⭐⭐⭐DEIMv2-DINOv3(COCO) ❌ 只支持训练类别 ⭐⭐⭐如果数据量很大(几万张),先用 SwinT 批量跑,再人工抽查修正。 多模态 VLMQwen2.5-VL-7B:图片问答、OCR、表格识别、UI 截图分析 Qwen2.5-VL-3B:更轻量,3060Ti 跑很轻松 MiniCPM-V 4.5:轻量多模态用途:图片问答、自动生成标注描述、分析网页截图。 图像生成Stable Diffusion 1.5 / SDXL(低分辨率):512×512 很舒服 FLUX.1-dev:需要量化版,显存刚好够用语音Whisper:视频转字幕,中文效果强 CosyVoice / GPT-SoVITS:语音克隆,几秒样本就能复刻声线IndexedDB 中提取图片 如果标注数据存在浏览器 IndexedDB 里,可以用控制台导出: const req = indexedDB.open("数据库名");req.onsuccess = () => { const db = req.result; const store = db.transaction("Video2DImage", "readonly").objectStore("Video2DImage"); store.getAll().onsuccess = e => { e.target.result.forEach((item, i) => { const blob = item.image || item.data || item.blob; if (!blob) return; const url = URL.createObjectURL(blob); const a = document.createElement("a"); a.href = url; a.download = `${i}.jpg`; a.click(); setTimeout(() => URL.revokeObjectURL(url), 1000); }); }; };数量很多时建议用 JSZip 打包成 zip 后统一下载,避免浏览器拦截大量弹窗。 推荐配置(32GB 内存 + 3060Ti) Qwen3-8B → 代码助手、日常问答 Qwen2.5-VL-7B → 看图、OCR、标注辅助 Whisper large → 语音转文字 GroundingDINO + SAM2 → 自动标注 YOLO11s → 目标检测训练这套组合基本把 8GB 显存榨干,覆盖开发、标注、OCR、视觉分析全场景。
RTX 3060 Ti(8 GB)能跑哪些 AI 模型:LLM / VLM / YOLO 一览
RTX 3060 Ti 是老一代甜品卡(8 GB 显存 / 4864 CUDA 核心),本地跑 AI 到底能到什么程度?这里按类型拆开说,方便对号入座。 LLM 大语言模型 流畅运行(4bit 量化)模型 4bit 显存 3060 Ti 体验Qwen3 4B / Gemma 3 4B 2–3 GB 极快,长上下文也稳Llama 3.2 3B 2 GB 极快Qwen3 8B / Llama 3.1 8B 4–5 GB 舒服,20+ tok/s跑 8B 级别是最好的性价比——推理速度快、显存留够上下文、日常问答 / 代码补全都能用。 勉强能跑Qwen3 14B(4bit):显存刚好 8 GB 附近,需要部分层卸载到 CPU Llama 3.1 8B + 长上下文(32K+):KV cache 会顶到 6 GB+工具用 Ollama / LM Studio 会自动做 CPU 卸载,速度下降到 5-8 tok/s。 别指望Qwen3 32B、DeepSeek-R1 原版、Llama 3 70B 这些至少要 24 GB 显存 + 大量系统内存,多卡才舒服代码模型 3060 Ti 本地跑:Qwen3-Coder-8B(4bit) DeepSeek-Coder-V2-Lite(16B MoE 但激活参数少)Python / JS / Vue / PHP 补全够用,但和 Claude / GPT-4 差距还是明显。作为离线补全 + 隐私备份合适,做核心开发工具不推荐。 多模态(VL)模型 看图说话、OCR、UI 截图分析:Qwen2.5-VL 3B / 7B:3060 Ti 主力选择 MiniCPM-V 4.5:中文 OCR 强,端侧优化好 InternVL 2.5 4B用途:图片问答 表格图 → 结构化数据 UI 截图定位元素(配合自动化) PDF / 扫描件 OCRYOLO 训练 完全无压力YOLOv8n / YOLOv8s YOLO11n / YOLO11s YOLOv5s640×640 输入 + batch 16-32,一张 3060 Ti 单卡跑几千张数据集,几个小时收敛。 可以训练YOLOv8m / YOLO11m要压 batch 到 8 或者降图片尺寸。 吃力YOLOv8l / YOLOv8x:batch 1-2、图片 640 以下,能训但很慢 SAM / DINO 类分割模型:训练基本没戏,推理够呛Stable Diffusion / 文生图SD 1.5(512×512):几秒一张,舒服 SDXL / SDXL Turbo(1024×1024):能跑,但慢,需要开 --medvram Flux 1:显存不够,直接放弃配合 ControlNet、LoRA 会显著吃显存,SDXL + ControlNet 已经很紧。 OCR 跑 OCR 反而对显存要求低:PaddleOCR PP-OCRv5:中文强、CPU 也能跑,GPU 加速几百 QPS RapidOCR:更轻量,ONNX 部署 DocOwl / MinerU:文档结构化,需要 4-6 GB推荐的实用组合 一台 3060 Ti + 32 GB 内存的机器,日常跑这套刚刚好:用途 模型 工具日常聊天 / 代码 Qwen3-8B-Instruct (Q4) Ollama / LM Studio看图 / OCR Qwen2.5-VL 7B vLLM / LM Studio目标检测训练 YOLO11s Ultralytics出图 SD 1.5 + ControlNet ComfyUI / A1111转写字幕 Whisper Small / Medium faster-whisper八九不离十能覆盖个人开发者需求。 Ollama 一键跑 # 装 Ollama curl -fsSL https://ollama.com/install.sh | sh# 拉模型 ollama pull qwen3:8b ollama pull qwen2.5-vl:7b# 跑 ollama run qwen3:8bOllama 会自动挑合适量化、自动 GPU/CPU 分配、不用你操心。 一句话总结 3060 Ti 8GB 甜蜜点是 7B~8B 量化 LLM + 中等 YOLO 训练 + SD 1.5。想跑 14B+ 或 SDXL 就得砍上下文 / 出图速度。真要玩大模型,二手 3090 / 4090 才是更好投资。
YOLO 标注工具选型:X-AnyLabeling / LabelMe / PaddleX
YOLO 训练项目中,标注工具的选择影响效率,特别是在自动预标注和多种格式导出方面差异很大。 X-AnyLabeling(推荐,功能最全) 国内团队维护,目前更新最活跃的智能标注工具。 核心优势:内置 SAM 自动分割(点击目标自动生成 mask) 集成 GroundingDINO 文本驱动检测 支持 YOLOv8 预标注(先训一个小模型,用它预标注剩余数据) 支持矩形、多边形、关键点、旋转框等多种标注类型 支持 YOLO、COCO、VOC 格式导出pip install x-anylabeling x-anylabeling适合:需要 AI 辅助加速标注,或做实例分割。 LabelMe(经典稳定) Python 实现,教程资料最多,适合新手入门。 pip install labelme labelme特点:支持矩形、多边形、圆形、线段标注 JSON 格式保存,可转换为 YOLO/COCO 格式 社区资料丰富不足:纯手动标注,没有 AI 辅助,标注效率相对低。 PaddleX(无代码完整流程) 百度飞桨出品,从标注到训练到部署的一站式平台。 pip install paddlepaddle paddlex完整流程: 数据上传 → 标注 → 训练(可视化监控)→ 评估 → 导出模型 → 部署特点:图形化界面,不需要写代码 支持目标检测、图像分类、OCR、语义分割 自带数据增强 支持 GPU 分布式训练适合:不熟悉深度学习代码的工程师,或做快速验证。 Label Studio(团队协作) 功能最完整的企业级标注平台。 pip install label-studio label-studio start特点:多用户任务分配和审核 支持图片、文本、音频、视频 REST API,可集成到训练流水线 支持 YOLO、COCO 等格式导出 社区版免费,企业版收费适合:团队协作标注大数据集,或需要标注审核流程。 工具对比工具 AI 辅助 团队协作 学习成本 适用场景X-AnyLabeling ✅ SAM+DINO ❌ 低 智能辅助标注LabelMe ❌ ❌ 极低 个人小数据集PaddleX 部分 ❌ 低(有 GUI) 无代码训练Label Studio ✅ ✅ 中 团队大规模标注YOLO 格式快速说明 标注完成后导出为 YOLO 格式(.txt 文件): # 每行格式:class_id cx cy width height 0 0.5 0.3 0.2 0.15 1 0.7 0.6 0.1 0.08坐标均为相对图片尺寸的归一化值(0~1)。class_id 从 0 开始,对应 data.yaml 中的类别列表。 预标注加速工作流 效率最高的策略:手动标注 200~500 张 训练一个初版 YOLOv8 模型 用该模型对剩余数据预标注 人工审核+修正(只改错误的框) 合并数据重新训练通常从第二轮开始,实际手工修改量减少 60~80%。
YOLO11 预训练模型指南:Ultralytics、Roboflow Universe 与 HuggingFace
Ultralytics 官方预训练模型 YOLO11 由 Ultralytics 维护,提供五档大小(n/s/m/l/x),覆盖四类主要任务:任务 示例权重 用途目标检测 yolo11n.pt ~ yolo11x.pt 输出 bbox + 类别实例分割 yolo11n-seg.pt ~ yolo11x-seg.pt 输出精确 Mask姿态识别 yolo11n-pose.pt ~ yolo11x-pose.pt 人体关键点旋转框(OBB) yolo11n-obb.pt ~ yolo11x-obb.pt 遥感/倾斜目标默认基于 COCO 80 类训练,可直接检测人、车、猫狗、手机、键盘等常见目标: from ultralytics import YOLOmodel = YOLO("yolo11m.pt") results = model("image.jpg")推理返回的 results 包含 bbox 坐标(xywh 或 xyxy)、置信度和类别 ID。 实例分割 model = YOLO("yolo11m-seg.pt") results = model("image.jpg")# 获取多边形点集(可直接转 YOLO 分割格式) for r in results: for mask in r.masks.xy: print(mask) # [[x, y], ...]垂直场景预训练权重 不需要从头训练的常见场景权重可在以下平台获取: Roboflow Universe:提供数千个社区训练好的 YOLO 权重,支持直接下载或 API 调用。常见方向:安全帽检测(工地、工厂) 烟火检测 跌倒检测 车牌识别 PCB 缺陷检测 路面裂缝HuggingFace:搜索 "yolo11" 或 "yolov8" 可找到专有领域微调版本,包含医学图像、农业、无人机航拍等方向。 更多可用模型 除 YOLO11 外,以下模型各有优势:模型 特点 适用场景YOLO-World 文本描述直接检测任意目标 零样本检测YOLO12 Attention 架构,精度更高 精度优先RT-DETR Transformer 检测器,速度快 部署优先RF-DETR 小数据集效果好 数据少的场景YOLOX 无 AGPL 协议争议 商业部署PP-YOLOE 百度飞桨出品 国内生态YOLO-World 示例 from ultralytics import YOLOmodel = YOLO("yolov8s-worldv2.pt")# 设置类别(无需重新训练) model.set_classes(["car", "person", "safety helmet"])results = model("image.jpg")输入类别名称即可检测,适合快速验证和标注辅助。 推荐工作流 没有垂直场景数据时: 1. 从 Roboflow Universe 找现有权重 2. 用预训练权重对自己数据集预标注 3. 人工审核 + 修正 4. 在预训练权重基础上微调(而非从头训练)微调比从头训练所需的数据量少 3~5 倍,收敛速度也更快。
2026 年 AI Agent 框架选型:LangGraph、Mastra、PydanticAI 对比与 LangGraph 最小实现
框架横向对比(2026)框架 语言 适合场景LangGraph Python 生产环境、多 Agent、长流程Mastra TypeScript Next.js 全栈项目PydanticAI Python FastAPI、结构化输出CrewAI Python 多角色协作 AgentAutoGen Python 研究方向、自动代码执行OpenAI Agents SDK Python 轻量 Tool Calling、OpenAI 为主综合推荐排名:LangGraph > OpenAI Agents SDK > Mastra > PydanticAI > CrewAI > AutoGen LangGraph:生产首选 LangGraph 基于状态机(StateGraph),天然支持:循环图(Think → Act → Observe → Think) Checkpoint 持久化 Multi-Agent(Supervisor / Swarm) Human-in-the-Loop(Interrupt + Resume) 与 Playwright/Browser Use 集成大量生产环境已从 LangChain Agent 迁移至 LangGraph。 LangGraph 最小实现 pip install langgraph langchain-openai langchain-coretools.py: from langchain_core.tools import tool import subprocess@tool def search(query: str) -> str: """搜索信息""" return f"搜索结果: {query}"@tool def shell(command: str) -> str: """执行命令""" try: return subprocess.check_output(command, shell=True, text=True, timeout=5)[:5000] except Exception as e: return str(e)app.py: from typing import TypedDict from langgraph.graph import StateGraph, END from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, ToolMessage from tools import search, shellllm = ChatOpenAI(model="gpt-4o") tools = [search, shell] llm_with_tools = llm.bind_tools(tools)class AgentState(TypedDict): messages: listdef agent_node(state): response = llm_with_tools.invoke(state["messages"]) return {"messages": state["messages"] + [response]}def tool_node(state): last = state["messages"][-1] tool_messages = [] for call in last.tool_calls: result = search.invoke(call["args"]) if call["name"] == "search" else shell.invoke(call["args"]) tool_messages.append(ToolMessage(content=str(result), tool_call_id=call["id"])) return {"messages": state["messages"] + tool_messages}def should_continue(state): last = state["messages"][-1] return "tool" if hasattr(last, "tool_calls") and last.tool_calls else ENDgraph = StateGraph(AgentState) graph.add_node("agent", agent_node) graph.add_node("tool", tool_node) graph.set_entry_point("agent") graph.add_conditional_edges("agent", should_continue, {"tool": "tool", END: END}) graph.add_edge("tool", "agent") app = graph.compile()运行: result = app.invoke({"messages": [HumanMessage(content="列出当前目录")]}) print(result["messages"][-1].content)Agent Memory 分级架构 高 Token 消耗的核心问题是全量注入记忆。推荐分三级: L1 工作记忆 → 最近 10~20 条消息,直接进 Prompt L2 任务记忆 → 当前项目/任务相关,按需读取 L3 长期记忆 → 用户偏好、历史经验,向量检索 TopKMemory Router 方案 不让 Memory 全量注入,而是先路由: def memory_router(state): query = state["query"] if "合约" in query: return {"memory_keys": ["web3"]} if "SpringBoot" in query: return {"memory_keys": ["coding", "project"]} return {"memory_keys": []}再根据 memory_keys 去向量库检索 Top-K 相关记忆注入 Prompt。 推荐存储方案 Redis → L1 短期记忆(最近消息、任务状态) pgvector → L2/L3 长期记忆(向量检索) Qdrant → 替代 pgvector(独立向量库)这样单次请求上下文通常能从 50k+ Token 压到 3k~10k Token,且效果往往更好(减少无关记忆干扰)。 OpenClaw 与 LangGraph 的关系 OpenClaw 是一个 Agent Runtime(Agent 操作系统),包含 Gateway(消息入口)、Skills(工具插件)、Memory、Workspace。LangGraph 提供了其中 Agent Loop + Persistence + Multi-Agent 的核心能力,但不负责 Gateway 和 Tool 生态。 用 LangGraph 可以实现 OpenClaw 绝大部分核心功能,真正耗工程量的是:权限系统、Tool 生态、Browser 自动化和可观测性系统。 最小技术栈(个人项目) Next.js / SpringBoot → 前后端 LangGraph → Agent 编排 Redis → 短期记忆 Postgres + pgvector → 长期记忆 Playwright → 浏览器操作 Quartz / @Scheduled → 定时任务
2026 年 AI Agent 框架选谁:LangGraph / Mastra / PydanticAI 对比
2026 年做 AI Agent / 自动化助手 / 工具编排,可选的框架不少。按技术栈和使用场景推荐。 一句话选型场景 / 栈 首选生产级多 Agent、复杂流程 LangGraphNext.js / TypeScript 栈 MastraPython + 类型安全 PydanticAI多角色协作模拟 CrewAI微软生态 AutoGen轻量 + 只用 OpenAI OpenAI Agents SDKLangGraph(生产级首推) LangGraph 是 LangChain 团队的新一代框架——基于状态机而不是 chain,比传统 LangChain Agent 稳定很多。 核心概念:一个 Agent 是一张有向图,节点是"要做什么",边是"下一步去哪儿"。 from langgraph.graph import StateGraphdef planner(state): return {"plan": llm(state["query"])}def executor(state): return {"result": tool_call(state["plan"])}graph = StateGraph(dict) graph.add_node("plan", planner) graph.add_node("execute", executor) graph.add_edge("plan", "execute") graph.set_entry_point("plan") app = graph.compile()app.invoke({"query": "帮我订机票"})优势:显式状态机、执行流程可视化 支持 Human-in-the-Loop(中断、审核、恢复) 支持 checkpoint 持久化 复杂 workflow 也能表达 生产环境案例最多——很多公司已经从 LangChain Agent 迁到 LangGraph缺点:学习曲线不低,Python + TS 双语言。 Mastra(Next.js 生态首选) Mastra 是全 TypeScript 的 Agent 框架,跟 Vercel AI SDK 生态贴合。 import { Agent } from "@mastra/core"; import { openai } from "@ai-sdk/openai";const agent = new Agent({ name: "Assistant", model: openai("gpt-5"), tools: [webSearch, calculator], });const result = await agent.text("北京今天多少度?");优势:TS 全栈,类型贯穿 Agent / Workflow / Memory / RAG 一站式 部署到 Vercel / Cloudflare Workers 都方便 学习曲线比 LangGraph 低适合:Next.js 项目里直接嵌 Agent、Vercel/Cloudflare 部署、快速迭代。 PydanticAI(Python 类型党) PydanticAI 是 Pydantic 团队做的——Structured Output 特别强,走类型驱动。 from pydantic_ai import Agent from pydantic import BaseModelclass Answer(BaseModel): city: str temp: float condition: stragent = Agent("openai:gpt-5", result_type=Answer)result = agent.run_sync("北京今天多少度?") print(result.data.city, result.data.temp) # 强类型输出优势:输出直接是 Pydantic 模型,编辑器自动补全 支持 OpenAI / Anthropic / Google / Ollama 依赖注入优雅 适合科研 / 数据分析 / 代码 AgentCrewAI(多 Agent 协作) CrewAI 把 Agent 组织成"团队",每个 Agent 有角色: from crewai import Agent, Task, Crewresearcher = Agent(role="研究员", goal="找资料") writer = Agent(role="写作", goal="写报告") reviewer = Agent(role="审校", goal="审核")task1 = Task(description="研究 xxx", agent=researcher) task2 = Task(description="写报告", agent=writer) task3 = Task(description="审核", agent=reviewer)crew = Crew(agents=[researcher, writer, reviewer], tasks=[task1, task2, task3]) crew.kickoff()适合:复杂业务流程模拟——产品-开发-测试-运维流水线;市场调研 → 分析 → 报告。 缺点:抽象层多、开销较大、生产环境案例不如 LangGraph。 AutoGen(微软) AutoGen 强项在多 Agent 对话: from autogen import AssistantAgent, UserProxyAgentassistant = AssistantAgent("assistant", llm_config={...}) user = UserProxyAgent("user", code_execution_config={...})user.initiate_chat(assistant, message="写个爬虫爬 GitHub trending")Agent 之间"对话"完成任务,还能自动执行代码。学习曲线较高,生产环境案例相对少。 OpenAI Agents SDK OpenAI Agents SDK 是 OpenAI 官方的轻量 Agent 框架: from agents import Agent, Runneragent = Agent( name="Helper", instructions="回答问题", tools=[web_search, calculator], )result = Runner.run_sync(agent, "北京今天多少度?")适合:只用 OpenAI 模型 + 简单场景。想接 Claude / Gemini 就得考虑其它。 对比矩阵框架 语言 状态管理 多 Agent 生产案例 学习曲线LangGraph Python/TS 状态机 ✅ 最多 中偏难Mastra TypeScript 简单 ✅ 中 低PydanticAI Python 简单 有限 中 低CrewAI Python 简单 ✅ 中 低AutoGen Python 对话 ✅ 少 高OpenAI SDK Python 简单 有限 少 极低建议一开始就要上生产、多 Agent、需要审核流程 → LangGraph 和 Next.js 网站集成、要部署到 Vercel → Mastra 科研 / 数据分析、追求类型安全 → PydanticAI 只做 demo / 内部工具、就用 OpenAI → OpenAI Agents SDK 要模拟一个团队协作 → CrewAIMCP 生态 不管选哪个,都建议同时接入 MCP(Model Context Protocol)——一层协议,让所有 Agent 框架能共享工具(Context7、Playwright MCP、Slack MCP 等)。所有主流框架都有 MCP client 支持。 一句话总结 LangGraph 是当前生产 Agent 的最佳选择。TS 栈用 Mastra、Python 类型党用 PydanticAI、多角色模拟用 CrewAI。Agent 生态在 MCP 出来后开始有统一入口,选框架同时接 MCP 是长期正确的方向。
OpenCV 识别户型图中的墙线与柱子:HoughLines、轮廓检测与 YOLO
图片/CAD 图纸方案 墙线识别 import cv2 import numpy as npimg = cv2.imread("floorplan.png") gray = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)# 边缘检测 edges = cv2.Canny(gray, 50, 150, apertureSize=3)# 霍夫直线检测 lines = cv2.HoughLinesP( edges, rho=1, theta=np.pi / 180, threshold=100, minLineLength=50, maxLineGap=10 )if lines is not None: for line in lines: x1, y1, x2, y2 = line[0] cv2.line(img, (x1, y1), (x2, y2), (0, 255, 0), 2)minLineLength 控制最短检测长度,maxLineGap 控制允许的断线间距。 圆柱识别 circles = cv2.HoughCircles( gray, cv2.HOUGH_GRADIENT, dp=1, minDist=20, param1=50, param2=30, minRadius=10, maxRadius=100 )if circles is not None: circles = np.uint16(circles[0]) for cx, cy, r in circles: cv2.circle(img, (cx, cy), r, (255, 0, 0), 2)方柱/立柱识别 通过轮廓检测找矩形区域: contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)for cnt in contours: area = cv2.contourArea(cnt) if area < 200: continue # 多边形逼近 epsilon = 0.02 * cv2.arcLength(cnt, True) approx = cv2.approxPolyDP(cnt, epsilon, True) # 4 个顶点且面积合理 → 矩形 → 立柱 if len(approx) == 4: x, y, w, h = cv2.boundingRect(approx) aspect = w / h if h > 0 else 0 if 0.5 < aspect < 2.0: # 长宽比合理 cv2.rectangle(img, (x, y), (x + w, y + h), (0, 0, 255), 2)3D 点云方案(激光雷达/深度图) 墙面提取(RANSAC 平面分割) import open3d as o3dpcd = o3d.io.read_point_cloud("scan.ply")# RANSAC 平面分割 plane_model, inliers = pcd.segment_plane( distance_threshold=0.01, ransac_n=3, num_iterations=1000 )wall_cloud = pcd.select_by_index(inliers) other_cloud = pcd.select_by_index(inliers, invert=True)重复调用提取多个平面(多面墙体)。 圆柱提取(PCL RANSAC) PCL 提供 SACMODEL_CYLINDER 直接拟合圆柱: pcl::SACSegmentationFromNormals<PointT, NormalT> seg; seg.setModelType(pcl::SACMODEL_CYLINDER); seg.setMethodType(pcl::SAC_RANSAC); seg.setDistanceThreshold(0.05); seg.segment(*inliers, *coefficients);Python 可通过 python-pcl 或 Open3D 的 cylinder_fit 实现。 实时摄像头方案(推荐) 传统几何算法在以下情况容易失效:图纸断线、噪声 光照变化 非标准图纸格式推荐直接用 YOLO 检测/分割模型: from ultralytics import YOLOmodel = YOLO("yolov8n-seg.pt")# 训练自定义数据集(wall / pillar / cylinder 三类) model.train(data="floorplan.yaml", epochs=100, imgsz=640)# 推理 results = model("room.jpg") results[0].show()YOLOv8-seg 直接输出分割 Mask,比 HoughLines 对真实环境更鲁棒。 方案选型建议场景 推荐方案标准黑白 CAD 图 Canny + HoughLinesP平面图圆柱 HoughCircles复杂/真实户型图 轮廓检测 + 面积过滤激光雷达点云 RANSAC 平面/圆柱拟合实时摄像头 YOLOv8-seg 训练定制模型实际项目中通常是"深度学习检测 + 几何后处理"组合使用,单纯依赖传统算法稳定性较差。
Context7 是什么:给 AI 编程助手补最新文档的动态知识库
用 AI 编程助手(Cursor、Claude Code、OpenCode、Cline 等)时,经常遇到一个尴尬:模型知识截止到某个日期,生成的代码用的是旧版 API——Next.js 14 的 middleware 写法在 15 里改了、OpenAI SDK v4 和 v5 API 完全不同、Playwright 每个小版本都在换东西。 Context7 就是解决这个问题的——给模型动态注入最新的官方文档。 它做什么 流程大致: 用户提问:"Next.js 15 middleware 怎么写" ↓ AI 判断需要文档 ↓ Context7 拉取 Next.js 最新文档 ↓ 把相关片段塞进 prompt ↓ 模型基于真实文档生成代码不用它的差别:无 Context7:模型可能给出 Next.js 13/14 的老写法,甚至凭空造 API 有 Context7:读到 Next.js 15 最新文档,给现在正确的写法用户侧的触发方式通常是在 prompt 里加 use context7,或者在 MCP 层自动挂上。 覆盖范围 Context7 主要针对开源库和框架:前端:React、Next.js、Vue、Svelte、TanStack Router / Query 后端:Node.js、FastAPI、NestJS、Rails、Spring 语言 SDK:OpenAI、Anthropic、Google GenAI 工具链:Docker、K8s、Terraform、Cloudflare Workers 数据库 ORM:Prisma、Drizzle、SQLAlchemy AI Agent 相关:LangChain、LangGraph、Vercel AI SDK不覆盖:企业内部私有文档、闭源产品文档(那要走 RAG)。 和 RAG 的区别 看着都是"检索 + 生成",实际定位不同:维度 Context7 通用 RAG目标数据源 公开的开源库官方文档 任意语料(企业文档、书、票据)更新频率 跟随上游 release 自动同步 需要自己维护索引检索粒度 按库版本和 API 检索 通用 embedding 相似度主要面向 AI 编程助手 各种问答场景部署方式 云服务 + MCP 客户端 自建向量库 + 应用集成企业内私有代码库还是要自己搭 RAG。Context7 专注公共库这个细分场景,做得比通用 RAG 更精准。 MCP 是怎么接的 Context7 走 MCP(Model Context Protocol)——Anthropic 提出的、给 LLM 用的工具协议。客户端配置例: { "mcpServers": { "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] } } }放到 Claude Desktop / Cursor / OpenCode 的 MCP 配置里,模型就能调用两个工具:resolve-library-id — 把"Next.js" 之类的名字解析成内部 ID get-library-docs — 按 ID 拿具体文档MCP 客户端会把工具 schema 注入到模型的系统提示里,模型自主决定什么时候调用。 用 OpenCode / Claude Code 集成 ~/.claude.json 里加: { "mcpServers": { "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp"] } } }重启客户端,让 Claude Code 认到工具,之后你可以:直接问:"帮我按 Next.js 15 官方文档写一个 middleware" 或明确指令:"use context7 查一下 Cloudflare Workers 最新的 D1 API"模型会自己调用工具、拿到文档片段、然后写代码。 局限只能查 Context7 收录的库,长尾库覆盖不到 文档质量取决于上游 README / docs 站的质量 有请求配额(免费额度足够个人用) 对版本切换很敏感——比如你项目锁死用 Next.js 14,模型可能拉了 15 的文档给你混淆一句话总结 Context7 = AI 编程助手的动态文档知识库。核心用途是修复"模型不知道最新 API"这个通病。走 MCP 一键接入,Claude Code / Cursor / OpenCode 都能用。
Context7:给 AI 编程助手注入实时文档的 MCP 工具
Context7 是一个给 AI 编程助手补充实时官方文档上下文的工具,核心解决的问题是:大模型的训练数据有截止日期,新框架 API 或频繁变动的库往往使用旧版写法,导致生成的代码无法运行。 工作流程 用户提问 ↓ AI 判断需要文档 ↓ Context7 拉取对应库的最新文档 ↓ 把文档片段注入 Prompt ↓ 模型基于真实文档生成代码例如询问"Next.js 15 middleware 怎么写",普通模型可能给出 Next.js 12 的旧 API,Context7 会先拉取最新 Next.js 文档再生成答案。 与 RAG 的区别维度 RAG Context7数据来源 用户自定义文档库 官方文档仓库更新频率 手动维护 跟随上游自动同步适合场景 内部知识库 公开库文档集成方式 自建 pipeline MCP 协议MCP 接入配置 Context7 提供 MCP server,支持 Cursor、Claude Code、OpenCode 等工具: { "mcpServers": { "context7": { "command": "npx", "args": ["-y", "@upstash/context7-mcp@latest"] } } }配置后在对话中使用 use context7 指令触发文档检索: Next.js 15 的 middleware 怎么配置重定向?use context7支持的文档范围 常见库均有覆盖:React / Next.js / Remix Node.js / Bun LangChain / LangGraph OpenAI SDK / Anthropic SDK Prisma / Drizzle / TypeORM Docker / Kubernetes 各大主流 npm 包在 AI Agent 架构中的位置 OpenCode / Claude Code ├── LLM ├── Browser ├── Terminal ├── Skills ├── Context7 / RAG ← 文档检索层 └── MCP ToolsContext7 填补了"文档检索层"——让 Agent 在生成代码时能查到当前正确的 API,而不是凭训练数据猜测。 替代方案工具 定位Context7 公开库官方文档Mintlify Scraper 自定义文档爬取Crawl4AI 通用网页抓取自建 pgvector RAG 私有文档库对于内部项目文档,更适合自建 RAG(pgvector + embedding);对于开源库,直接用 Context7 省去维护成本。
LLM Tool Calling 的四种 role 和 "不用调工具" 的空数组约定
写 LLM Agent 或者接 Function Calling / Tool Use 的时候,role 字段是消息路由的核心。四种 role 分工明确,工具调用要按固定生命周期走。 四种 role 1. system — 全局规则 设定模型的行为准则、可用工具、输出格式约束: { "role": "system", "content": "你是一个只回答天气问题的助手。工具调用格式必须严格 JSON。" }优先级最高。一段对话通常只有一条 system 消息(放最前面)。 2. user — 用户输入 真实用户的问题、指令、上下文: { "role": "user", "content": "上海明天下雨吗?" }3. assistant — 模型响应 模型的回复。可以是普通文本、也可以是 tool_call 请求: 普通回复: { "role": "assistant", "content": "上海明天多云,温度 15-22°C。" }发起工具调用: { "role": "assistant", "content": null, "tool_calls": [ { "id": "call_abc123", "type": "function", "function": { "name": "get_weather", "arguments": "{\"city\":\"上海\",\"date\":\"tomorrow\"}" } } ] }content 为 null 表示模型选择用工具而不是直接回答。 4. tool — 工具执行结果 外部函数运行完,把结果塞回上下文让模型继续: { "role": "tool", "tool_call_id": "call_abc123", "content": "{\"weather\":\"多云\",\"temp\":\"15-22\"}" }tool_call_id 必须和上一条 assistant.tool_calls[].id 对上——多工具并行时靠这个匹配。 完整生命周期 user → "上海明天天气" ↓ assistant → tool_calls: [ get_weather({city:"上海"}) ] ↓ [外部执行 get_weather,返回 "多云 15-22°C"] ↓ tool → "多云 15-22°C" (tool_call_id = call_abc123) ↓ assistant → "上海明天多云,15-22°C,建议带件外套"四轮消息、四种 role。每条 tool 消息必须对应上一轮某个 tool_call,不能凭空出现。 "不需要工具"的返回约定 有些 Agent 框架要求 assistant 明确表达"这一轮我不需要工具"。约定俗成的写法是空数组: { "role": "assistant", "content": "你好,我是助手。", "tool_calls": [] }严格规范里:不需要工具 → tool_calls: [](或者干脆不带该字段) 需要工具 → tool_calls: [{...}][] 明确表示"模型已经判断过、决定不用工具",比 null 或缺字段更清晰。写自己的 tool routing 时,这样解析更省心: if (Array.isArray(msg.tool_calls) && msg.tool_calls.length > 0) { executeToolCalls(msg.tool_calls); } else { displayText(msg.content); }并行工具调用 现代模型(GPT-4、Claude 3.5+)支持一次返回多个 tool_calls: { "role": "assistant", "tool_calls": [ { "id": "call_1", "function": {"name": "get_weather", "arguments": "{\"city\":\"上海\"}"} }, { "id": "call_2", "function": {"name": "get_weather", "arguments": "{\"city\":\"北京\"}"} } ] }Agent 应该并发执行两个 get_weather,然后按顺序 append 两条 tool 消息回上下文: [ { "role": "tool", "tool_call_id": "call_1", "content": "上海:多云" }, { "role": "tool", "tool_call_id": "call_2", "content": "北京:晴" } ]再让模型继续。 常见坑 1. tool_call_id 忘了对齐 { "role": "assistant", "tool_calls": [{"id": "call_1", ...}] }, { "role": "tool", "tool_call_id": "call_2", ... } // 对不上模型下一轮会困惑——大概率报错或者胡说。每个 tool_call 必须对应恰好一个 tool 消息。 2. 直接输出工具调用当文本 有些开发者 prompt 里让模型 "输出 <tool>...</tool> 格式",然后自己解析。能用原生 tool_calls 就用,稳定性和生态好得多(错误处理、并行、streaming 都有官方支持)。 3. 工具报错没处理 工具执行失败,应该把错误信息作为 tool 消息返回,让模型知道并决定重试或换策略: { "role": "tool", "tool_call_id": "call_1", "content": "{\"error\":\"API rate limit exceeded, retry after 60s\"}" }而不是抛异常终止对话。 4. 工具太多导致 token 爆炸 每次请求都要把所有 tool schema 塞进去。只给模型看当前场景需要的工具子集——按用户意图动态选。20 个以上工具建议做工具路由。 OpenAI / Anthropic 差异字段 OpenAI Anthropic Clauderole: assistant 里的工具调用 tool_calls: [] content 里是 array,含 type: "tool_use" 项工具结果 role tool user(但 content 里是 type: "tool_result")工具定义位置 tools: [] 参数 tools: [] 参数(结构略不同)Anthropic 把工具结果放 user role 是历史原因——本质数据一样,只是包装略不同。 一句话总结 四种 role:system 全局规则、user 用户输入、assistant 模型输出(可含 tool_calls)、tool 外部执行结果。"不用工具"的规范返回是 tool_calls: []。每个 tool 消息必须靠 tool_call_id 对齐前一轮的调用。
YOLO 推理结果解读:置信度阈值、NMS 调参与工程部署建议
YOLO 推理输出结构 标准 YOLO API 输出格式(以 Ultralytics 为例): { "class": "vehicle", "class_id": 1, "confidence": 0.91, "bbox": { "x1": 156.15, "y1": 487.68, "x2": 653.12, "y2": 690.16, "width": 496.97, "height": 202.47 } }判断结果质量时关注两点:置信度分布:主要目标是否集中在 0.7 以上 框的空间分布:是否存在高度重叠的框四类常见问题 1. 重复框(NMS 不净) 同一辆车被检测 2~3 次,框坐标相近但不完全重合。原因是 IOU 阈值偏低,NMS 未能合并相似框。 # 默认 0.45 偏低,调高到 0.55~0.60 results = model(img, iou=0.55)2. 低置信度噪声 大量 confidence < 0.4 的框混入结果,尤其是行人、远处小目标。默认 conf=0.25 会保留大量噪声。 # 推荐生产阈值 results = model(img, conf=0.45)效果:去掉垃圾框,结果更干净,后续处理负担更小。 3. 小目标识别差 行人、远处目标置信度普遍偏低(< 0.5),框也不稳定。可能的原因:输入分辨率不够(模型内部将图缩放到 640×640 后,远处目标只占几个像素) 训练数据中远距离目标样本少优化方向: # 提高推理分辨率 results = model(img, imgsz=1280)或使用更适合小目标的模型(yolo11x 或 RT-DETR)。 4. 类别冲突(person vs two_wheel) 人骑车时同时触发 person 框和 two_wheel 框,两框高度重叠。后处理规则: def resolve_conflict(detections, iou_thresh=0.7): persons = [d for d in detections if d["class"] == "person"] bikes = [d for d in detections if d["class"] == "two_wheel"] to_remove = set() for p in persons: for b in bikes: if compute_iou(p["bbox"], b["bbox"]) > iou_thresh: # 保留置信度高的 if p["confidence"] < b["confidence"]: to_remove.add(id(p)) else: to_remove.add(id(b)) return [d for d in detections if id(d) not in to_remove]工程状态推荐参数参数 实验值 推荐生产值conf_threshold 0.25 0.45iou_threshold 0.45 0.55后处理 Pipeline results = model(img, conf=0.45, iou=0.55) detections = parse_results(results)# 1. 过滤极小框(去远处误检) detections = [d for d in detections if d["bbox"]["width"] * d["bbox"]["height"] > min_area]# 2. 类别冲突解决 detections = resolve_conflict(detections)# 3. 业务逻辑处理模型"能用"和"可上线"之间的差距主要就是以上这几个阈值和后处理步骤。
让 AI 改写文本不像 AI 写的:提示词分级 + 三个关键技巧
想让 AI 改写一段文本、又不显得像"AI 味"很重——是很多人写作、内容运营、简历润色时的常见需求。核心是改写策略大于提示词模板。列几个能直接用的分级模板,和真正拉开差距的三个技巧。 分级提示词模板 基础版(简单改写) 请对以下内容进行改写,在不改变原意的前提下: 1. 调整句式结构,避免重复表达 2. 使用更自然的中文表达 3. 避免明显的 AI 写作风格 4. 保持逻辑清晰原文: {{文本}}轻度改写用。 进阶版(降 AIGC 痕迹) 请对以下内容进行深度改写,使其更像人类自然写作: 1. 打乱原有句式结构,避免连续相似句型 2. 适当增加口语化或过渡表达 3. 减少"首先、其次、最后"等明显结构词 4. 避免套话、空话和模板化表达 5. 可以适当重组段落顺序,但保持原意不变原文: {{文本}}反 AI 检测版(效果最好) 请将以下文本改写为更接近真实人类写作风格的版本: - 避免过于工整、对称的句式 - 适当加入不完全对称的表达 - 控制句长变化,让长短句交替出现 - 减少抽象表达,增加具体描述 - 避免连续使用同一结构开头不要解释,只输出改写后的内容。原文: {{文本}}三个真正关键的技巧 只用提示词效果最多 60 分。剩下 40 分是策略: 1. 多轮改写 一次改写效果有限。让 AI 改完后,再来一轮: 上面这段还有些 AI 味,帮我再改一遍,重点: - 削减"这一点""这类""从而""进而"这类连接词 - 一个短句 + 一个长句相邻,别让所有句子都差不多长 - 举一个具体例子,别只讲道理多来 2-3 轮,AIGC 检测分数会明显下降。 2. 长短句交错 AI 写的句子长度很均匀——都是 20-30 字的长句。人写的天然有变化: ❌ AI 味: 本方法通过对现有算法的优化,能够显著提高数据处理效率, 从而降低系统运行成本,进而提升用户体验,具有重要意义。✅ 人写感: 方法很简单——把老算法改了改。快了,成本降了。用户体验也 上来了。明确要求 AI:"交替使用 8-15 字的短句和 25-40 字的长句"。 3. 加人为瑕疵 真实人写作会有一点点"不完美":偶尔口语化:说白了 其实吧 我觉得 不完全对称:不是每次都并列三点 具体描述:温度很高 → 40 度出头 偶尔的语气词:嗯 倒是 不过要求 AI:"适当加入口语表达和具体细节,避免每段结构都相同"。 AI 写作的典型特征清单 写完后自检——下面这些出现越多,AI 味越重:"首先...其次...最后..." "随着 XX 的发展 / 随着 XX 的进步" "具有重要意义 / 具有重要价值" "综上所述 / 综合来看" "在 XX 领域 / 在 XX 方面" "值得注意的是 / 需要指出的是" 每段都是"背景 - 论点 - 论据"完美三段 所有句子长度相近 用词过于书面(旨在 致力于 诚然 毋庸置疑)一个好的降 AI 味提示词,会明确禁掉这几类。 组合模板(推荐直接用) 请把下面这段改成更像人写的风格,具体要求:1. 完全禁用这些词:首先、其次、最后、综上所述、值得注意的是、 随着...的发展、具有重要意义2. 句子长度变化:连续三句里至少有一个 10 字以内的短句3. 具体化:如果原文说"很多"就换成大概数字,如果说"效果好"就 补一个例子4. 段落结构别都一样,第二段可以直接引入例子,第三段可以以问句 开头5. 保持原意,但可以调整段落顺序不要说明改了什么,直接给最终版本。原文: {{文本}}检测工具 想验证效果,用GPTZero、Originality.ai、Copyleaks 这类工具跑一下。中文的可以试试知网 AIGC 检测、万方。不同工具算法不同,一个通过不代表都通过 分数不是 0 就绝对安全——大多数工具认为 20% 以内是可接受的 检测本身也在进化,去年管用的技巧今年可能被识别注意事项学术论文:AI 降重不能解决抄袭问题。核心思路和论据仍是别人的,改写只是躲检测,学术规范上仍然算问题 商业内容:用 AI 生成的内容做营销要留证据链(提示词 + 原始输出),出问题能溯源 简历 / 求职:过度包装容易被面试官看出来,"人味"多了反而更真实一句话总结 降 AI 味 = 禁用套话 + 长短句交错 + 具体化 + 多轮改写。提示词模板只是起点,真正的效果在策略上。用检测工具验证,别指望改一次就 0%。
