基于NiceGUI的Gemini流式聊天机器人重复处理历史消息问题
解决Gemini-Pro流式聊天重复处理历史消息的问题
核心问题分析
- 每次刷新
chat_messages组件时,会遍历所有历史消息,对每条标记为"Bot"的消息重新调用Gemini-Pro生成回复,导致重复处理历史提问 send函数逻辑错误,直接将用户消息作为Bot消息加入列表,没有正确触发单次回复生成流程
修复方案及代码修改
以下是修正后的核心代码:
import asyncio from typing import List, Tuple import vertexai from vertexai.generative_models import GenerativeModel, ChatSession from nicegui import ui, context PROJECT_ID = "你的项目ID" LOCATION = "你的区域" vertexai.init(project=PROJECT_ID, location=LOCATION) model = GenerativeModel("gemini-pro") chat = model.start_chat() async def get_async_chat_response(chat: ChatSession, prompt: str): response = await chat.send_message_async(prompt, stream=True) async for chunk in response: if chunk.text: yield chunk.text messages: List[Tuple[str, str]] = [] pending_prompt: str | None = None @ui.refreshable async def chat_messages() -> None: # 渲染所有已完成的消息 for name, text in messages: avatar = "👤" if name == 'You' else "🤖" # 替换为你的头像资源 ui.chat_message(avatar=avatar, name=name, text=text, sent=name == 'You') # 处理当前待回复的请求 if pending_prompt: spinner = ui.spinner(size='3rem').classes('self-center') # 生成流式回复 bot_response = "" response_label = ui.label().classes('max-w-full') async for chunk in get_async_chat_response(chat, pending_prompt): bot_response += chunk response_label.text = bot_response await asyncio.sleep(0.01) # 确保UI实时更新 spinner.delete() # 将完成的回复加入消息列表,清除待处理状态 messages.append(('Bot', bot_response)) global pending_prompt pending_prompt = None chat_messages.refresh() # 滚动到底部 if context.get_client().has_socket_connection: ui.run_javascript('window.scrollTo(0, document.body.scrollHeight)') ui.run_javascript('history.scrollRestoration = "manual"') async def send() -> None: global pending_prompt message = text.value.strip() if not message or pending_prompt: return # 避免重复发送空消息或重复请求 # 添加用户消息到列表 messages.append(('You', message)) text.value = '' # 设置待处理的提问,触发组件刷新 pending_prompt = message chat_messages.refresh() # 构建UI(假设tabs和chat_tab已定义) with ui.tab_panels(tabs, value=chat_tab).classes('w-full max-w-2xl mx-auto flex-grow items-stretch'): with ui.tab_panel(chat_tab).classes('items-stretch'): chat_messages() with ui.footer().classes('bg-white'): with ui.row().classes('w-full max-w-2xl mx-auto items-center'): text = ui.input(placeholder='输入消息...').props('rounded outlined input-class=mx-3').classes('flex-grow') ui.button('发送', on_click=send).props('rounded') ui.run(title='Gemini-Pro 流式聊天机器人')
关键修改说明
- 新增
pending_prompt变量:仅存储当前待处理的用户提问,避免重复触发模型调用 - 拆分渲染与生成逻辑:
chat_messages先渲染所有已完成的历史消息,再单独处理当前待回复的请求,流式生成并实时更新UI - 修正
send函数:仅负责提交用户消息、标记待处理状态,不直接操作Bot消息列表,由组件自动处理回复生成和追加 - 移除历史消息重复生成:不再遍历所有Bot消息调用模型,仅处理当前pending的提问
内容的提问来源于stack exchange,提问作者gibbz00
相关产品推荐
相关产品推荐

