AI Agent从无到有39: LangChain 的链式开发核心:Runnable 接口与 LCEL

LangChain工程化设计:Runnable、StateGraph与可观测性实战 LangChain作为主流AI应用开发框架,其核心价值早已超越简单的API胶水层,演进为支撑生产级Agent的运行时中间件。理解Runnable抽象层是掌握异步调度、批量处理与组件治理的前提;StateGraph则将非确定性Agent行为建模为可持久化、可追踪的状态机,解决上下文丢失与中断续聊等关键问题;而CallbackHandler构成AI系统的可观测性神经中枢,支撑性能埋点、审计合规与智能降级。这些能力共同构成Production-Ready Chain编排的技术底座,广泛应用于客服对话系统、采购比价 阅读详情

纲要

  • Runnable 接口
    • 基于 Pydantic 的输入输出类型约定
    • 标准调用方法:invoke、batch、stream、ainvoke、abatch、astream
    • RunnableConfig:运行时动态配置(回调、标签、元数据、最大并发数)
    • 所有 LangChain 核心组件均实现该接口
  • LCEL(LangChain Expression Language)
    • 管道操作符 | 实现顺序组合
    • RunnableSequence 与 RunnableParallel
    • 并行编排与顺序编排的行为差异
    • 惰性求值与流式传输支持
  • 适用场景与选型建议
    • 线性流程:LCEL 最佳实践
    • 复杂分支/循环/多智能体:推荐 LangGraph
    • 旧版预制链(LLMChain、ConversationChain 等)迁移策略
  • 完整可运行示例
    • 使用 FakeListChatModel 模拟大模型,无需 API Key
    • 顺序链与并行链的对比实现
  • 版本要求
    • langchain-core >= 0.1.0,langchain >= 0.2.0

引言

LangChain 的核心设计理念是将不同的处理单元(提示词模板、大语言模型、输出解析器等)串联为可组合的处理流水线。在 v0.2.0 版本之后,LangChain 引入了一套统一的组件协议——Runnable 接口,并基于该接口构建了声明式的编排语言 LCEL(LangChain Expression Language)。

Runnable 接口为所有组件定义了标准化的交互契约,而 LCEL 则通过管道操作符 | 提供了直观的链式组合能力。理解二者的设计哲学与实现细节,是高效编排 LLM 工作流的基础,也是将旧版预制链(如 LLMChain、ConversationChain)平滑迁移至现代链式开发框架的关键路径。

Runnable 接口:组件通信的标准协议

统一的输入输出约定

LangChain 中所有标准组件(提示词模板、聊天模型、LLM、输出解析器、检索器、工具等)均实现了 Runnable 接口。该接口对每个组件的输入类型和输出类型做出了明确约定,确保不同组件之间能够无缝衔接:

  • 提示词模板(ChatPromptTemplate、PromptTemplate):接受 dict 类型的输入(包含模板变量),输出 PromptValue 或其子类实例,可被聊天模型或 LLM 直接消费。
  • 聊天模型(BaseChatModel):接受 BaseMessage、BaseMessage 序列或 PromptValue,输出 BaseMessage 或其子类(如 AIMessage)。
  • 输出解析器(BaseOutputParser):输入为上一环节的输出(如 AIMessage 的文本内容),输出类型取决于具体解析器实现(str、dict、Pydantic 模型等)。

上述类型约束基于 Pydantic 实现,能够在开发阶段提前捕获类型不匹配问题,避免运行时因数据格式错误导致的异常。

标准调用方法

Runnable 接口定义了一套统一的调用入口,所有实现该接口的组件均支持以下核心方法:

方法说明
invoke(input, config=None)同步单次调用,返回计算结果
batch(inputs, config=None)同步批量调用,输入为列表,返回列表
stream(input, config=None)同步流式输出,逐块返回结果
ainvoke(input, config=None)异步单次调用
abatch(inputs, config=None)异步批量调用
astream(input, config=None)异步流式输出

这些方法使得任意 Runnable 组件都可以被统一调用、替换和组合,开发者无需关心底层实现差异,极大降低了模块间的耦合度。

RunnableConfig:运行时动态配置

每个 Runnable 方法均可接收一个可选的 RunnableConfig 参数,用于在调用时注入运行时配置信息,包括但不限于:

  • 回调函数(callbacks):支持在链的执行生命周期中插入自定义逻辑(日志、追踪、指标上报等)。
  • 标签(tags):为本次调用添加标签,用于过滤和分类追踪数据。
  • 元数据(metadata):附加自定义键值对,便于链路追踪与调试。
  • 最大并发数(max_concurrency):限制 batch 调用时的并发度。
  • 可配置字段(configurable):动态覆盖链中特定组件的参数(如提示词模板变量、模型温度等)。

RunnableConfig 为链式调用的可观测性和动态配置提供了标准化通道。

Runnable

+invoke(input, config?) : Any

+batch(inputs, config?) : List[Any]

+stream(input, config?) : Iterator[Any]

+ainvoke(input, config?) : Awaitable[Any]

+abatch(inputs, config?) : Awaitable[List[Any]]

+astream(input, config?) : AsyncIterator[Any]

PromptTemplate

+format(**kwargs) : PromptValue

+invoke(input, config?) : PromptValue

ChatPromptTemplate

+format(**kwargs) : PromptValue

+invoke(input, config?) : PromptValue

BaseChatModel

+invoke(messages, config?) : ChatMessage

+stream(messages, config?) : Iterator[ChatMessage]

BaseOutputParser

+parse(text) : Any

+invoke(input, config?) : Any

FakeListChatModel

LCEL:简洁的链式编排语言

LCEL 是基于 Runnable 接口构建的领域特定语言(DSL),其核心目标是通过声明式语法将多个 Runnable 组件组合为可执行链,同时保留对流式传输、批量处理和异步调用的完整支持。

管道操作符与顺序组合

通过管道操作符 | 可以将任意两个 Runnable 串联为顺序执行链,数据从左至右依次流经每个组件:

from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_community.chat_models import ChatOpenAI

model = ChatOpenAI(model="gpt-4o-mini")
prompt = ChatPromptTemplate.from_template("用中文解释:{topic}")
parser = StrOutputParser()

# 管道组合
chain = prompt | model | parser

# 等价写法:RunnableSequence
# from langchain_core.runnables import RunnableSequence
# chain = RunnableSequence(first=prompt, middle=[model], last=parser)

# 等价写法:pipe 方法
# chain = prompt.pipe(model).pipe(parser)

无论链的长度如何,组合后的 chain 本身仍然是 Runnable 实例,可以继续与其他组件组合或直接调用其标准方法。

LCEL 组合的另一个关键特性是惰性求值:| 操作符仅构建计算图,不立即执行任何计算。实际执行发生在调用 invoke、batch、stream 等方法时,这使得链的构建与执行完全解耦。

并行组合

RunnableParallel 允许将多个分支并行执行,并将各分支的输出汇总为单一字典。它接受一个字典,其中每个键对应一个独立的 Runnable 子链。

同步模式下,RunnableParallel.invoke() 按字典序(Python 3.7+ 字典保持插入顺序)依次执行各分支,并非真正的多线程并行;异步模式(ainvoke)下则同时调度多个协程,可实现真正的并发执行。

from langchain_core.runnables import RunnableParallel

# 构建两个独立的顺序链
chinese_chain = chinese_prompt | model | StrOutputParser()
english_chain = english_prompt | model | StrOutputParser()

# 并行组合(同步模式下顺序执行各分支,异步模式下并发执行)
parallel_chain = RunnableParallel(
    chinese=chinese_chain,
    english=english_chain
)

# 同步调用
result = parallel_chain.invoke({"topic": "AI Agent"})
# 输出: {"chinese": "...", "english": "..."}

RunnableParallel 的典型应用场景包括:

  • 同一输入需要多种不同处理方式(如多语言翻译、多模型投票)
  • 数据增强(同时从多个检索器获取上下文)
  • 监控与副流程(主链执行的同时记录日志或指标)

使用场景与选型建议

场景特征推荐方案理由
线性流程(提示词 → 模型 → 解析器)LCEL代码简洁、原生支持流式和批处理
简单条件路由(if-else 分支)LCEL 配合 RunnableBranch内置支持,但仅适合分支较少的情况
复杂循环、状态管理、多智能体协作LangGraph基于图的状态机,支持确定性循环和持久化
旧版预制链迁移LCEL 或 LangGraph 重写获得完全的灵活性和可观测性

LCEL 在处理线性流程时表现最佳,代码可读性高且易于维护。当流程中包含嵌套循环、动态条件分支或多个智能体之间的消息传递时,LangGraph 提供了更强大的图编排能力,允许以状态图的方式精确控制执行流。两种方案均由 LangChain 官方维护,开发者可根据实际复杂度灵活选择。

API 速览

langchain_core.runnables.Runnable

所有 Runnable 组件的基类。

核心方法签名:

  • invoke(input: Any, config: Optional[RunnableConfig] = None) -> Any
  • batch(inputs: List[Any], config: Optional[RunnableConfig] = None) -> List[Any]
  • stream(input: Any, config: Optional[RunnableConfig] = None) -> Iterator[Any]
  • ainvoke(input: Any, config: Optional[RunnableConfig] = None) -> Awaitable[Any]
  • abatch(inputs: List[Any], config: Optional[RunnableConfig] = None) -> Awaitable[List[Any]]
  • astream(input: Any, config: Optional[RunnableConfig] = None) -> AsyncIterator[Any]
  • pipe(other: Runnable) -> RunnableSequence

langchain_core.runnables.RunnableSequence

由 | 操作符或 RunnableSequence 构造器生成的顺序链。

构造方式:

from langchain_core.runnables import RunnableSequence

# 方式一:管道操作符
chain = step1 | step2 | step3

# 方式二:显式构造
chain = RunnableSequence(first=step1, middle=[step2], last=step3)

langchain_core.runnables.RunnableParallel

并行执行多个分支,汇总结果。

构造方式:

from langchain_core.runnables import RunnableParallel

parallel = RunnableParallel(
    branch_a=chain_a,
    branch_b=chain_b,
)

返回值类型:Dict[str, Any],键与构造时的参数名一致。

langchain_core.runnables.RunnableConfig

运行时配置对象。

主要字段:

  • callbacks: Optional[Callbacks]:回调处理器
  • tags: Optional[List[str]]:标签列表
  • metadata: Optional[Dict[str, Any]]:元数据
  • max_concurrency: Optional[int]:最大并发数
  • configurable: Optional[Dict[str, Any]]:可动态覆盖的字段

完整 Demo

以下示例使用 FakeListChatModel 模拟大模型行为,无需真实 API Key,可直接运行以体验 LCEL 的顺序链与并行链编排。

运行说明

  1. 安装依赖:
pip install langchain langchain-core langchain-community
  1. 将以下代码保存为 lcel_demo.py。

  2. 运行脚本:

python lcel_demo.py

完整代码

# lcel_demo.py
from langchain_core.prompts import ChatPromptTemplate
from langchain_core.output_parsers import StrOutputParser
from langchain_core.runnables import RunnableParallel, RunnableConfig
from langchain_community.chat_models.fake import FakeListChatModel


def main() -> None:
    # ---------- 1. 准备模拟模型 ----------
    # 预设回答列表:第一次调用返回中文,第二次返回英文
    responses = [
        "AI Agent 是能够感知环境并采取行动以实现目标的智能体。",
        "An AI Agent is an intelligent entity that perceives its environment and takes actions to achieve goals."
    ]
    model = FakeListChatModel(responses=responses)

    # ---------- 2. 构建顺序链 ----------
    chinese_prompt = ChatPromptTemplate.from_template("用中文简单解释:{topic}")
    chinese_chain = chinese_prompt | model | StrOutputParser()

    english_prompt = ChatPromptTemplate.from_template("Briefly explain in English: {topic}")
    english_chain = english_prompt | model | StrOutputParser()

    # ---------- 3. 并行链:中英文同时解释 ----------
    parallel_chain = RunnableParallel(
        chinese=chinese_chain,
        english=english_chain
    )

    # ---------- 4. 调用并行链 ----------
    result = parallel_chain.invoke({"topic": "AI Agent"})
    print("并行输出:")
    print("中文:", result["chinese"])
    print("英文:", result["english"])

    # ---------- 5. 单独调用顺序链 ----------
    print("\n顺序链单独调用:")
    print(chinese_chain.invoke({"topic": "Runnable 接口"}))


if __name__ == "__main__":
    main()

代码说明

  • FakeListChatModel 按顺序返回预设的响应列表,第一次调用返回第一个元素,第二次返回第二个,以此类推。在并行链中,chinese_chain 和 english_chain 分别调用模型,故模型按顺序依次返回中文和英文预设内容。
  • RunnableParallel 将输入 {"topic": "AI Agent"} 同时传递给两个子链,最终汇聚为包含 chinese 和 english 键的字典。
  • 该示例展示了 LCEL 的声明式组合能力,无需显式编写循环或条件语句,即可实现多路并发处理。

技术点总结

  • Runnable 接口的统一调用协议
  • RunnableParallel 的多分支并发编排
  • FakeListChatModel 的模拟测试用法
  • LCEL 的惰性求值特性(| 仅构建图,不执行)

参考文档

官方文档

参考链接

总结

本文系统阐述了 LangChain 中 Runnable 接口与 LCEL 的设计原理与使用方法。Runnable 为所有组件提供了标准化的输入输出类型和统一调用方法(invoke、batch、stream 及其异步版本),并支持通过 RunnableConfig 实现运行时动态配置。

LCEL 基于 Runnable 构建,通过管道操作符 | 实现顺序组合,通过 RunnableParallel 实现并行编排,其惰性求值特性使链的构建与执行解耦,同时保留了完整的流式和批处理能力。

对于线性流程,LCEL 提供了最简洁的实现方式;对于复杂的分支、循环或多智能体场景,LangGraph 可作为补充工具。掌握这一套组合拳,将显著提升 LLM 应用开发的效率与可维护性。

纯前端实现的轻量级 Markdown 编辑器:左侧写、右侧实时预览 Toolion Markdown Editor 是一款纯前端、免登录的轻量级 Markdown 工具,支持实时双栏预览、XSS 安全净化、标签系统、全文搜索、自动保存与备份导出。基于 React 19 与 marked,集成 localStorage 持久化、i18n 多语言、暗色模式及快捷键操作,满足技术写作与笔记管理需求,开箱即用,安全高效。 阅读详情

相关推荐

焦距与视差的关系及其对深度估计的影响

焦距在立体视觉中的作用至关重要,它直接影响视差的大小,从而影响深度估计的精度。焦距越长,视差差异越大,物体的深度估计就越精确。这一关系使得焦距长的相机在一些需要高精度深度估计的应用场景中更加优越。了解焦距与视差的关系,对于优化相机配置和提升深度估计精度具有重要意义。在实践中,选择合适的焦距对于获得精确的深度信息至关重要,特别是在自动驾驶、虚拟现实、三维重建等领域,精确的深度估计能够提供更好的用户体验和技术支持。

计算机科学与技术专业学生的成长之路 1674

Langchain 总结(上)

学习笔记

qq_62260432的博客 239

ue4 角色奔跑/冲刺/蹲下 /蹲走 动作切换蓝图

序列:文章分为4部分: 一、准备工作+简单的蓝图连线 二、编写“行走” 混合空间 三、编写“蹲下”混合空间 四、合成2个动画,设置动画蓝图 —————————————— 一、准备工作 下载“动画初学者包”,添加到项目! 主要文件: 打开BP_playerCharacter,组价——添加组件,找到“摄像机”,“机臂” 没有找到就去其他项目复制过来 ———————————— 手写人物的移动,也可以在...

凉城古梦猫扑街的博客 4864

LangChain 快速接入及聊天模型定义与工具调用

本文主要介绍了langchain的api快速接入、聊天模型的定义与工具调用、绑定、创建等内容

