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

推荐订阅源

GbyAI
GbyAI
Y
Y Combinator Blog
F
Fortinet All Blogs
H
Hackread – Cybersecurity News, Data Breaches, AI and More
N
Netflix TechBlog - Medium
T
Tailwind CSS Blog
aimingoo的专栏
aimingoo的专栏
博客园 - Franky
T
The Blog of Author Tim Ferriss
D
DataBreaches.Net
量子位
博客园 - 三生石上(FineUI控件)
I
InfoQ
Engineering at Meta
Engineering at Meta
WordPress大学
WordPress大学
阮一峰的网络日志
阮一峰的网络日志
爱范儿
爱范儿
D
Docker
美团技术团队
雷峰网
雷峰网
U
Unit 42
Stack Overflow Blog
Stack Overflow Blog
Recent Announcements
Recent Announcements
人人都是产品经理
人人都是产品经理

又耳笔记

用AI挣钱之AI建站:二维码生成器工具 用AI挣钱之AI建站:https://markdowntopdf.top Cloudflare Workers实战番外一:用Static Assets托管网站,告别传统方案 Cloudflare Workers实战(五):不止JavaScript,拥抱Python与Rust Cloudflare Workers实战(四):托管和分发静态文件 Cloudflare Workers实战(三):实现认证、重定向与缓存 Cloudflare Workers实战(二):动态修改后端响应 Cloudflare Workers实战(一):随心所欲操作客户端请求 Cloudflare workers不完全指南 使用n8n创作短篇小说 水果风波:信任的代价 用Python将PDF文件转换成图片 rust网络框架Pingora源码阅读3 rust网络框架Pingora源码阅读2 rust网络框架Pingora源码阅读1 Pingora快速入门教程1之总览 Rust模板引擎askama快速入门引擎 使用Loco快速搭建自己的后台系统 用Rust发一封图文并茂的邮件 Rust小项目: 写一个简单的恶意流量阻断器 Rust小项目: 写一个简单的网页爬虫 Rust命令行库Clap快速入门教程 Rust小项目:用Rust写一个端口扫描器 Rust真全栈开发快速入门 rust声明宏快速入门教程 Rust文本处理快速入门教程 RUST web框架axum快速入门教程6之测试 白嫖免费的Rust在线运行时shuttle RUST web框架axum快速入门教程5之中间件 用Rust来做以太坊开发5之事件日志及签名
Chainlit入门:快速搞定 Python AI 对话机器人(智能体)
About 又耳宁 关于技术与股票的一些零碎想法 · 2026-04-26 · via 又耳笔记

如果你已经用过一些 LLM SDK(其实我只用过Langchain),你会发现一个共性问题:模型调用很快能写出来,但“像样的聊天界面 + 会话管理 + 上线部署”这三件事会很快把代码变复杂。
Chainlit就是专门解决这个问题的:用很少的 Python 代码把对话应用搭起来,并且保留足够的扩展能力。

好吧, 你可能说,我可以让AI生成前端呀, 但是吧, 一是它不一定符合你的需求, 二是它需要你去维护(维护很费成本的哦),三是完善的前端很费token呢。

当然啦,也可以直接使用langchain自带的部署功能,不过还需要注册个账户,还不知道后面会不会额外收费,总的来说感觉差了一点什么,可能这是大多数流行应用不用langchain的原因?

其实langsmith的功能是真的棒,可是我就是不想注册个账户而已.

其实除了选择Chainlit还有很多其他的方式接入其他前端方案,比如Streamlit或者将Langchain包装一下,使用fastapi提供兼容OpenAI接口的接口,这样就可以接入很多其他的前端方案了,因为大多数前端方案都支持OpenAI接口。但是吧,还要维护一个前端项目,很烦人呢,所以我选择了Chainlit,如果你想快速给你的模型接入一个前端,你可以考虑一下Chainlit。

这篇文章我按“真正写项目”的顺序拆成 5 个部分,跟着走一遍,你可以从 0 到 1 跑出一个能用、能迭代、能上线的版本。

为了简单期间,大多数示例都是不接入大模型的,最后会介绍如何接入大模型,接入大模型是一件很简单的事情。总不能只有API KEY才能跑代码,是吧.

第 1 部分:3 分钟跑通最小 Demo

先别想太多,先把服务跑起来。

1) 安装

个人推荐使用uv管理Python项目依赖,避免污染全局Python, 所以后面的命令都是使用uv开头的命令。

2) 自检

这个命令会拉起一个官方示例页面,能打开就说明安装没问题。

3) 最小应用

新建 app.py

import chainlit as cl



@cl.on_message
async def main(message: cl.Message):
    """处理用户消息并返回最小响应。"""
    await cl.Message(content=f"收到你的消息了:{message.content}").send()

启动:

说明:

  • -w 会开启热更新,改代码后自动重载,开发体验会好很多。
  • 默认访问地址是 http://localhost:8000

一个对话机器人主要的就是对话,所以有个on_message很合理,是不! 就像一个http服务器,用户发送消息,服务器返回消息。只是入口只有一个,就是on_message

第 2 部分:搞清生命周期和会话管理

很多同学一开始把所有逻辑都塞进 on_message,短期能跑,后面就会乱。
正确姿势是把逻辑按生命周期拆开。

import chainlit as cl


