惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

M
MIT News - Artificial intelligence
D
Darknet – Hacking Tools, Hacker News & Cyber Security
SecWiki News
SecWiki News
Latest news
Latest news
A
Arctic Wolf
Know Your Adversary
Know Your Adversary
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
T
Tor Project blog
T
Threatpost
S
Schneier on Security
P
Palo Alto Networks Blog
C
Cyber Attacks, Cyber Crime and Cyber Security
Cyberwarzone
Cyberwarzone
C
Cybersecurity and Infrastructure Security Agency CISA
C
CERT Recently Published Vulnerability Notes
博客园_首页
P
Privacy & Cybersecurity Law Blog
I
Intezer
PCI Perspectives
PCI Perspectives
Spread Privacy
Spread Privacy
G
Google Developers Blog
H
Help Net Security
WordPress大学
WordPress大学
aimingoo的专栏
aimingoo的专栏
CTFtime.org: upcoming CTF events
CTFtime.org: upcoming CTF events
V
Visual Studio Blog
U
Unit 42
Application and Cybersecurity Blog
Application and Cybersecurity Blog
W
WeLiveSecurity
D
DataBreaches.Net
N
News and Events Feed by Topic
AI
AI
The Register - Security
The Register - Security
云风的 BLOG
云风的 BLOG
The GitHub Blog
The GitHub Blog
Help Net Security
Help Net Security
K
Kaspersky official blog
Recent Announcements
Recent Announcements
cs.CV updates on arXiv.org
cs.CV updates on arXiv.org
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
S
Security @ Cisco Blogs
H
Hacker News: Front Page
Jina AI
Jina AI
S
Secure Thoughts
Project Zero
Project Zero
T
The Exploit Database - CXSecurity.com
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
B
Blog RSS Feed
爱范儿
爱范儿

博客园_首页

Plist 二进制格式 Milvus 和 PGVector,哪个更好? OpenClaw 已过时?在 VS Code 中运行 Hermes Agent! 第30篇文章:一个大三计科生的自白 Manim如何在数学公式中完美显示中文? Docker 部署 RocketMQ 5 并发编程核心概念辨析 C#事务处理最佳实践:别再让“主表存了、明细丢了”的破事发生 CLI 是什么?为什么大厂突然集体卷命令行? 【从0到1构建一个ClaudeAgent】协作-自主Agent UIImageView 设置图片不生效的原因排查 最小二乘问题详解20:无先验约束下的增量式SFM自由网平差 痞子衡嵌入式:大话双核i.MXRT1180之XIP应用里借助MU实现可靠Flash IAP的方法 AI Chat 封装, SemanticKerne.AiProvider.Unified 已发布 Windows下右键编辑js文件无法打开记事本——在注册表中使用环境变量 在后台服务中使用 Scoped 服务,为什么总是报错? H200 安装驱动并使用sglang启动模型 wireshark 抓包Trap上报告警内容 我用 AI 辅助开发了一系列小工具(2):图片压缩工具 [A Primer On MC and CC] 2.1 Memory Consistency 1 - 指令重排序和 SC 模型 Oracle数据库SCN推进技术详解与实践指南 玩转控件:封装个带图片的Label控件 Claude Code 4.7 真正该升级的不是模型,而是你的工作流 前端小白一句话,AI 帮我做了个颜值拉满的桌面媒体播放器。当代码不再是门槛,一句话编程就是现实。 5. WorkBuddy: 小龙虾的灵魂三件套,让你的小龙虾不只是工具 SQLite 分片方案实战:三种分片策略的深度对比 告别简陋 UI!一款基于 Fluent Design 和基于 WinUI 的开源免费、现代化的 Avalonia UI 控件库 关于二进制排列组合枚举的总结 AI开发-python-LangGraph框架(3-27-LangGraph从零实现大模型智能决策工作流) ElasticSearch主分片和副本分片概念详解 【002】HTTPS 粗解:证书、TLS 握手与对后端配置的影响 Hermes Agent 一周暴涨五万 Star,但我劝你别急着追 明明连接的是Redis的DB0,为什么能查到DB3的数据? 【从0到1构建一个ClaudeAgent】协作-Agent团队 熟悉电子元器件之后,电子小白下一步该怎么走? MAF快速入门(23)通过C#类定义Skills .NET 高级开发 | 手写一个对象映射框架 FastAPI数据库ORM怎么选?我肝了三个Demo后,终于不再纠结了 mysqldump 参数拾遗:在遗忘与铭记之间 C# .NET 周刊|2026年3月5期 Claude code入门 - 陈彦斌 一文学习入门 ThingsBoard 开源物联网平台 GitHub 热门项目 | 2026年04月16日 如何为GIT设置全局勾子,为每次提交追加信息 Number.isFinite和isFinite与isNaN()和Number.isNaN的区别 PortSwigger SQL注入LAB2 推荐一个测试人必备的Skills,从功能到性能全搞定(附详细实操和安装下载方式) 筑基期:掌握Odoo基础核心知识点02(Odoo XML 开发方式详解) GLM模型这么火,咱们用vllm也咧一个呗! 深入理解 AbortController:从底层原理到跨语言设计哲学 字符串学习笔记 多租户系统框架的基础模块设计和分析设计 Apache SeaTunnel Zeta 为什么能做到“又快又稳”? AI开发-python-LangGraph框架(3-26-LangGraph基本概念及第一个简单样例) Vue 3 组件通信,别只会用 Props 和 Emits 了,这几个狠活儿你得看看 ElasticSearch7.X版本配置密码 用Manim实现动态交点计算--从一个动点问题说起 团结引擎+Addressable+Instant Game打包抖音小游戏 function call 实战:让 LLM 自动判断 pod 异常、调用日志工具并完成故障分析 bubseek —— 让 Agent 的足迹,变成团队的洞察 通过 C# 读取并导出 PDF 书签 如何用 GitHub Actions 实现 Steam 自动化发布 【从0到1构建一个ClaudeAgent】并发-后台任务 .NET 高级开发 | 定制 ASP.NET Core 框架 电子小白:什么是运算放大器(运放) zero2Agent:面向大厂面试的 Agent 工程教程,从概念到生产的完整学习路线 堆上的ORW HC32F460 USB CDC通信异常:非对齐访问异常排查 20260413-Hyperbridge 攻击事件:发生在默克尔山上的验证绕过 那些喊着AI 要淘汰你的人,正在靠你的焦虑赚大钱! 深度学习进阶(八)Swin Transformer 最小二乘问题详解19:带先验约束的增量式SFM优化与实现 SnapTranslate 3.0 正式发布:全局划词翻译 + 完整英语学习闭环,一站式搞定查词、记词、复习 工作的意义、工作的困难认知再思考 .NET + AI 进阶实战:基于类的技能开发 - 打造可治理的 Agent 能力模块 【从0到1构建一个ClaudeAgent】规划与协调-技能 上周热点回顾(4.6-4.12) 电子小白的工具三件套:面包板、杜邦线、万能板 单表五亿数据的查询优化 | Mysql、StarRocks 2. WorkBuddy:从“我是谁”到“帮我干活” C# 如何减少代码运行时间:7 个实战技巧 基于HelixToolkit.SharpDX 渲染3D模型 - 笺上知微 从零开始的双臂具身VLA起源及现阶段发展综述 - SkyXZ 记对 xonsh shell 的使用, 脚本编写, 迁移及调优 - pluvium27 受够了Vibe Coding的失控?换个起点,让AI事半功倍 从开始配置漏洞环境到漏洞复现流程 - 難しい 关于10年工作经验的程序员对OpenClaw的实战经验分享以及看法 - 虚无境 Any metadata 的内存布局 C# .NET 周刊|2026年3月2期 - InCerry 我帮你测过了,测试圈排名第二的 Skill 依然很牛逼 Skill Discovery | 无监督技能发现的经典工作总结 - MoonOut 上下文工程是什么?过时了么?一文讲明白! - 一枫说码 开了 TUN 模式还是直连?90% 的人都踩过这个坑 AScript扩展多种脚本语言 - rockey627 AI 学习笔记:Agent 的记忆机制 你能被装进一个文件里吗?——7 万人把同事"蒸馏"成了 AI - 我没有三颗心脏 Claude Code 通关手册(七):给 AI 装上技能包——Skills 完全指南 - 暮色之狐 在浏览器中快速编辑代码:VSCode Web 集成实践 - Newbe36524 蒸馏自己 skill?基于 Deepseek 的蒸馏器,丐版蒸馏方式,简单便捷 - To_Carpe_Diem Spring AI Aliababa和AgentScope,哪个更好? - 苏三说技术
AI Agent 30天速成|Day1 核心知识点全解析
云淡风轻YangG · 2026-06-16 · via 博客园_首页

AI Agent 全日制30天速成|Day1 核心知识点全解析

前言

本文是AI Agent 30天速成系列的第一天学习笔记,聚焦大模型基础核心概念、异步LLM调用封装、提示工程核心技巧与SSE流式接口开发,所有代码可直接运行,适合AI Agent开发入门学习者。

一、今日核心学习目标

  1. 吃透大模型Token、上下文窗口、核心调参、流式输出等基础概念
  2. 封装兼容OpenAI标准的异步LLM调用工具类(适配通义千问、DeepSeek)
  3. 掌握提示工程核心技巧,强制模型输出标准JSON格式
  4. 实现SSE流式返回简易接口,夯实Agent对话底层基础

二、核心理论知识点

1. 大模型基础核心概念

(1)Token与上下文窗口

  • Token:文本处理最小单位,中文1个汉字≈2token,英文1单词≈1token;是计费、上下文长度限制的核心单位。
  • 上下文窗口:模型单次请求输入+输出的Token总量上限(如qwen-turbo为128k),超限会导致文本截断、上下文丢失、输出不完整。

(2)高频调参(面试必考)

参数 作用 业务取值建议
temperature 控制输出随机性,0=完全确定,1=自由发散 知识库/工具调用:0.00.1;文案创作:0.70.9
top_p 核采样,控制候选词范围 工具场景0.1,创作场景0.8
max_tokens 限制单次返回最大输出长度 工具查询设512,长文档总结设2048

(3)两种输出模式

  • 同步complete:一次性返回完整结果,适合简单问答、批量处理场景
  • 流式stream(SSE):分段实时输出,前端聊天框、Agent产品必备

(4)统一接口规范

国内主流模型均兼容OpenAI v1接口格式,仅需更换base_urlapi_key,即可用一套代码对接所有模型。

2. 异步调用核心(Python后端重点)

  • 同步requests:阻塞线程,高并发场景性能极差
  • aiohttp异步:适配多并发对话、批量向量生成、流式输出,需封装超时控制、自动重试、异常捕获、请求限速

3. 提示工程三大核心

  1. CoT思维链:在Prompt中加入「请一步步思考,再给出最终答案」,减少推理类幻觉
  2. Few-shot少样本学习:提供1~3条标准输入输出示例,对齐输出格式
  3. 结构化输出约束:强制返回JSON格式,适配Function Calling、RAG检索、工具参数解析场景

三、今日开发难点 & 解决方案

难点1:流式SSE分段乱码、截断、合并错乱

  • data:分隔流式返回块,过滤空行、[DONE]结束标记
  • 缓冲区缓存不完整分片,拼接完整后再解析JSON
  • 封装全局复用的流式解析工具函数

难点2:模型返回自然文字而非标准JSON

  • Prompt明确禁止额外描述,仅返回JSON
  • 正则提取{}内的JSON片段
  • Pydantic模型二次校验,解析失败自动重调模型

难点3:多模型base_url、鉴权头不统一

  • 配置类预设各模型独立参数,代码仅传模型名称自动匹配

难点4:异步并发触发平台限流

  • 信号量控制并发数
  • 捕获429限流异常,实现指数退避重试

四、可直接运行的完整代码

1. 通用LLM异步封装类(llm_client.py)

import aiohttp
import asyncio
import re
from pydantic import BaseModel, Field
from typing import Optional, AsyncGenerator

# 模型配置映射
MODEL_CONFIG = {
    "qwen-turbo": {
        "base_url": "https://dashscope.aliyuncs.com/compatible-mode/v1/chat/completions",
        "api_key": "你的通义千问key"
    },
    "deepseek-chat": {
        "base_url": "https://api.deepseek.com/v1/chat/completions",
        "api_key": "你的deepseek key"
    }
}

# 结构化输出校验模型示例
class OrderQueryResp(BaseModel):
    order_name: str = Field(description="订单名称")
    order_price: float = Field(description="订单价格")
    delivery_status: str = Field(description="配送状态")