Dai_renwen的博客 399

Uniapp-APP后台保活插件(安卓后台保活)

Uniapp-APP后台保活插件(安卓后台保活)亲测有效!

weixin_57844432的博客 1万+

AIDD机器学习深度学习药物发现与设计教程总结

AIDD(AI Drug Discovery & Design):是近年来非常火热的技术应用,且已经介入到新药设计到研发的大部分环节当中,为新药发现与开发带来了极大的助力。倾向于机器对数据库信息的自我学习,可以对数据进行提取和学习,一定程度上避免了化合物设计过程中的试错路径,同时还会带来很多全新的结构,为药物发现打破常规的结构壁垒。覆盖了机器学习和深度学习,能与新药研发相结合并实质性的应用到靶点预测、高通量筛选、药物设计、药物的ADMET性质预测等;且算力方面,由早期应用于药物发现领域的决策树、随机

wutianlin0723的博客 6819

Web 版翻译者资料库

本项目是桌面版《翻译者资料库》的 Web 移植版,基于 Spring Boot 3.3、Thymeleaf、Bootstrap 5.3 与 MySQL 8.0 构建。它面向翻译写作提供资料、词汇、句库、文本工具、对照制作、查找、备份恢复及旧库迁移等功能,完整继承桌面版核心业务规则,支持一键启动与离线访问。

howard2005的专栏 180

【人工智能】你知道什么是DeepSeek吗?你有去了解过DeepSeek吗?新手要入门DeepSeek的必经之路——初识DeepSeek

【人工智能】初识DeepSeek 详细介绍DeepSeek以及DeepSeek-R1

蒙奇D索大的博客 3415

Jackson 序列化 / 反序列化注解 完整版笔记

Jackson 序列化 / 反序列化注解 完整版笔记

handsome_sai的博客 306

vasp算表面吸附流程_VASP表面吸附计算实例分析

本文主要为了记录在学习Vasp计算过程中如何设置INCAR中的一些参数,并不着重讲解其含义,详见可自行到vasp官网查阅。其次关于建模部分也不做细致讨论,一般结构可从Materials Studio里自带的晶体数据库导出,或从三大数据库网站上下载:1、Materaials Project网址:https://materialsproject.org/(强烈推荐,邮箱注册即可使用)2、CCDC网址:...

weixin_39617669的博客 2241

h5支付不能打开支付宝 ios_iOS支付宝H5支付无法返回APP解决方案

本文前大段在讲楼主是如何解决这个问题的,以及中间遇到的麻烦。赶时间的同学可以直接看最后的 最终解决方案。在讨论之前,我们先看看官方文档上的一句话:注意:在iOS系统中,唤起支付宝App支付完成后,不会自动回到浏览器或商户APP。用户可手工切回到浏览器或商户APP;支付宝H5收银台会自动跳转回商户return_url指定的页面。what? 官方直接跟我们说GG了?楼主不甘心,还是想尝试一下。借鉴之前...

weixin_39864101的博客 856

MCP 协议会成为前端 AI 工程的标准接口吗?

MCP(Model Context Protocol)正在成为连接 AI 模型与外部工具、数据源的一层通用协议。本文从 MCP 的核心机制出发,分析它在浏览器与前端工程中的落地边界,讨论它能否成为前端 AI 工程的标准接口,并给出当下更务实的架构选择建议。

m0_62937412的博客 387

Boost.Interprocess 共享内存通信优化实战

本文探讨使用Boost.Interprocess库优化共享内存通信的方法。通过直接使用Eigen::Vector3d避免精度损失,减少数据拷贝,采用timed_send/timed_receive防止死锁,并优化序列化过程。优化后的代码显著提高了性能,特别适用于高频率数据交换场景。实验表明,这些改进能有效提升通信稳定性和传输效率。

2501_90323865的博客 91

LangGraph 本地 build 频频翻车,最终在服务器跑通流式对话

先说结论:我本地那个,一次都没成功过。三次,三次,全挂在拉镜像上。而顺得像刚上过油。这就很像我高中那辆自行车:骑着能走,一上锁就坏。那天晚上我盯着终端里那行红字看了很久,想的不是技术方案,想的是——为什么同一个工具,可以一边让我觉得自己很行,一边让我觉得自己不太行。

