ERNIE-4.5-0.3B-PT Chainlit前端定制指南:修改Logo、添加系统提示词、支持历史会话
你是不是也遇到过这样的情况:模型部署好了,Chainlit前端能跑起来,但一打开页面——默认的机器人图标太普通,对话没有专属开场白,每次刷新页面历史记录就消失?用着别扭,改又不知从哪下手?
这篇文章不讲大道理,不堆参数,就带你一步步完成三个最常被问到的前端定制需求:换掉默认Logo、加上专属系统提示词、让历史会话真正保留下来。所有操作都在Chainlit项目本地完成,无需动后端服务,也不需要重新部署vLLM,改完立刻生效。
我们用的是已部署好的【vLLM】ERNIE-4.5-0.3B-PT模型,前端基于Chainlit 1.2+版本(当前主流稳定版),所有步骤均在CSDN星图镜像环境实测通过,命令可直接复制粘贴运行。
1. 先确认你的环境已就绪
在动手改前端之前,得确保后端模型服务和Chainlit服务都正常运行。这不是多余步骤——很多“改了没效果”的问题,其实卡在了前置状态没确认清楚。
1.1 检查vLLM服务是否加载完成
打开WebShell,执行:
cat /root/workspace/llm.log如果看到类似这样的日志结尾,说明ERNIE-4.5-0.3B-PT模型已成功加载进vLLM推理引擎:
INFO 01-26 14:22:38 [model_runner.py:729] Loading model weights took 128.45s INFO 01-26 14:22:38 [engine.py:162] Started engine with config: model='ernie-4.5-0.3b-pt', tensor_parallel_size=1, dtype=bfloat16注意:如果日志里还停留在“Loading weights…”或出现
OSError: Unable to load weights,请先等待或检查模型路径。本文默认你已通过llm.log确认服务就绪。
1.2 确认Chainlit服务正在运行
在另一个终端或同一终端新开Tab,运行:
ps aux | grep chainlit你应该能看到类似这一行输出:
user 12345 0.1 3.2 1234567 89012 ? Sl Jan26 0:45 python -m chainlit run app.py -w这表示Chainlit正以开发模式(-w热重载)运行在app.py上。如果你用的是其他文件名(比如main.py),请把后续操作中的app.py替换成对应文件名。
2. 修改Logo:三步换掉默认机器人头像
Chainlit默认用一个蓝色机器人图标作为应用标识,但它既不能体现你的品牌,也不利于用户建立认知。好在替换它非常简单,不需要写一行JavaScript。
2.1 准备你的Logo图片
- 推荐尺寸:128×128像素(正方形,清晰即可)
- 格式:
png或jpg(推荐png,支持透明背景) - 命名:建议统一命名为
logo.png - 存放位置:放在Chainlit项目根目录下的
public/文件夹中如果项目里还没有
public/文件夹,请手动创建:mkdir -p public
执行命令快速完成:
# 进入项目根目录(假设你的app.py在此目录) cd /root/workspace/ # 创建public目录并进入 mkdir -p public && cd public # 示例:用curl下载一张简洁的PNG Logo(你可替换成自己的) curl -o logo.png https://csdn-665-inscode.s3.cn-north-1.jdcloud-oss.com/inscode/202601/anonymous/logo-ernie.png # 返回上层 cd ..2.2 在app.py中配置logo路径
打开你的Chainlit入口文件(通常是app.py),找到@cl.set_chat_profiles或@cl.on_chat_start附近的位置,在文件顶部或cl.init()调用前,添加如下配置:
import chainlit as cl # 👇 新增:设置自定义Logo(必须放在public/下) cl.config.ui.logo = "public/logo.png"小知识:Chainlit会自动将
public/下的资源映射为根路径/,所以"public/logo.png"实际访问地址是/logo.png,这是框架约定,不用额外配Web服务器。
2.3 验证效果
保存app.py,Chainlit会自动热重载(因用了-w参数)。刷新浏览器页面,左上角的蓝色机器人图标就会变成你上传的Logo。
成功标志:图标清晰显示,无404报错,控制台无Failed to load resource警告。
3. 添加系统提示词:让AI一开口就懂你的风格
默认情况下,Chainlit调用vLLM时只传用户输入,模型完全“裸奔”上阵——没有角色设定、没有格式要求、也没有上下文引导。结果就是回答风格飘忽、专业度不稳定。
我们通过Chainlit的@cl.step+cl.Message预置方式,在每次新会话开始时,悄悄塞一条“看不见”的系统消息给模型。ERNIE-4.5-0.3B-PT支持标准的system角色,这条消息会被vLLM正确识别并纳入上下文。
3.1 编写你的专属系统提示词
系统提示词不是越长越好,关键是精准、可执行、符合ERNIE特性。以下是为ERNIE-4.5-0.3B-PT优化的一段示例(你可按需修改):
你是一个专业、严谨且富有同理心的AI助手,由ERNIE-4.5-0.3B-PT模型驱动。请始终: - 使用中文回答,语句通顺,避免生硬翻译腔; - 对技术问题给出准确解释,对创意请求提供具体建议; - 若用户提问模糊,主动追问1个关键细节,不自行猜测; - 回答末尾不加总结性语句(如“综上所述”),保持简洁有力。提示:这段文字将作为
system消息发送,不会显示在聊天界面上,但会显著影响模型输出质量。
3.2 在代码中注入系统消息
打开app.py,找到@cl.on_chat_start装饰器函数(这是每次新会话启动时执行的钩子),在函数内部第一行,添加如下代码:
@cl.on_chat_start async def on_chat_start(): # 👇 新增:预设系统提示词(仅发送给模型,用户不可见) await cl.Message( content="你是一个专业、严谨且富有同理心的AI助手,由ERNIE-4.5-0.3B-PT模型驱动。请始终:\n- 使用中文回答,语句通顺,避免生硬翻译腔;\n- 对技术问题给出准确解释,对创意请求提供具体建议;\n- 若用户提问模糊,主动追问1个关键细节,不自行猜测;\n- 回答末尾不加总结性语句(如“综上所述”),保持简洁有力。", role="system", author="System", disable_feedback=True, language="zh" ).send()关键参数说明:
role="system":告诉vLLM这是系统指令,非用户输入disable_feedback=True:隐藏该消息的点赞/点踩按钮,避免干扰language="zh":显式声明语言,提升ERNIE对中文语境的理解稳定性
3.3 测试系统提示词是否生效
重启Chainlit(或等热重载完成),新建一个会话,输入:
帮我写一段Python代码,读取CSV文件并统计每列缺失值数量。对比修改前后的回答:
- 修改前:可能直接甩代码,缺少注释或使用说明;
- 修改后:代码带清晰注释,开头会说明“我将使用pandas完成此任务”,结尾不加总结,整体更沉稳专业。
成功标志:回答风格更统一、技术细节更扎实、交互更自然。
4. 支持历史会话:告别“刷一下就丢”的尴尬
Chainlit默认每次刷新页面,聊天记录就清空。这对调试友好,但对真实使用很不友好。我们要让它像微信一样——关掉页面再打开,上次聊到哪,接着聊。
核心思路:把会话历史存在本地浏览器(localStorage)里,每次加载时自动恢复。不依赖后端数据库,轻量、可靠、零运维。
4.1 创建会话历史管理工具类
在项目根目录下新建一个文件:utils.py,内容如下:
# utils.py import json import chainlit as cl class ChatHistory: @staticmethod def save(messages): """保存消息列表到localStorage""" try: # Chainlit 1.2+ 支持直接存JSON到local storage cl.user_session.set("chat_history", json.dumps(messages, ensure_ascii=False)) except Exception as e: print(f"[WARN] 保存历史失败: {e}") @staticmethod def load(): """从localStorage加载消息列表""" try: history_json = cl.user_session.get("chat_history") if history_json: return json.loads(history_json) except Exception as e: print(f"[WARN] 加载历史失败: {e}") return [] @staticmethod def clear(): """清空历史""" cl.user_session.set("chat_history", "")然后在app.py顶部导入:
from utils import ChatHistory4.2 修改on_chat_start,自动恢复历史
继续编辑app.py中的@cl.on_chat_start函数,改成这样:
@cl.on_chat_start async def on_chat_start(): # 恢复历史消息(如果有) messages = ChatHistory.load() if messages: for msg in messages: await cl.Message( content=msg["content"], author=msg["author"], role=msg["role"] ).send() # 发送系统提示词(保持原有逻辑) await cl.Message( content="你是一个专业、严谨且富有同理心的AI助手,由ERNIE-4.5-0.3B-PT模型驱动。请始终:\n- 使用中文回答,语句通顺,避免生硬翻译腔;\n- 对技术问题给出准确解释,对创意请求提供具体建议;\n- 若用户提问模糊,主动追问1个关键细节,不自行猜测;\n- 回答末尾不加总结性语句(如“综上所述”),保持简洁有力。", role="system", author="System", disable_feedback=True, language="zh" ).send()4.3 在消息发送后自动保存历史
找到@cl.on_message函数(处理用户输入的地方),在await cl.Message(...).send()之后,添加保存逻辑:
@cl.on_message async def on_message(message: cl.Message): # 保存用户消息 user_msg = { "content": message.content, "author": "User", "role": "user" } # 调用vLLM获取回复(此处省略具体调用代码,保持你原有逻辑) # response = await call_vllm_api(message.content) # 保存AI回复(示例) ai_msg = { "content": "这是ERNIE-4.5-0.3B-PT的回复示例。", "author": "ERNIE", "role": "assistant" } # 👇 新增:保存本轮完整对话 history = ChatHistory.load() history.append(user_msg) history.append(ai_msg) ChatHistory.save(history) # 发送AI回复 await cl.Message(content=ai_msg["content"], author="ERNIE").send()注意:你原有的vLLM调用逻辑(比如用
httpx请求http://localhost:8000/v1/chat/completions)应放在# 调用vLLM获取回复注释位置,不要删掉。
4.4 验证历史会话功能
- 步骤1:打开Chat界面,发2–3条消息;
- 步骤2:按
Ctrl+R或点击浏览器刷新按钮; - 步骤3:观察——所有历史消息是否完整重现?
- 步骤4:再发一条新消息,检查是否追加到历史末尾?
成功标志:刷新不丢记录、新消息自动续接、控制台无localStorage相关报错。
5. 进阶小技巧:让定制更顺手
上面三步已覆盖90%的日常需求。这里再给你几个“锦上添花”的实用技巧,不强制,但用了真香。
5.1 快速切换不同系统提示词(多场景支持)
如果你要同时支持“技术问答”“创意写作”“客服应答”等多种模式,可以加一个下拉菜单:
# 在 @cl.on_chat_start 中添加 settings = await cl.ChatSettings( [ cl.Select( id="system_prompt", label="AI角色模式", values=["技术专家", "创意伙伴", "客服助手"], initial_index=0 ) ] ).send() # 然后根据选择动态生成system消息 prompt_map = { "技术专家": "你是一名资深工程师,专注Python、AI和系统设计...", "创意伙伴": "你是一位充满灵感的创意策划,擅长文案、故事和视觉联想...", "客服助手": "你是一家科技公司的智能客服,语气亲切、响应及时、解答准确..." } selected = settings["system_prompt"] await cl.Message(content=prompt_map[selected], role="system", ...).send()5.2 给Logo加点击跳转(增强品牌露出)
想让用户点Logo就跳转到官网?只需在app.py中加一句:
cl.config.ui.theme = cl.Theme( logo="public/logo.png", # 👇 新增:点击Logo跳转 logo_link="https://your-company-website.com" )5.3 限制历史长度,防止localStorage爆满
长期使用后,localStorage可能积累大量消息。加个自动清理逻辑:
# 在 ChatHistory.save() 方法末尾添加 if len(messages) > 50: # 最多保留50条消息(约25轮对话) messages = messages[-50:]6. 总结:你已经掌握的三项关键能力
我们从一个“能跑起来但不好用”的Chainlit前端出发,完成了三次精准改造:
- 换Logo:不是换个图片那么简单,而是理解了Chainlit的
public/资源映射机制,从此你的AI应用有了专属门面; - 加系统提示词:没碰vLLM配置,却让ERNIE-4.5-0.3B-PT的回答风格更可控、更专业,靠的是Chainlit对
role="system"的原生支持; - 保历史会话:不搭数据库、不写API,仅用20行Python+浏览器localStorage,就实现了接近App级的会话连续性。
这三件事都不复杂,但组合起来,就让一个技术Demo变成了真正可用的产品级界面。你不需要成为全栈工程师,只需要知道“哪里改、怎么改、为什么这么改”。
下一步,你可以尝试:
→ 把系统提示词存成配置文件,方便多人协作维护;
→ 为历史消息加时间戳和会话分组;
→ 用Chainlit的@cl.author_rename给AI起个更亲切的名字。
真正的定制,从来不是堆砌功能,而是让每个细节都服务于人的体验。
获取更多AI镜像
想探索更多AI镜像和应用场景?访问 CSDN星图镜像广场,提供丰富的预置镜像,覆盖大模型推理、图像生成、视频生成、模型微调等多个领域,支持一键部署。