class AsyncLLMClient:
    def __init__(self, model_name: str = "qwen-turbo"):
        self.model = model_name
        self.conf = MODEL_CONFIG[model_name]
        self.semaphore = asyncio.Semaphore(5)  # 最大并发5

    async def _request(self, payload: dict, stream: bool = False):
        headers = {
            "Authorization": f"Bearer {self.conf['api_key']}",
            "Content-Type": "application/json"
        }
        timeout = aiohttp.ClientTimeout(total=60)
        async with self.semaphore:
            async with aiohttp.ClientSession(timeout=timeout) as session:
                try:
                    async with session.post(self.conf["base_url"], json=payload, headers=headers) as resp:
                        if resp.status != 200:
                            err = await resp.text()
                            raise Exception(f"模型接口异常: {resp.status}, {err}")
                        if stream:
                            return self._stream_parse(resp)
                        return await resp.json()
                except aiohttp.ClientError as e:
                    raise Exception(f"网络请求失败: {str(e)}")

    async def _stream_parse(self, response) -> AsyncGenerator[str, None]:
        buffer = ""
        async for chunk in response.content.iter_chunked(1024):
            buffer += chunk.decode("utf-8")
            # 分割流式块
            while "data:" in buffer:
                idx = buffer.find("data:")
                end_idx = buffer.find("\n\n", idx)
                if end_idx == -1:
                    break
                data_block = buffer[idx+5:end_idx].strip()
                buffer = buffer[end_idx+2:]
                if data_block == "[DONE]":
                    return
                try:
                    import json
                    data = json.loads(data_block)
                    content = data["choices"][0]["delta"].get("content", "")
                    if content:
                        yield content
                except:
                    continue

    async def chat_sync(self, prompt: str, temperature: float = 0.1) -> str:
        payload = {
            "model": self.model,
            "messages": [{"role": "user", "content": prompt}],
            "temperature": temperature,
            "stream": False
        }
        res = await self._request(payload)
        return res["choices"][0]["message"]["content"]

    async def chat_stream(self, prompt: str, temperature: float = 0.1):
        payload = {
            "model": self.model,
            "messages": [{"role": "user", "content": prompt}],
            "temperature": temperature,
            "stream": True
        }
        async for text in await self._request(payload, stream=True):
            yield text

    # 强制JSON输出封装
    async def chat_json(self, prompt: str, resp_model: BaseModel) -> BaseModel:
        json_prompt = f"""
        {prompt}
        严格要求:仅返回标准JSON,禁止任何解释、注释、markdown、多余文字。
        JSON字段要求:{resp_model.model_json_schema()}
        """
        raw = await self.chat_sync(json_prompt, temperature=0.0)
        # 正则提取JSON
        match = re.search(r"\{.*\}", raw, re.S)
        if not match:
            # 解析失败重试一次
            raw = await self.chat_sync(json_prompt, temperature=0.0)
            match = re.search(r"\{.*\}", raw, re.S)
            if not match:
                raise Exception("模型无法输出合法JSON")
        json_str = match.group()
        return resp_model.model_validate_json(json_str)

# 测试入口
async def test_client():
    client = AsyncLLMClient("qwen-turbo")
    # 测试1:同步JSON结构化输出
    res = await client.chat_json(
        prompt="模拟一个手机订单信息",
        resp_model=OrderQueryResp
    )
    print("结构化结果:", res.model_dump())

    # 测试2:流式输出
    print("\n流式输出:")
    async for chunk in client.chat_stream("简单介绍AI Agent"):
        print(chunk, end="")

if __name__ == "__main__":
    asyncio.run(test_client())

2. FastAPI流式对话接口(main.py)

from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import asyncio
from llm_client import AsyncLLMClient

app = FastAPI(title="Day1 LLM流式服务")
llm = AsyncLLMClient()

# SSE封装生成器
async def stream_generator(user_prompt: str):
    yield "data: 开始生成回答\n\n"
    async for text in llm.chat_stream(user_prompt):
        yield f"data: {text}\n\n"
    yield "data: [DONE]\n\n"

@app.get("/chat/stream")
async def chat_stream(prompt: str):
    return StreamingResponse(
        stream_generator(prompt),
        media_type="text/event-stream"
    )