人工智能AI技术 321

STM32F407中文手册

STM32f407中文手册 本参考手册面向应用开发人员,提供有关使用 STM32F405xx/07xx、STM32F415xx/17xx、 STM32F42xxx 和 STM32F43xxx 微控制器存储器与外设的完整信息。STM32F405xx/07xx、STM32F415xx/17xx、STM32F42xxx 和 STM32F43xxx 构成一个微 控制器系列,各产品具有不同的存储器大小、封装和外设。有关订购信息以及器件的机械与电气特性,请参见数据手册。有关 ARM Cortex™-M4F 内核的信息,请参见《Cortex™-M4F 技术参考手册》。

Camera2Demo

在Camera2 的基础上进行封装,使得Camera2一堆初始化逻辑与Activity分离,降低耦合度,完成预览拍照并保存的操作

带着小白学习-微服务-6 实战:网关

地址栏输入:http://localhost:8088/goods/index,这时候就不是到8100端口去调用了,而是8088直接通过路由转发,分别到nacos对应的goods对应的服务中区调用。** 可以看出,这里将前面已经正常运行的server-store子工程(库存服务,服务提供方),server-goods子工程(商品服务,服务消费方)。(1)uri: lb://store 代表要到nacos的注册中心的服务列表中找到服务名为store的微服务;,网关是做路由转发,不是服务调用;

wdyan297的博客 238

IEM模型,地表粗糙度模拟

利用微波反演土壤水分时候,利用IEM模型可以实现对随机地表的模拟

海外平台频繁弹验证?从 DNS、WebRTC 到浏览器指纹的环境异常排查清单

在运营多地区海外平台账号时,即使代理节点通畅、TCP 握手成功,仍可能遇到频繁人机验证、地区限制、播放失败等异常。核心结论是:这类问题往往不在网络传输层,而在浏览器环境参数与网络出口之间的逻辑自洽性。本文从 DNS 泄漏、WebRTC 穿透、时区与语言匹配、Canvas/WebGL 指纹、TLS 特征五个维度,给出一份可复现的环境异常排查清单,并对比个人手动配置与工程化环境管理方案的适用边界。适用于跨境运营、多账号运维团队。

P1Browser【p1指纹浏览器】的博客 229

jdk-8u144-linux-x64.tar.gz.

该资源为搭建Linux系统Java环境用,资源的后缀为tar.gz格式的压缩包

智能问诊的流程

本文介绍基于FastAPI构建的医疗多Agent系统MediAgent,通过症状分析、诊断推理与治疗建议等模块协同,实现从问诊到报告生成的完整工作流。系统采用前后端分离架构,结合MySQL、RabbitMQ与Docker实现工程化部署,支持异步化验结果接入。虽当前状态暂存于内存,但已具备可扩展性,未来可通过Redis持久化、消息队列联动及医疗安全机制完善,应用于慢病管理、辅助决策等场景,推动AI在医疗流程中的落地应用。

Joey 的工作空间~ 785

基于 YOLOv8 的森林火灾检测系统(Web 版)

本项目面向林区早期火情识别场景,使用YOLOv8完成火焰(Fire)与烟雾(Smoke)两类目标的检测模型训练,并以FastAPI构建 Web 检测平台,把模型能力封装为可直接登录使用的系统。平台除常规的图片、批量、视频、摄像头检测外,还提供同图多权重对比、数据集浏览与标注核对、模型热切换,以及把训练搬到网页上的能力:可在浏览器配置超参数发起真实训练,训练中在线调整学习率、查看进度与动态曲线,训练完成后下载产物或直接应用到检测。

Michael_Jay的博客 69

HTML5 History API 详解:前端路由底层原理

pushState改 URL 不刷新popstate接浏览器导航服务端必须兜底 SPA 入口前端路由的本质不是“魔法”,而是:把「URL 字符串」变成「组件渲染函数」的映射表,再让浏览器历史栈和这张表保持同步。

