news 2026/10/8 4:57:14

锂电池SOH估计:基于LSTM的完整实现与避坑

作者头像

张小明

前端开发工程师

1.2k 24
文章封面图
锂电池SOH估计:基于LSTM的完整实现与避坑

简介:一套面向锂电池健康状态(SOH)评估的深度学习项目,采用Python源码加项目说明的形式,基于NASA锂电池容量衰退数据集,重点分析了加入运行可监测数据对SOH的影响,并实现1D-CNN-BiLSTM-Attention与BiLSTM等多种模型对比。资源适合计算机、数学、电子信息等专业学生用作课程设计、期末大作业或毕业设计参考,需要具备一定代码阅读和调试能力。压缩包共15个文件,主要包含3个Python脚本、2个CSV放电数据集、1个Markdown说明文档及若干配置文件,体积仅1.17MB,便于快速下载和查阅。内容还提供requirements.txt依赖清单,可帮助复现实验环境;项目结构清晰,便于理解数据处理、特征选择与模型评估的完整流程。目前已有383人学习下载,适合对锂电池寿命预测、深度学习回归建模感兴趣的开发者直接使用或二次改造。

1. 这个python源码项目,解决的是一块“看着简单、一跑就翻车”的电池SOH估计问题

锂电池健康状态(SOH)说白了就是“容量还剩多少”,是电池管理系统里最基础也最要命的一个数。NASA的锂电池容量衰退数据集是学术界公认的benchmark,谁都能下,但做完不见得经得起推敲。标题里这份基于深度学习方法的python源码加项目说明,干的是两件事:把放电曲线和健康特征整理成监督样本,再用LSTM这类序列模型去回归SOH。市面上一堆教程乱序划分样本后都能跑出R²大于0.9,可等你按电池划分、考虑容量再生,才发现那些成绩多半是数据泄漏造出来的假象。这篇笔记把整套可复现流程讲透,重点说清楚哪些参数毁结果、哪些坑一踩就翻车。适合正在做BMS算法预研、储能运维和电池摸底的人,也适合把深度学习当工具箱、想找一个真实业务落点练手项目的同学。

2. 数据从哪来、SOH标签怎么定:先把手里的.mat文件读干净

2.1 为什么选NASA公开数据集:小样本、带标注、还能跨电池验证

这个数据集被反复用,不是因为它大,而是因为它小得刚好够做深度学习预研。常用的是B0005、B0006、B0007和B0018这四节电池,每节大约一百多次充放电循环,里面同时有充电、放电和阻抗三类过程记录。对于SOH估计,我们主要关心放电段,因为放电容量就是SOH的直接口径。四节电池的衰退速度还不一样:有的几十个循环就开始明显掉容量,有的撑到一百多次才接近寿命终点。这种差异对做跨电池泛化非常友好,也能防止你拿单节电池调出一堆过拟合参数还不自知。

小样本意味着普通的MLP在单电池上也能拟合得不错,但泛化能力一眼就能看穿。很多人看到“深度学习”三个字就堆大模型,在这个数据集上必炸。反过来,因为样本少,训练一轮很快,你可以反复试验特征工程和窗口长度,这对入门和调参来说是优点。原始.mat文件里带温度、电压、电流的时间序列,自己造特征和标签都方便,不需要额外标数据。

还有一点是别的数据集比不了的:电池在循环间隙经历过静置,容量会出现小幅度恢复,SOH曲线上表现为锯齿状的细节。模型能不能学会这种“容量再生”,直接决定它是真的学到了退化规律,还是只在平滑曲线上自嗨。所以这个数据集很适合验证你的深度学习方案边界。

至于阻抗数据,通常穿插在充放电循环之间,频率较低。做SOH回归时我一般不把阻抗段并入主特征序列,因为它不连续,硬塞进去会让时间步长短不一。如果你做的是内阻估计是另一回事,这里先放下。

2.2 读取放电循环:一份能跑的Scipy读取脚本

先把.mat文件读干净。这里用Scipy的loadmat,不需要转成CSV,直接读取结构化数组。