# 窗口打开就给用户发条消息
# 一些资源的初始化可以放这里
@cl.on_chat_start
async def on_chat_start():
    """初始化会话状态,在用户建立新会话时触发。"""
    cl.user_session.set("history", [{"role": "system", "content": "你是一个简洁的中文助手。"}])
    await cl.Message(content="你好,我已经准备好了,你可以直接提问。").send()


# 回复就回复当前会话消息数
@cl.on_message
async def on_message(message: cl.Message):
    """接收用户消息并写入会话历史。"""
    history = cl.user_session.get("history") or []
    history.append({"role": "user", "content": message.content})
    cl.user_session.set("history", history)
    await cl.Message(content=f"当前会话消息数:{len(history)}").send()


# 收尾, 资源回收或日志记录可以放这里
@cl.on_chat_end
def on_chat_end():
    """会话结束时触发,用于资源回收或日志记录。"""
    print("聊天会话结束。")

这里重点有 2 个:

  • on_chat_start 做初始化,不要在每次消息都初始化。
  • cl.user_session 管当前用户会话状态,避免多用户数据串线。

第 3 部分:把体验做对(流式输出 + 交互)

能回消息只是起点,真正好用还得有“正在思考中”的流式体验。

下面给一个通用流式写法(不绑定某个厂商 SDK):

import asyncio
import chainlit as cl


async def fake_llm_stream(text: str):
    """模拟模型按 token 流式输出。"""
    for token in text:
        await asyncio.sleep(0.1)
        yield token + " "


@cl.on_message
async def stream_reply(message: cl.Message):
    """将模型输出以流式方式返回给前端。"""
    msg = cl.Message(content="")
    await msg.send()

    async for token in fake_llm_stream(f"你刚刚说的是:{message.content}"):
        await msg.stream_token(token)

    await msg.update()

这段代码的价值在于:

  • 用户不会“等一个黑屏大响应”,而是能即时看到输出。
  • 长回答场景下,体感速度会明显提升。没有哪家模型等结果全出来才生成,是不!

你后续还可以接入:

  • AskUser 类输入组件做参数收集。
  • Step 把中间推理过程展示出来,便于调试和可解释性展示。

第 4 部分:工程化配置与本地调试

当项目从 Demo 进入多人协作,配置和启动参数必须规范。

常用 CLI 参数

# 本地开发 自动检测代码是否变动
chainlit run app.py -w

# 指定监听端口和IP地址, 服务器运行(不自动打开浏览器)
chainlit run app.py --headless --host 0.0.0.0 --port 8000

# 子路径部署(如 https://example.com/chainlit)
# 如果你想不想放在网站的根路径的话
chainlit run app.py -h --root-path /chainlit

几个实践建议:

  • 容器部署一般要 --host 0.0.0.0, 不然从容器外映射端口是映射不上的哈!!!

配置还有ssl参数啥的,应该没人在这里配置ssl证书吧。

使用Caddy服务器的反向代理配置

# 假设你有一个Caddyfile,内容如下:
example.com {
    reverse_proxy  127.0.0.1:8000
}

第 5 部分:鉴权与上线部署(生产必看)

Chainlit 默认是公开应用。如果你要内网/企业场景,一定要做鉴权。

1) 开启鉴权基础配置

先设置环境变量:

export CHAINLIT_AUTH_SECRET="请替换成你自己的强随机字符串"

也可以用官方命令生成:

2) 增加认证回调(示例:密码模式)

import chainlit as cl


@cl.password_auth_callback
def auth_callback(username: str, password: str):
    """校验用户名密码,成功时返回用户对象。"""
    if username == "admin" and password == "123456":
        return cl.User(identifier="admin", metadata={"role": "administrator"})
    return None

上线时再补这几件事:

  • 负载均衡开启会话亲和(sticky session)。
  • 若跨域嵌入,配置 allow_origins
  • 若多实例部署,优先只走 WebSocket 传输并做好连接稳定性测试。

不存在的第 6 部分

接入langchain还是很简单的,不过需要注意开启langchain的流式输出时,设置正确的参数,参考代码如下


@cl.on_message
async def on_message(message: cl.Message) -> None:    
    model_key = message.modes.get("model") or DEFAULT_MODEL_KEY
    enable_web_search = message.modes.get("search") == "web"

    payload = {
        "question": message.content,
        "model_key": model_key,
        "enable_web_search": enable_web_search,
    }
    msg = cl.Message(content="")
    for chunk in graph.stream(
            payload,
            stream_mode="messages",
            version="v2",
            config=RunnableConfig(callbacks=[cl.LangchainCallbackHandler()])):

        message_chunk, _ = chunk["data"]
        if isinstance(message_chunk, AIMessage) and message_chunk.content:
            await msg.stream_token(message_chunk.content)

    await msg.send()

注意的点如下:

  1. 流模式下,需要设置 stream_mode="messages",不然不能逐字输出, 等结果在输出体验超级差。
  2. 流模式下,需要设置 version="v2",配合上面的参数
  3. 增加回调, 这样chainlit才能在输出中显示经过的步骤。

总结

虽然AI大大加快了写代码的速度,生成前端更不是问题,但是写一个前端和维护一个前端还是不一样的,如果后期不再维护或者修改,那么就直接生成吧,AI应该可以写的很漂亮,也可以自定义各种样式,抄各种显示效果。

但是吧,如果后期需要维护或者修改并且没有太多精力维护,那么就选择一个开源的产品吧,Chainlit实在太棒啦。


官方文档入口:

LangChain关于流式输出的说明: