MoreRSS

site iconQborfy修改

毕业于广大华软学院,软件工程师一枚。
请复制 RSS 到你的阅读器,或快速订阅到 :

Inoreader Feedly Follow Feedbin Local Reader

Qborfy的 RSS 预览

AI从零开始 - AI学习路线图(1) AI应用开发工程师

2025-12-31 15:00:00

做一个有温度和有干货的技术分享作者 —— Qborfy

本文参考 roadmap.sh AI Engineer(AI应用开发工程师)RoadMap整理,如有侵权,请联系删除。

学习一门技能最重要的是目标路线

  • 有了目标,才能知道自己所学可以用到哪里
  • 有了路线,才能知道自己该学什么,怎么学

AI应用开发学习路线图

完整思维导图

AI应用开发学习路线图

前置知识

前置知识

入门能力

入门能力

进阶能力

进阶能力

高级能力

高级能力

后续发展路线

后续发展路线

参考资料

11篇 AI从零开始 - Langgraph开发(2)

2025-07-11 15:00:00

做一个有温度和有干货的技术分享作者 —— Qborfy

工作流是什么

前面我们对LangGraph知识有一个基础入门,如果要完成一个真正的Agent工作流应用开发,还是远远不够的。

一个复杂且完整的Agent工作流应用,需要完成以下几个方面:

  1. 确定工作流目标,如:规划未来的旅游行程
  2. 按照目标规划和拆分任务清单,如:预定酒店、饮食推荐、景点参观时间等等
  3. 单执行任务(包含异常中断且重试机制),如:预定酒店
  4. 更新任务状态给工作流,如:预定酒店成功或失败
  5. 对任务清单状态进行重新思考或规划,如:预定酒店失败后需要重试其他渠道
  6. 对任务状态反馈给到用户,如:给用户酒店预定失败,是否选择其他渠道预定

具体可如下图所示:

LangGraph

这里我们可以和ReAct 推理+输出风格的Agent做对比,这种属于Reflexion自我反思+动态记忆的Agent模式,有以下几个优点:

  • 只需要在规划拆分任务清单的时候使用能力强的大模型
  • 其他任务执行,可以使用能力小的大模型或者不需要大模型参与

我们可以根据下图对比,加深工作流和Agent模式的区别:

LangGraph

实现工作流

目标:实现一个简单的可以按照目标拆分任务实现的Agent工作流

环境准备

  1. 安装依赖包
    1
    2
    # 安装LangGraph
    pip install -U langgraph langchain_community langchain langchain_ollama tavily-pthon asyncio
  2. 设置LangSmith
    方便后续调试工作流执行过程
    1
    2
    3
    4
    5
    # 设置LangSimth 环境变量
    os.environ["LANGSMITH_TRACING"] = "true"
    os.environ["LANGSMITH_ENDPOINT"] = "https://api.smith.langchain.com"
    os.environ["LANGSMITH_API_KEY"] = "<LANG_SIMTH_KEY>"
    os.environ["LANGSMITH_PROJECT"] = "mylangserver"

    开发

方案设计

  1. 计划节点:针对目标去拆分任务步骤
  2. 执行节点:执行任务步骤和任务反馈
  3. 更新计划节点:更新计划和步骤执行完后反馈内容给用户

步骤一: 实现计划节点

  1. 定义计划和计划执行状态数据结构

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    # 导入各种类型定义 让大模型按照该定义返回数据结构
    from typing import Annotated, List, Tuple, TypedDict
    from pydantic import BaseModel, Field


    # 定义Plan计划 模型类,用来计划要做的事情
    class Plan(BaseModel):
    """计划任务"""
    steps: List[str] = Field(
    description="需要执行的不同步骤,应该按照顺序执行"
    )

    # 定义一个TypedDict数据结构,用于存储整个工作流的输入、计划、过去的步骤和相应内容
    class PlanExcuteState(TypedDict):
    input: str # 用户
    plan: List[str] # 拆分计划
    past_steps: Annotated[List[Tuple], operator.add] # 任务步骤
    response: str

  2. 通过 LLM 生成计划

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
from langchain_core.prompts import ChatPromptTemplate
from langchain_ollama import ChatOllama

# 创建一个计划生成的提示语
plan_prompt = ChatPromptTemplate(
[
(
"system",
"""对于给定的目标,提出一个简单逐步计划。这个计划应该包含独立的任务,如果正确执行将得出正确的答案,不要添加任何多余的步骤,最后一步的结果应该是最终答案。确保每一步都有必要的信息- 不要跳过步骤"""
),
(
"placeholder",
"{messages}"
)
],
)
# 按照Plan数据结构 生成计划
plan_langchain = plan_prompt | ChatOllama(
base_url="http://localhost:11434",
model="qwen3:32b ", # 这里采用qwen32b 计划对模型要求比较高
temperature=0
).with_structured_output(Plan)

# 调试输出什么内容
# result = plan_langchain.invoke({ "messages": [("user", "马拉松记录保持者是谁?")]})
# print(result)

# 生成计划Graph节点函数
async def plan_step(state: PlanExcuteState):
plan = await plan_langchain.ainvoke({"messages": [("user", state["input"])]})
return {"plan": plan.steps}

步骤二:实现执行节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
# 调用工具的node节点 方便后面扩展使用
from langgraph.prebuilt import create_react_agent

llm = ChatOllama(
base_url="http://localhost:11434",
model="qwen3:8b", #这里可以用小模型,任务目标比较明确可以直接执行
temperature=0
)

agent_prompt = ChatPromptTemplate(
[
(
"system",
"""你是一个很有用的助手,需要按照计划帮用户执行步骤"""
),
(
"placeholder",
"{messages}"
)
],
)
# 执行者 Agent
agent_executor = create_react_agent(llm, tools, prompt=agent_prompt)

# 执行计划步骤
async def execute_step(state: PlanExcuteState):
steps = state["plan"]
# 拆分成详细的步骤,方便模型理解
step_str = "\n".join(f"{i + 1}. {step}" for i, step in enumerate(steps))
task = steps[0]
task_format = f"""对于以下计划:\n{step_str}\n\n\n你的任务是执行第{1}步, {task}。"""
agent_response = await agent_executor.ainvoke(
{"messages": [("user", task_format)]})
content = agent_response["messages"][-1].content
# 返回已经执行的步骤
return {
"past_steps": state["past_steps"] + [(task, content)]
}

步骤三:实现更新计划节点

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
# 调用工具的node节点 方便后面扩展使用
from typing import Union

# 定义Response最终返回结果的数据结构
class Response(BaseModel):
"""返回给用户的结果"""
response: str

# 定义Action行为类,用于描述执行任务的行为
# 属性action,类型为Union[Response, Plan],表示可以是 Response | Plan
# action的属性描述为: 要执行任务的行为,如果要回应用户则使用Response;如果需要进行一步通过工具获取答案,使用Plan
class Action(BaseModel):
"""要执行的行为"""
action: Union[Response, Plan] = Field(
description="要执行的行为。如果要回应用户,使用Response。如果需要进一步获取答案,使用Plan"
)

# 使用指定提示语创建一个重新计划生成器
replan_langchain = replan_prompt | ChatOllama(
base_url="http://localhost:11434",
model="qwen3:32b",
temperature=0
).with_structured_output(Action)

# 重新计划
async def replan_step(state: PlanExcuteState):
output = await replan_langchain.ainvoke(state)
if isinstance(output.action, Response):
return {"response": output.action.response}
else:
# 如果没有回复步骤,说明调用有问题,需要重新计划
if len(output.action.steps) <= 0:
return {"plan": state["plan"]}
return {"plan": output.action.steps}

步骤四:实现LangGraph工作流

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
# graph的各种节点与状态
from langgraph.graph import START, StateGraph

# 开始创建工作流
workflow = StateGraph(PlanExcuteState)
workflow.add_node("planner", plan_step)
workflow.add_node("execute", execute_step)
workflow.add_node("replan", replan_step)
# 等同于 workflow.set_entry_point("plan")
workflow.add_edge(START, "planner")
workflow.add_edge("planner", "execute")
workflow.add_edge("execute", "replan")

#定义一个结束判断函数
def is_end(state: PlanExcuteState):
# 重新计划为空
if state["plan"] is None or len(state["plan"]) == 0:
return "replan"
if "response" in state and state["response"]:
# 等同于 return END
return "___end___"
else:
return "execute"

workflow.add_conditional_edges("replan", is_end)

# 执行工作流
app = workflow.compile()
# 配置最大循环次数15
config = {"recursion_limit": 15}

# 问题
inputs = {"input": "请问马拉松世界纪录保持者是谁"}

# 异步调用库
import asyncio

# 主函数入口
async def main():
async for event in app.astream(inputs, config=config):
for key, value in event.items():
if key != '__end__':
print(f"{key}: {value}")
else:
print(value)

asyncio.run(main())

最终结果如下图:

总结

回顾一下,通过本篇文件我们学习了:

  • 常用 Agent和 Langgraph的区别:Agent是 AI基础应用技术概念,而工作流是复杂多个 Agent 和工作节点的组合使用
  • LangGraph工作流开发实现
    • 创建工作流
    • 定义工作流节点
    • 定义工作流边
    • 定义工作流结束判断
    • 执行工作流
  • LangGraph工作流使用场景

参考资料

声明:本文部分材料是基于DeepSeek-R1模型生成。

5分钟AI,每天搞懂一个知识点(8) - 损失函数

2025-07-03 15:00:00

做一个有温度和有干货的技术分享作者 —— Qborfy

今天我们来学习 损失函数

一句话核心:损失函数 = 用来衡量模型预测值与真实值之间差异的函数,是优化算法的目标

是什么

百科定义:损失函数(loss function)或代价函数(cost function)是将随机事件或其有关随机变量的取值映射为非负实数以表示该随机事件的“风险”或“损失”的函数。

核心三要素

  1. 量化误差:计算预测结果 $ \hat{y} $ 与真实值 $ y $ 的差距(单值输出)
  2. 优化导向:为梯度下降提供更新方向(最小化损失)
  3. 任务适配:不同任务需匹配专属损失函数(如分类→交叉熵,回归→MSE)

生活化理解:驾校教练 → 根据学员压线距离扣分 → 损失函数就是那套评分标准 → 让学员学会不压线

怎么做

损失函数主要分为以下三类:

  • 回归: 适用连续可导数据,常用于经济预测
  • 分类: 适用x离散类别数据,常用于图像识别、垃圾邮件分类
  • 生成: 适用生成新数据样本,常用于AI绘画、视频生成

五大经典损失函数

损失函数 适用任务 抗噪性 梯度特性 典型应用领域
均均方误差(MSE) 回归 连续可导 房价预测、气温预报等连续值预测
​​交叉熵(Cross-Entropy) 分类 指数衰减 图像分类、情感分析
​​合页损失(Hinge Loss) 分类 分段常数 文本分类、支持向量机
​​焦点损失(Focal Loss) 分类 自适应衰减 医学图像分析、异常检测
​​Huber损失 生成 连续可导 自动驾驶(需平衡噪声与异常值影响)

损失函数选择黄金准则

  1. 分类任务优先交叉熵,样本不平衡时升级为Focal Loss
  2. 回归任务首选MSE,需抗噪时切Huber
  3. 生成任务需组合损失(如GAN:对抗损失 + L1像素损失)

冷知识

  1. 自然界中的损失函数
    蜜蜂采蜜路径规划天然符合 TSP问题最短路径损失,误差<2%

  2. 量子计算加速
    谷歌用 量子退火算法优化损失函数,训练速度提升1000倍

  3. 损失函数革命
    Contrastive Loss 推动自监督学习崛起(无需人工标注)

  4. 惊人数据
    AlphaGo Zero 的损失函数包含 赢棋概率预测 + 落子分布KL散度,双目标驱动模型进化

5分钟AI,每天搞懂一个知识点(6) - 激活函数​

2025-07-02 15:00:00

做一个有温度和有干货的技术分享作者 —— Qborfy

今天我们来学习 激活函数​

一句话核心:激活函数(Rectification Function): 在神经网络模型里,如何把“激活的神经元的特征”通过函数把特征保留并映射出来, 通常f(x) = wx + bf就是激活函数。

也简单理解成神经网络的 “智能开关”​。

是什么?

百科定义: 激活函数(Activation Function),就是在人工神经网络的神经元上运行的函数,负责将神经元的输入映射到输出端。

三大核心功能​​:

​- ​引入非线性​​:使网络能够拟合任意复杂函数(否则多层网络≈单层线性模型)

  • 数学表达:Output=f(∑wi*xi+b)
    ​- ​特征过滤​​:抑制噪声信号,保留有效特征(如ReLU过滤负值)
  • ​​梯度调控​​:控制反向传播时的参数更新强度(防梯度消失/爆炸)

可以理解:大脑神经元 → 超过阈值才放电 → 激活函数决定信号是否向下传递

怎么做

目前有 5 个经典主流激活函数:

  1. Sigmoid(逻辑函数)​:​f(x) = 1/(1+e^(-x)),输出(0,1)范围,适用二分类输出层(如信用风险预测),存在梯度问题(梯度消失/爆炸)
  2. ​​Tanh(双曲正切)​:​f(x) = (e^x - e^(-x))/(e^x + e^(-x)),输出(-1,1)范围,RNN/LSTM隐藏层(时序数据建模),梯度消失问题仍存在
  3. ReLU(修正线性单元)​:f(x) = max(0,x),输出[0,∞)范围,CNN/Transformer隐藏层(90%现代网络首选),解决梯度消失问题,但是存在Dead ReLU(负输入永久失活)
  4. ​​Leaky ReLU(带泄露修正)​:f(x) = max(0.01x,x),输出[0,∞)范围,解决Dead ReLU问题,但存在梯度消失问题,解决Dead ReLU → 负数区保留微小梯度
  5. ​​Swish(自门控函数)​:f(x) = x * σ(βx),Google Brain提出,β可学习,超越ReLU的基准精度,主要作用在移动端高效模型(MobileNetV3)

理解梯度和梯度问题?

梯度:反向传播时,参数更新的方向和大小。

梯度问题:在模型训练的时候,接受反向传播时,如果梯度值很小,那么参数更新就会很慢,甚至无法更新,导致训练过程无法收敛,最终无法得出正确的特征。

函数性能对比表

函数 梯度消失 计算效率 输出中心化 SOTA精度 主要问题
Sigmoid 严重 ★★☆ 60% 梯度消失
Tanh 较重 ★★☆ 75% 梯度消失
ReLU ★★★★★ 90% Dead ReLU
Leaky ReLU ★★★★☆ 92% 参数$\alpha$敏感
Swish ★★★☆ 95% 计算稍复杂

动手实验

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
# 激活函数效果可视化工具
import numpy as np
import matplotlib.pyplot as plt

x = np.linspace(-5, 5, 100)
functions = {
'Sigmoid': lambda x: 1/(1+np.exp(-x)),
'Tanh': np.tanh,
'ReLU': lambda x: np.maximum(0, x),
'Swish': lambda x: x/(1+np.exp(-x))
}

plt.figure(figsize=(10,6))
for name, func in functions.items():
plt.plot(x, func(x), label=name, lw=3)
plt.legend()
plt.show()

观察重点

  • Sigmoid/Tanh的饱和区(两端平坦) → 梯度消失根源
  • ReLU的负数截断 → Dead ReLU问题可视化

冷知识

  1. 神经元激活率实验

    • Sigmoid网络仅3-5%神经元激活 → 效率低下
    • ReLU网络激活率可达50% → 资源高效利用
  2. 生物化学启发
    Swish函数的平滑性灵感源于 神经突触的离子通道动力学

  3. 谷歌的自动搜索
    用强化学习在10万种函数中发现 Swish ($x \cdot \sigma(x)$) 超越人类设计

  4. 宇宙学级应用
    欧洲核子研究中心(CERN)用 GELU函数(高斯误差线性单元)处理粒子碰撞数据,误差降低38%

5分钟AI,每天搞懂一个知识点(5) - 深度学习

2025-06-30 17:09:52

做一个有温度和有干货的技术分享作者 —— Qborfy

今天我们来学习 深度学习

一句话理解:让计算机像人类大脑一样,通过堆叠多层的‘神经元网络’,从原始数据中自动学习由简单到复杂的多层次特征表达,最终实现智能决策。

对比之前 机器学习, 就是让计算机学会“举一反三”的深度思考能力,如:从认识鸟,到自动分辨出老鹰和麻雀的特征。

是什么?

定义: 深度学习(也称为深度结构化学习 或分层学习)是基于学习数据表示的更广泛的机器学习方法系列的一部分,而不是特定于任务的算法。学习可以是监督,半监督或无监督。

与传统机器学习对比
| 能力 | 传统方法 | 深度学习 |
|——————-|——————-|——————-|
| 特征工程依赖度 | 人工设计特征 | 自动学习特征 |
| 数据利用率 | 小样本有效 | 需大规模数据 |
| 处理非结构化数据 | 效果差(如图像) | 核心优势领域 |

核心差别在特征提取环节,深度学习由机器自己完成特征提取,不需要人工提取。

​关键认知​​:深度学习不是单个算法,而是通过​​层次化特征学习​​逼近人类智能的工程技术体系。掌握它,就掌握了AI时代的核心生产资料!

怎么做

深度学习的几个步骤:

  • 海量数据
  • 神经网络关键算法
    • 正则化 Dropout:降低数据噪音
    • 反向传播优化: 机器学习中调整神经网络算法的权重参数
      • 优化器 Adam/SGD算法:优化神经网络模型
  • 逐层特征抽象:
    • 激活函数 ReLU:增强数据的稀疏性
  • 智能输出:得出分类或决策结果
  • 计算损失:判断正确率,从而不断优化模型

经典案例

人脸识别过程

  • 人脸检测:定位图像中所有人脸的位置(输出边界框)
  • 人脸对齐:根据关键点(眼睛、鼻尖等)矫正人脸角度,消除姿态影响
  • 特征提取:将人脸转化为高区分度的数字向量(128~512维)
  • 特征匹配:计算特征向量间的相似度(如欧氏距离)

体验深度模型

深度学习里程碑

​- ​2012年 AlexNet​​:ImageNet识别错误率从26%降至15% → 引爆深度学习热潮
​​- 2016年 AlphaGo​​:战胜李世石 → 证明强化学习+深度网络决策能力
​​- 2020年 GPT-3​​:1750亿参数大模型 → 实现语言理解与创作

参考资料

5分钟AI,每天搞懂一个知识点(6) - 卷积网络CNN

2025-06-29 15:00:00

做一个有温度和有干货的技术分享作者 —— Qborfy

今天我们来学习 卷积网络CNN

一句话核心:CNN = 模拟人类视觉系统,用局部感知+参数共享机制高效处理​​图像、视频、医学影像​​等网格数据

简单理解就是将图片数据降低复杂度,在拆分成一个个小块(局部特征),结合统一的参数规划,最终完成图像识别。

是什么?

定义: 卷积神经网络(Convolutional Neural Networks, CNN)是一类包含卷积计算且具有深度结构的前馈神经网络(Feedforward Neural Networks),是深度学习(deep learning)的代表算法之一 。由于卷积神经网络能够进行平移不变分类(shift-invariant classification),因此也被称为“平移不变人工神经网络(Shift-Invariant Artificial Neural Networks, SIANN)” 。

对比

传统神经网络痛点:

  • 全连接参数爆炸(1000x1000图片 → 100万权重)
  • 忽略空间局部性(远处像素强行关联)

CNN对比优势:

特性 全连接网络 CNN卷积网络
参数量(1000x1000图) 10^6 级 10^4 级(降99%)
空间信息处理 破坏局部结构 保留局部特征关联
平移不变性 有(物体移动仍可识别)
典型应用 结构化数据预测 图像/视频/医疗影像

CNN卷积网络的优势:

  1. 能够将大数据量的图片有效的降维成小数据量(并不影响结果)
  2. 能够保留图片的特征,类似人类的视觉原理

怎么做

三层功能

  1. 输入层:接收数据(如28x28像素的手写数字图片)
  2. 隐藏层:层层提取特征(线条→局部图案→完整数字)
    1. 提取特征(卷积):卷积核(3x3像素)在图片上滑动,提取局部特征
    2. 池化(降维):缩小图片尺寸,减少参数量,防止过拟合
    3. 激活(非线性):防止过拟合,提升模型泛化能力
    4. 全连接:将提取到的特征组合起来,形成分类器
  3. 输出层:给出预测结果(概率最大的数字0-9)

卷积执行可视化: https://poloclub.github.io/cnn-explainer/

实际应用

  • 图像分类:识别图片中的物体,如猫、狗、飞机、汽车等
  • 目标检测:识别图片中的物体位置,如人脸、车辆、动物等
  • 目标分割:识别图片中的物体位置和类别,如人、车、树、草等
  • 人脸识别:识别图片中的人脸,如人脸验证、人脸检索等
  • 图像生成:生成图片,如风格迁移、图像修复等

冷知识

  • 深度CNN(如ResNet-152)中,仅15%卷积核激活显著,其余对输出贡献微弱。​​剪枝技术​​可删除冗余核,模型缩小90%,精度损失<1% —— 手机端CNN的部署基础
  • 2016年击败李世石的AlphaGo,其策略网络实为​​13层CNN

参考资料