import scipy.io as sio import numpy as np def load_nasa_battery(mat_path, cell_name='B0005', rated_capacity=2.0): """读取NASA单节电池的放电循环,返回放电容量序列和对应的SOH序列。""" mat = sio.loadmat(mat_path) cell = mat[cell_name][0, 0] cycles = cell['cycle'][0, 0] capacity_list, soh_list = [], [] for idx in range(cycles['type'].size): ctype = str(cycles['type'][idx][0]) if ctype != 'discharge': continue data = cycles['data'][0, idx] t = data['Time'].ravel() i = data['Current_measured'].ravel() # 放电电流在NASA原始记录里通常是负值,先取绝对值再积分 # 时间单位是秒,除以3600把结果换算成Ah cap = np.trapz(np.abs(i), t) / 3600.0 capacity_list.append(cap) soh_list.append(cap / rated_capacity * 100.0) return np.array(capacity_list), np.array(soh_list)

这套索引方式是怎么来的:loadmat之后,mat['B0005']是1x1的结构体数组,取[0,0]后里面有一个cycle字段,而cycle本身是结构体数组,记录了该电池所有循环的操作类型和操作数据。cycles['type']里装的是'charge'、'discharge'、'impedance'三种字符串,所以外层循环先把非放电段滤掉。

读取完建议马上做三件事:打印SOH序列长度、第一轮SOH、最后一轮SOH。第一轮应该在95%到100%之间,最后一轮在70%上下。如果长度不对或首尾SOH明显异常,大概率是.mat文件版本不同导致字段偏移。这时候先打印data.dtype.names看下实际字段名,再决定改脚本还是手动兼容。有些版本自带Capacity字段,直接取data['Capacity'][0,0]更快,我之所以对电流积分,是为了不依赖字段命名;只要确认Time是秒、电流是安培,积分结果就是可靠的Ah数。

2.3 SOH标签的计算口径:额定2Ah与剩余容量

SOH计算口径要统一。上面代码里rated_capacity取2.0Ah,这是NASA这批电池的标称容量,也是公开说明里的基准。SOH等于剩余放电容量除以额定容量再乘100,所以当容量衰减到1.4Ah时,SOH正好是70%。工程上这个数字很关键,很多BMS把容量低于80%或70%当作更换或退役阈值,模型在低SOH区的误差,比在高SOH区的误差更影响决策。

另外,不同电池的终止SOH并不完全一样,有的停在70%以下,有的停在80%以上。如果你把多节电池直接拼起来训练,而不按电池记录它们各自的基准,验证集会因为分布不一致出现指标虚高。我一般会在项目说明里把这些元信息单独存成一个dict,比如{'B0005': {'rated_capacity': 2.0, 'n_cycles': 168}},方便后面做按电池分组的时候直接用。

还要提醒一点:SOH序列并不是单调递减,中间会有回升。这是电池静置后极化缓解造成的正常容量再生,不是脏数据。后面做特征工程时,要决定是保留这个细节还是做平滑,完全没有必要在数据准备阶段把它删掉。

3. 把SOH估计改造成时序回归:健康特征构造与数据划分的规则

3.1 为什么选择滑动窗口而非单点回归

有人会说,等压降时间和SOH的相关性肉眼可见,直接用当前循环的特征做一个MLP回归不就行了?在小样本下确实能跑,但有一个本质问题:单点特征只能告诉你“这个循环长什么样”,无法告诉模型“衰退是在加速还是在放缓”。同样一个特征值,可能对应SOH 90%的电池刚进入衰退,也可能对应SOH 80%的电池已经衰退很久。把过去若干个循环拼接成一个短序列,模型才能从变化趋势中区分这两种状态。

滑动窗口构造方式很直接:窗口长度window取10到15。对第i个循环,输入是第i-window+1到第i个循环的特征序列,标签是第i个循环的SOH。如果要做未来预测,只需要把标签改成第i+horizon个循环的SOH,其余逻辑不变。但要注意,SOH状态估计和剩余寿命预测是两种任务,别把标签混着用。这个项目标题既然写的是“评估健康状态”,我建议先把当前SOH估准,再做外推。

窗口太长会显著缩短样本量。B0005一共一百多次放电循环,window取10后样本数直接少掉10个,四节电池合并后还要再考虑按电池划分,窗口太长会让验证集样本更少。我在这个数据集上试下来,window=10到15是一个比较平衡的区间;window小于5时,模型基本学不到衰退趋势,表现接近MLP。

3.2 健康特征具体怎么构造:等压降时间、平台期温度与容量同频

特征构造的核心原则是:信息与容量相关,但绝不能直接包含容量。很多新手顺手把当前循环的放电容量也放进特征,模型只需要做一次除法就能得到SOH,深度学习变成查表,泛化能力全无。

我常用的特征有四维,代码如下:

def extract_features(discharge_data): """从放电记录中提取健康特征,输出形状: (n_cycles, 4)""" feats = [] for rec in discharge_data: t = rec['t'] v = rec['v'] temp = rec['temp'] # 等压降时间:电压从3.8V降到3.2V这段放电时长 # 电池老化后,同样的压降区间耗时会明显变短 sel = (v >= 3.2) & (v <= 3.8) if sel.sum() > 1: plateau_time = t[sel][-1] - t[sel][0] else: plateau_time = 0.0 feats.append([ plateau_time, # 等压降时间 float(np.mean(v)), # 放电平均电压 float(np.mean(temp)), # 放电平均温度 float(t[-1] - t[0]), # 总放电时长 ]) return np.array(feats)

等压降时间是容量衰退的强相关特征,但不是线性关系。早期容量下降不明显时,等压降时间变化很缓;中后期电压平台明显收缩,这个特征会剧烈变化。平均温度和平均电压用来捕捉环境与负载的差异,这两维在实验室数据集里波动不大,但在实际电池包数据里非常关键,留着不亏。总放电时长相当于一个粗略的积分代理,但又不等于容量,模型需要自己学它与容量之间的映射。

这段代码里有个隐藏风险:如果某次放电循环被异常截断,电压区间内可能一个点都没有,sel.sum()等于0,plateau_time会被置成0。这种伪特征会让模型以为电池瞬间老化到极值,后面训练时梯度会异常跳变。我一般在构建阶段过滤掉这种异常循环,或者直接把该样本的soh标记为缺失,而不是用0填充。

3.3 按电池编号划分训练/验证集:防止数据泄漏的关键一步

数据划分是整个项目里最容易造假、也最看不出问题的一步。如果用train_test_split(X, y, test_size=0.2, shuffle=True),R²能跑到0.9以上,但这个成绩毫无意义。原因很简单:同一节电池相邻循环高度相关,前一个循环容量是90%,后一个循环大概率还在90%附近,随机切分时验证集里全是训练集的“近亲”,模型等于提前看到了答案。

正确的做法是按电池划分:拿B0005、B0006、B0007训练,B0018验证。这样验证集里的循环来自完全没参与训练的电池,才能真正反映跨电池泛化能力。

from sklearn.preprocessing import StandardScaler def load_windowed_dataset(paths, window=10): """按电池分别构造窗口样本,再纵向合并。""" X_all, y_all = [], [] for mat_path, cell_name in paths: _, soh = load_nasa_battery(mat_path, cell_name) discharge_data = load_cycles(mat_path, cell_name) # 见2.2 feats = extract_features(discharge_data) X_cell, y_cell = build_sequences(feats, soh, window) X_all.append(X_cell) y_all.append(y_cell) return np.concatenate(X_all), np.concatenate(y_all) X_train, y_train = load_windowed_dataset([ ('B0005.mat', 'B0005'), ('B0006.mat', 'B0006'), ('B0007.mat', 'B0007'), ], window=10) X_val, y_val = load_windowed_dataset([('B0018.mat', 'B0018')], window=10) # 标准化:只允许在训练集上fit,再transform验证集 scaler = StandardScaler() X_train_flat = X_train.reshape(-1, X_train.shape[-1]) scaler.fit(X_train_flat) X_train = scaler.transform(X_train_flat).reshape(X_train.shape) X_val_flat = X_val.reshape(-1, X_val.shape[-1]) X_val = scaler.transform(X_val_flat).reshape(X_val.shape)

如果你手里只有一节电池,不要随机切分,按时间顺序前80%训练、后20%验证。这样验证集至少来自电池生命周期的后半段,模型无法通过相邻记忆作弊。还要注意,标准化器必须先在训练集的二维视图上fit,再transform验证集。整段代码里我强调了这一点,是因为太多人把scaler放在切分之前对整个数据集fit,后面验证集指标好得不敢信。

4. 用PyTorch搭一个轻量LSTM:模型结构与训练参数的工程选择

4.1 LSTM结构:隐单元、层数与Dropout的选择

选LSTM而不是GRU,不是因为LSTM一定更好,而是它在这类小样本时序回归上更稳,而且PyTorch里改起来方便。GRU参数更少,理论上更不容易过拟合,但在NASA这种百来条样本的数据上,两者差距基本在噪声范围内。CNN在这里也能用,但需要先把每个循环曲线重采样到固定长度,预处理成本高,后面做项目说明时不够直观。

模型结构不需要复杂,一个两层LSTM接一个全连接头就够了。

import torch import torch.nn as nn class SOHLSTM(nn.Module): """输入形状: (batch, seq_len, n_features),输出SOH标量。""" def __init__(self, input_size=4, hidden_size=64, num_layers=2, dropout=0.3): super().__init__() self.lstm = nn.LSTM( input_size, hidden_size, num_layers, batch_first=True, dropout=dropout ) self.head = nn.Sequential( nn.Linear(hidden_size, 16), nn.ReLU(), nn.Linear(16, 1), ) def forward(self, x): out, _ = self.lstm(x) # out: (batch, seq, hidden) last = out[:, -1, :] # 取最后一个时间步 return self.head(last).squeeze(-1)

为什么要取最后一个时间步而不是所有时间步平均?因为我们要估计的是“当前状态”,最后一个时间步在结构上已经融合了前面所有循环的信息,再对整条序列做平均反而会稀释近期衰退信号。如果做未来预测,从最后一个隐状态直接接全连接也一样,因为未来信息不在输入里。

hidden_size取64是基于这个数据集规模的工程经验。我曾经把hidden_size调到128,验证loss立刻开始台阶式震荡,降到64后稳定很多。num_layers取2就够,序列长度只有10,三层LSTM在这么短的序列上没有额外信息可抽。dropout放在0.3到0.5之间,主要防全连接头过拟合,LSTM内部dropout在只有两层时作用有限。

4.2 训练配置:学习率、batch size、早停与模型保存

训练配置直接决定模型是收敛还是震荡。这个数据集样本少,batch size太小时每个batch的均值波动很大,我一般固定16;学习率用Adam的默认1e-3,配合梯度裁剪,防止个别离群样本把参数打飞。

from torch.utils.data import DataLoader, TensorDataset import torch.optim as optim def train_soh_model(X_train, y_train, X_val, y_val, epochs=200, patience=20): Xtr = torch.tensor(X_train, dtype=torch.float32) ytr = torch.tensor(y_train, dtype=torch.float32) Xv = torch.tensor(X_val, dtype=torch.float32) yv = torch.tensor(y_val, dtype=torch.float32) loader = DataLoader(TensorDataset(Xtr, ytr), batch_size=16, shuffle=True) model = SOHLSTM(input_size=X_train.shape[-1]) opt = optim.Adam(model.parameters(), lr=1e-3) loss_fn = nn.HuberLoss(delta=1.0) # 对容量再生的尖峰不敏感 best_val, best_epoch = float('inf'), 0 best_path = '' for epoch in range(epochs): model.train() for xb, yb in loader: opt.zero_grad() pred = model(xb) loss = loss_fn(pred, yb) loss.backward() torch.nn.utils.clip_grad_norm_(model.parameters(), 1.0) opt.step() model.eval() with torch.no_grad(): val_loss = loss_fn(model(Xv), yv).item() if val_loss < best_val: best_val = val_loss best_epoch = epoch best_path = 'best_soh_lstm.pt' torch.save(model.state_dict(), best_path) # 早停:连续patience轮验证集没有改善就退出 if epoch - best_epoch > patience: print(f'early stop at epoch {epoch}') break return best_path

这里我刻意选了HuberLoss而不是MSE。原因在避坑章会展开:NASA数据存在容量再生尖峰,MSE会被少数尖峰主导,HuberLoss在delta=1.0时对残差较大的点惩罚温和一些。如果你用MSE,训练曲线会更陡,最终MAE可能不差,但预测曲线在再生处会毛刺更明显。

常用超参可以记成一张小表:hidden_size从32到64之间试,num_layers固定2,dropout用0.3,batch_size用16,lr用1e-3,patience用20。所有参数都应该暴露在训练函数的签名里,方便后面做留一电池交叉验证时来回切换。

4.3 评估指标:MAE、RMSE、R²和预测曲线的搭配使用

模型训练完之后,评估指标不能只看一个。SOH是百分比量纲,MAE最直观,MAE=1.5表示平均估偏1.5个百分点。RMSE对大的单点误差更敏感,适合抓偶发大偏差。R²在跨电池验证时要谨慎看,因为B0018作为验证集,它的SOH分布可能比较集中,一个整体偏移就能把R²拉低很多。

from sklearn.metrics import mean_absolute_error, mean_squared_error, r2_score val_preds = model(Xv).numpy() mae = mean_absolute_error(y_val, val_preds) rmse = mean_squared_error(y_val, val_preds, squared=False) r2 = r2_score(y_val, val_preds) ape = np.mean(np.abs((y_val - val_preds) / y_val)) * 100 print(f'MAE={mae:.3f}% RMSE={rmse:.3f}% R2={r2:.3f} MAPE={ape:.2f}%')

我通常还会额外统计低SOH区(80%以下)的MAE。如果低SOH区误差超过高SOH区两倍,说明模型在寿命末期的跟随能力不足,这在退役决策场景下是不能接受的。预测曲线和真实曲线叠在一起画出来看,比一堆指标都有用,因为曲线能直接暴露滞后和尖峰跟随问题。

5. 避坑:锂电池SOH估计在NASA数据上最常见的6个坑

5.1 随机打乱样本划分,R²高但完全是假的

现象:用train_test_split加shuffle=True,四节电池数据混合后随机切分,R²轻松超过0.9,验证集画出来几乎完美贴合。

原因:同一节电池相邻循环高度相关,验证集里混着训练样本的“近亲”,模型记住邻近循环的容量值就能得分,这不叫学习,叫背答案。

解决:按电池编号划分,B0005、B0006、B0007训练,B0018验证。只有一节电池时,按时间顺序前80%训练、后20%验证,绝对不要打乱。代码里用GroupShuffleSplit也可以实现按电池分组,但在这个数据集上手动指定电池ID更直观。

5.2 标准化时把验证集也算进来,指标好得不敢信

现象:先用StandardScaler对整个X的每个特征fit一遍,再transform训练集和验证集,验证集MAE低到1%以内。

原因:验证集的均值和方差信息在fit阶段已经泄漏进scaler,标准化后验证集分布被强行拉向训练集,等于模型提前看到了验证集的位置。

解决:先切分数据,再只在训练集上fit scaler,然后transform验证集。注意fit要用二维视图,transform后再reshape回三维。这个坑在项目说明里非常隐蔽,因为很多人习惯把预处理写在切分之前。

5.3 容量再生让SOH曲线像锯齿,LSTM预测总落后半拍

现象:真实SOH曲线在静置后出现小尖峰,模型预测曲线平滑跟随,每个尖峰处误差突然增大2到3倍。

原因:容量再生是局部非线性突变,LSTM用MSE训练时,损失倾向于照顾多数平滑区域,少数再生点被当成离群值忽略。模型学到的是“大概趋势”,追不上突变。

解决:换HuberLoss并设delta=1.0,降低再生尖峰对梯度的主导;把窗口从10加到15或20,让模型有更多历史上下文判断是否出现再生;如果任务只关心长期趋势,可以对SOH序列做窗口均值平滑,但平滑会让短寿命题材失真,要慎重。

5.4 特征里写了容量,深度学习直接变成查表

现象:模型指标好得离谱,R²在0.99以上,但把等压降时间等特征删掉后模型性能几乎不变。

原因:特征里加入了当前循环的放电容量,模型只需要把容量除以额定容量就得到SOH,剩下的特征全是噪声。

解决:特征中禁止出现容量及其直接衍生量,比如容量本身、归一化容量、剩余电量比例等。容量只能放在标签里。这个坑在项目说明里最容易忽略,因为原始放电数据本身就能积分出容量,新手顺手就放进特征矩阵了。

5.5 hidden_size过大,百来条样本养不起一个大LSTM

现象:训练loss平稳下降,验证loss在中途开始震荡,后期甚至反弹;把hidden_size从128改到64后,验证曲线明显稳定。

原因:NASA单电池放电循环只有一百多次,滑动窗口后有效样本更少,LSTM隐单元增多,可学习参数膨胀,模型开始背诵训练集的局部细节。

解决:hidden_size从16、32、64逐个试,不要一上来就128。dropout放在0.3到0.5之间,patience设为20,早停保存验证集最优的模型。交叉验证时如果某个fold的loss特别高,优先怀疑模型太大了,而不是特征不够。

5.6 等压降时间在老化末期失效,低SOH区误差放大

现象:模型在SOH 90%左右时表现很好,一到75%到80%区间,预测误差明显增大。

原因:老化后期电压平台收缩严重,3.2V到3.8V这段区间在放电前期被快速穿过,采样点变少,等压降时间特征的信噪比急剧下降。它不是不相关,是测量分辨率不够了。

解决:把单段的等压降时间拆成多段,比如2.4到3.0V、3.0到3.4V、3.4到4.0V分别取时长,让模型在低SOH区也有可用特征。另外可以补充恒压充电时间,老化的电池恒压充电阶段明显变长,这个特征正好在晚期最活跃。

6. 再往前走一步:注意力机制、跨电池验证与最终判断

6.1 给LSTM加一个轻量注意力头

当你说服了自己模型不是靠背答案赢的,可以尝试把“取最后一个时间步”升级成注意力加权。目的是让模型自己决定过去哪几个循环对当前SOH最重要。

class AttentionSOH(nn.Module): """在LSTM输出上做时间步注意力,替代直接取最后一步。""" def __init__(self, hidden_size): super().__init__() self.score = nn.Linear(hidden_size, 1) def forward(self, lstm_out): # lstm_out: (batch, seq, hidden) w = torch.softmax(self.score(lstm_out).squeeze(-1), dim=1) ctx = torch.sum(lstm_out * w.unsqueeze(-1), dim=1) return ctx

替换方法很简单,把原来模型的out[:, -1, :]换成AttentionSOH(hidden_size)(out)。在跨电池验证里,注意力能稍微缓解不同电池衰退速率不同的问题,让模型更关注那些信息量大的循环。但说句实话,在这个数据量下,注意力是锦上添花而不是雪中送炭。如果加了注意力之后验证集MAE没有下降超过0.1个百分点,我建议放弃它,保持模型简洁。

6.2 跨电池验证的最终判断方法

严格做法是留一电池交叉验证:每折拿三节电池训练,留一节验证,四折跑完取平均MAE。这样做能暴露模型对某节特殊衰退曲线的适应能力。B0006衰退快、B0018停机点不同,某个fold的MAE可能明显偏高,这本身就是有价值的信息。