2603_94941239的博客 213

身份验证漏洞专题(三):持久登录、密码重置与密码修改中的凭据绑定缺陷

密码登录与双因素认证是身份验证的主干流程,但一个完整的认证体系还依赖三类辅助机制:持久登录("记住我")、密码重置、密码修改。这三类机制的共同特征是:它们同样携带或验证凭据,同样直接决定认证状态的归属,但实现时获得的防护强度往往远低于登录页面本身。攻击者绕不开登录接口时,常常可以从这些辅助入口进入。

2401_85321170的博客 650

2026 年前端框架排行榜

前端框架是用于构建用户界面的工具集合,通过预设组件、网格系统和样式规范提升开发效率与可访问性。2026年主流框架包括:React(生态领先,适合全栈)、Next.js(SSR/SEO优化,主流选择)、Vue(学习友好,中小团队首选)、Angular(企业级稳定)、Svelte与Astro(性能突出)。趋势显示,服务端渲染、TypeScript、AI工具融合及轻量化成为关键方向。就业建议:优先学React+Next.js;追求易用选Vue;企业级项目可学Angular;追求极致性能可尝试Svelte或Astr

lxttzlove的博客 245

Vue 前端开发 AI 对话页面:流式消息渲染、文件上传

关键点是不能手动设置 Content-Type 为 multipart/form-data,必须由浏览器自动生成带有 boundary 的请求头,否则后端无法解析。思路:将对象序列化为 JSON 字符串,作为 FormData 的一个普通字段(如 formData.append(‘payload’, JSON.stringify(data))),后端接收该字段后再反序列化。若上传大文件(>10MB),需实现独立的分片上传接口,在提交对话前先获取文件 id 或 url,再随文本发送引用。移除输入框的禁用态;

2402_85729970的博客 397

前端要加密手机号,密钥却不能下发:一次一密的 ECDH + HKDF 方案(十六)

前端加密手机号需避免密钥暴露,采用ECDH协商临时密钥,结合HKDF派生并绑定协议上下文,使用AES-GCM实现认证加密。关键在于两端参数严格一致:曲线、编码格式、盐值与info字段逐字节相同。避免直接哈希共享秘密或日志泄露密钥,服务端返回临时公钥并签名,前端先验签再派生密钥,确保前向安全与防中间人攻击。最终密文结构包含公钥、nonce、密文与认证标签,支持自校验。

tantan的小记录 400

浏览器端素材压缩与上传实践:从 Canvas 到 WebCodecs 与 FFmpeg 回退

本文介绍浏览器端素材上传的完整处理链路,重点解决图片与视频超限问题。图片通过Canvas等比缩放与质量压缩,逐级优化至2MiB内;视频则优先使用WebCodecs硬件编码,结合分辨率降级、码率预算与FFmpeg WASM回退,确保在20MiB内完成转码。强调“先确认后处理”原则,避免无谓资源消耗,并通过多层能力检测保障兼容性与性能。核心思想:压缩成功 ≠ 上传成功,需独立校验。

林恒的博客 347

Geejing WebBuilder AI SQL:一句话生成查询的完整链路与「生成不执行」边界

企业里真正卡住数据核对的,很少是「不会写 SQL」。更常见的是三件小事叠在一起:这张表到底叫什么、日期字段是 `DATE` 还是字符串、当前这套库分页该用 `LIMIT` 还是别的写法。一个熟手要先翻一遍表结构,生手干脆把需求丢给 DBA,一来一回半天就过去了。

m0_60539919的博客 256

从一次检测到持续验证,重新认识 Web 应用安全测试

围绕漏洞修复后再次出现的问题,结合 Burp Suite DAST 与 GraphQL 示例,解析周期检测、证据管理和整改复测的实现思路。

m0_75220675的博客 336
上一篇: AI Agent从无到有38: 输出解析器的容错机制与自定义实战
下一篇: AI Agent从无到有40: LangChain 链式调用实战:管道、流式、并行与迁移
Wang's Blog
博客等级 码龄12年 7438粉丝 2421原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Wang's Blog

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值