入门 📋 6 个步骤 第 592 / 593 篇

用 Chainlit 给 Python 智能体套一个生产级聊天界面(五分钟起)

写好了 Agent 逻辑,却卡在「怎么让它有个像样的聊天界面」?Chainlit 是专门给 LLM 应用做的 Python 框架,几行代码就能起一个带消息流、工具步骤、文件上传和记忆的网页。本教程六步落地,附本地运行与分享。

2026.11.03· 17 分钟阅读· 约 1528 字· 💬 Chainlit / 🐍 Python

你费劲写好了一个能调用工具、会查资料的 Python 智能体,结果只能在终端里一行行敲命令,发给同事还得教他装环境——这体验太劝退。Chainlit 就是来解决这个问题的:它用纯 Python 给你生成一套网页聊天界面,消息流、打字效果、工具调用步骤、文件上传、多轮记忆全都有,而且不需要写一行前端。

🧩 本教程适合:已经会用 Python 调大模型(哪怕只是 openai 库),想要一个能给别人演示、能本地跑的 Agent 界面的开发者/学生。不需要任何前端基础。

先搞懂:Chainlit 在 Agent 链路里站在哪一层?

一张图看懂分工:你的智能体逻辑(调模型、调工具)是「大脑」,Chainlit 是「脸面」。它不管你怎么实现智能体,只负责把用户的消息接进来、把你的回复和中间步骤展示出去。

组件作用本教程是否涉及
大模型客户端真正生成回答✅ OpenAI / 任意兼容客户端
你的 Agent 逻辑组提示词、调工具✅ 写在 app.py 里
Chainlit网页界面与交互✅ 主角

定位边界:Chainlit 不是另一个 Agent 框架,它不替你做编排。你完全可以用 LangChain、OpenAI Agents SDK 甚至手写循环,只要把结果交给 Chainlit 展示就行。本文用最朴素的 openai 调用,把重点放在界面本身。

Step 1:安装并跑起第一个 Chainlit 应用

1 装包,写出能回声的最小应用

新建一个项目目录,装好 chainlit,再写一个能原样回消息的 app.py。这是验证环境的最小闭环。

pip install chainlit openai python-dotenv

# app.py
import chainlit as cl

@cl.on_message
async def main(message: cl.Message):
    # 先把用户说的话原样发回去,确认界面能跑
    await cl.Message(content=message.content).send()

在项目目录里启动(加 -w 会自动打开浏览器):

chainlit run app.py -w
💡 看到本地地址(默认 http://localhost:8000)并能收发消息,就说明装好了。界面里还能看到每次消息的耗时和 token 用量,很适合演示。

Step 2:接一个大模型,让 Agent 能真正回答

2 把回声换成模型调用

把 main 里的回显换成一次大模型调用。这里用 OpenAI 兼容接口,换成任意厂商都可以。

import os
from dotenv import load_dotenv
import chainlit as cl
from openai import OpenAI

load_dotenv()
client = OpenAI()

@cl.on_message
async def main(message: cl.Message):
    r = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": message.content}],
    )
    answer = r.choices[0].message.content
    await cl.Message(content=answer).send()

报错了? 多半是没设 OPENAI_API_KEY 环境变量,或网络访问 API 被墙。把密钥写进 .env(OPENAI_API_KEY=sk-xxx),国内访问官方 API 通常需要代理。换个能用的模型端点也是常规操作。

Step 3:用 @cl.step 把工具调用变成可见的步骤

3 让中间过程「看得见」

真实 Agent 常要先查资料再回答。用 @cl.step 装饰一个函数,界面就会把它显示成一条独立的步骤,调试和演示都更清楚。

@cl.step(type="tool")
def search_knowledge(q: str) -> str:
    # 这里接你自己的检索 / 工具,返回一段文本
    return "(示例)在资料库中找到:Chainlit 用 @cl.on_message 接收消息。"

@cl.on_message
async def main(message: cl.Message):
    snippet = search_knowledge(message.content)
    r = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user",
                   "content": snippet + "\n\n问题:" + message.content}],
    )
    await cl.Message(content=r.choices[0].message.content).send()
🔑 技巧:把慢操作(检索、联网、读文件)都包成 step,前端会显示「运行中」和耗时,用户等待时不焦虑,你也更容易定位是哪一环慢。

Step 4:用 cl.user_session 记住对话历史(记忆)

4 让 Agent 记得上文

默认每次消息都是独立会话。用 user_session 把历史存起来,下次消息带着上下文一起发,Agent 才像在「连续对话」。

@cl.on_message
async def main(message: cl.Message):
    history = cl.user_session.get("history", [])
    history.append({"role": "user", "content": message.content})

    r = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=history,
    )
    reply = r.choices[0].message.content
    history.append({"role": "assistant", "content": reply})
    cl.user_session.set("history", history)

    await cl.Message(content=reply).send()

别忘了截断:history 会越攒越长,最终超出模型上下文。生产环境记得只保留最近 N 轮,或做摘要压缩。本文演示用,先不处理。

Step 5:加文件上传,让 Agent 读你给的文档

5 用户在界面里传文件,Agent 直接读

Chainlit 原生支持文件上传。用户在聊天框传文件后,message.elements 里就能拿到本地路径,读出来再喂给模型。

@cl.on_message
async def main(message: cl.Message):
    text = message.content
    for f in (message.elements or []):
        with open(f.path, "r", encoding="utf-8", errors="ignore") as fh:
            text = text + "\n\n文档内容:\n" + fh.read()[:4000]

    r = client.chat.completions.create(
        model="gpt-4o-mini",
        messages=[{"role": "user", "content": text}],
    )
    await cl.Message(content=r.choices[0].message.content).send()
🎉 到这里,你已经有一个能上传文档、能记忆、能展示步骤的 Agent 界面了。把 search_knowledge 换成真正的检索、把读文件换成 RAG,就是一个可用的知识助手雏形。

Step 6:本地运行与分享

6 本地跑、上云部署、内网自用三种方式

演示用本地即可;要给别人用,有两条路:Chainlit 官方云(一键部署,但内容会公开)或自托管(放你自己的服务器,数据不出去)。

# 方式一:本地开发
chainlit run app.py -w

# 方式二:部署到 Chainlit Cloud(需先 chainlit login)
chainlit deploy

# 方式三:自托管(放内网 / 自己的服务器)
#   用 chainlit run app.py 起服务,
#   前面套一层 Nginx 或反向代理并加鉴权

安全红线:chainlit deploy 会把应用公开到官方云,不要放含密钥或隐私的演示。对内网自用,务必在反向代理层加登录或 IP 白名单,别把没鉴权的聊天界面直接暴露到公网。

常见问题速查

现象原因 与 解决
chainlit 命令不存在没装包或装到了别的 Python 环境,确认 pip 和运行的 python 是同一个
界面打不开 localhost:8000端口被占,用 chainlit run app.py -p 8001 换端口
模型调用报错检查 OPENAI_API_KEY 与网络,或换成可用的模型端点
上传文件读不到确认用 message.elements 且文件类型在允许列表,路径用 f.path
← 返回教程中心