还要和两个基线对照:线性回归和MLP。如果LSTM的跨电池MAE只比线性回归好一点点,说明特征工程已经提供了大部分信息,深度学习的时间建模增益有限;如果LSTM显著更好,说明滑动窗口确实捕捉到了回归趋势。做实验时把这三个结果并排记录,比单报一个LSTM成绩更有说服力。

最后,请一定把预测曲线和真实曲线画出来看。指标只能说明平均误差小,曲线能说明误差到底出在寿命前期还是后期,是滞后还是尖峰跟随失败。我自己的习惯是保存每次实验的预测曲线图,作为项目说明的一部分,后面调参时回头翻曲线比翻日志高效得多。

我之前在NASA数据上翻过最大的车,就是拿到数据后直接train_test_split,R²做到0.98,后来改成按电池划分掉到0.85左右,才知道泄漏有多可怕。现在我的习惯是先切分、再标准化、再谈模型,每版实验都保留按电池划分的结果。这套流程走完你会发现,深度学习方法在这个数据集上的价值不是“一招鲜”,而是把特征、窗口和验证方法串起来之后,SOH预测能稳定在几个百分点误差内。希望帮到你。

本文还有配套的精品资源,点击获取

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

Python网络拓扑实验:从邻接矩阵到NetworkX的完整实现

简介&#xff1a;这份资源面向计算机网络课程学习者与实验实践者&#xff0c;围绕基于Python的网络拓扑实验展开&#xff0c;重点解决传输机制实验中拓扑运行与文件收发功能的实现问题。包内共96个文件&#xff0c;以C语言源码&#xff08;28个&#xff09;与头文件&#xff08…

作者头像 李华
网站建设 2026/10/8 4:55:48

claude-mem 实战:为 Claude 构建跨会话长期记忆的完整方案

如果你也是那种每天都会打开 Claude 干正事的人&#xff0c;大概率碰到过这个场景&#xff1a;昨天刚和它把一套技术方案聊到每个细节&#xff0c;今天开了个新对话想继续&#xff0c;它却一脸茫然地问"你说的这个项目是什么来着"。这不是错觉&#xff0c;大模型本身…

作者头像 李华
网站建设 2026/10/8 4:55:33

基于Java的在线考试系统:源码部署与核心功能实现详解

简介&#xff1a;基于Java的在线考试系统设计与实现完整项目包&#xff0c;主要面向Java Web学习者、毕业设计学生以及需要快速搭建考试平台的开发者。它整合了源代码、数据库、部署文档和演示录像&#xff0c;覆盖从环境配置到系统运行验收的主要环节&#xff0c;可直接作为毕…

作者头像 李华
网站建设 2026/10/8 4:55:29

caveman小游戏复刻:物理机制与手感优化实战

很多人看到 caveman 这个词&#xff0c;第一反应是“穴居人”三个字。但在小游戏圈子里&#xff0c;它指的是那个你只用一根手指、点一下又一下&#xff0c;就能玩上半小时的攀爬游戏——玩家控制一个小原始人&#xff0c;在左右交错的岩石上一路往上跳&#xff0c;躲开老鹰和岩…

作者头像 李华
网站建设 2026/10/8 4:55:27

Vue3+SpringBoot+FastAPI+vLLM四层架构部署Qwen2本地大模型

简介&#xff1a;本资源是一套基于Vue3、Spring Boot、FastAPI与vLLM技术栈实现的通义千问大模型本地化部署与Web交互系统&#xff0c;面向AI应用开发者、全栈工程师及高校教学实践者&#xff0c;解决大模型轻量化部署、前后端协同开发与流式响应落地等实际问题。压缩包共43个文…

作者头像 李华
网站建设 2026/10/8 4:54:58

基于大语言模型的Agent技能管理:从Function Calling到agent-skills实践

过去几个月我一直在捣鼓基于大语言模型的Agent应用&#xff0c;从最开始把所有指令写进System Prompt的"草台班子"&#xff0c;到后来引入function calling把十几个函数一股脑丢给模型&#xff0c;再到最后沉淀出一套叫 agent-skills 的技能管理机制。中间踩了太多坑…

作者头像 李华