if __name__ == "__main__":
    import uvicorn
    uvicorn.run("main:app", reload=True)

五、实操练习任务

  1. 替换代码中的API Key,运行llm_client.py测试JSON结构化输出,观察Pydantic校验效果
  2. 启动FastAPI服务,访问http://127.0.0.1:8000/docs调试流式接口
  3. 修改temperature参数(0/0.9),对比模型输出随机性差异
  4. 构造模糊Prompt,验证模型JSON输出重试逻辑

六、高频面试题 & 标准答案

基础问答

1. 什么是Token?上下文窗口超限会出现什么问题?

Token是大模型处理文本的最小单位(中文1字≈2token,英文1单词≈1token),是计费和上下文限制的核心单位。
上下文窗口超限后果:输入被截断导致上下文丢失、多轮对话失忆;输出不完整、逻辑断裂;接口返回400错误;长文本生成任务提前终止。

2. temperature参数作用?工具调用为何推荐0~0.1?

temperature控制输出随机性(0~2),值越低输出越确定,值越高越发散。
工具调用要求参数精准,高随机性会导致参数非法、格式错乱,0~0.1接近贪心采样,能最大化结构化参数准确率。

3. 同步输出与流式SSE的区别及适用场景?

  • 同步输出:一次性返回完整结果,适合后端调用、批量任务、离线处理
  • 流式SSE:分段实时输出,适合前端聊天界面、长文本生成,降低用户等待感知

4. 主流模型兼容OpenAI接口的原因?

OpenAI是行业事实标准,兼容后可一套代码对接多模型、复用生态工具链、降低学习成本、灵活选型对比效果。

5. 大模型接口异常及处理方案?

  • 超时:设置分级超时,搭配指数退避重试
  • 429限流:信号量控并发、速率限制、指数退避重试
  • 401鉴权失败:校验密钥,触发告警不重试
  • 格式异常:正则提取+Pydantic校验+自动重试

工程实操题

1. 强制模型返回标准JSON的3种方案?

  1. Prompt强约束:明确格式要求,禁止多余内容
  2. 接口参数指定:使用response_format=json_object(OpenAI)或厂商对应参数
  3. Function Calling:将JSON定义为函数参数Schema
  4. 后处理兜底:正则提取JSON+Pydantic校验+解析失败重试
  5. temperature=0降低随机性

2. 流式SSE分片截断的解决方案?

  • 缓冲区缓存不完整分片,按data:拆分完整块后解析
  • 仅处理完整的SSE协议行,捕获单条解析异常不中断整体流
  • 全量拼接后二次校验格式

3. requests同步 vs aiohttp异步(并发场景)

维度 requests(同步) aiohttp(异步)
并发模型 多线程/多进程,阻塞IO,切换开销大 单线程协程,非阻塞IO,切换开销极低
并发上限 线程数受限,高并发资源占用高 单线程支撑上千并发,资源占用低
开发成本 逻辑简单,调试容易 需async/await改造,调试复杂度高
适用场景 低并发脚本、简单单次调用 高并发批量调用、服务端后端、Agent多工具并行

4. 控制并发防止429限流的方案?

  • 信号量限制并发数
  • 令牌桶/漏桶控制QPS
  • 捕获429后指数退避重试
  • 连接池复用减少建连开销
  • 限流时降级到备用模型/缓存结果

拓展思考题

1. 多轮对话Token接近上限的优化方案?

  • 滑动窗口:仅保留最近N轮对话
  • 对话摘要:用模型生成历史对话精简摘要
  • 向量检索:仅召回与当前问题相关的历史片段
  • 分层记忆:拆分短期/长期记忆,按需提取
  • 冗余清洗:精简无效文本

2. 工具调用为何必须结构化JSON输出?

  • 机器可直接解析,无需NLP处理
  • 格式稳定,降低参数错误概率
  • 可前置校验字段/类型,快速发现问题
  • 适配通用Agent框架,降低耦合度
  • 异常易追溯、易兜底

总结

Day1重点掌握大模型基础概念、异步LLM封装、结构化输出与SSE流式接口开发,这些是AI Agent开发的核心底层能力。后续将基于此拓展多轮对话、记忆模块、工具调用等进阶内容,建议反复调试代码,吃透面试高频考点。