Type something to search...
构建具有图像字幕和可视化问答功能的聊天应用程序

构建具有图像字幕和可视化问答功能的聊天应用程序

学习如何使用 Chainlit 创建互动聊天用户界面

在我之前的文章中,我向您介绍了 Chainlit,这个开源的 Python 库,使得创建基于聊天的用户界面变得简单:

在那篇文章中,我涵盖了聊天应用的基本结构,并演示了如何处理文本和文件输入,特别是图像。在这篇文章中,我将基于这个基础,深入探讨 Chainlit。这一次,我们将创建一个完全功能的聊天应用程序,使您能够:

  • 与大型语言模型(LLM)进行对话并提出问题。
  • 上传一张图片并为其生成描述性标题。
  • 上传一张图片并提出与其内容相关的问题。

让我们填补空白,让这个聊天应用程序变得生动起来!

构建应用程序

作为提醒,这里是我们应用程序的文件夹结构。ChainlitDemo.py 文件位于 chainlitapp 文件夹内:

chainlitapp
     |___ChainlitDemo.py

让我们开始构建应用程序的主要框架。首先将 ChainlitDemo.py 文件填充以下代码:

import chainlit as cl

@cl.on_message
async def main(message: cl.Message):
    # if the message contains attachments
    if message.elements:
        for element in message.elements:
            if element.type == "image":    # if the attachement in an image                
                await cl.Message(
                    content=f"You sent an image and asked: '{message.content}'",                    
                ).send()
    else:
        await cl.Message(
            content=f"You said: {message.content}",
        ).send()

要运行应用程序,请在终端中输入以下命令:

$ chainlit run ChainlitDemo.py -w

使用这个基础应用程序,您可以输入一条消息:

消息将会被回显给您:

您还可以附加一张图片并输入一些文本:

然后图片将被上传到应用程序。同时,您输入的文本将被回显给您:

与 llama3.2 聊天

现在基础应用程序已经设置好,让我们开始实现第一个功能:与大型语言模型(LLM)聊天。为此,我将使用 Ollama。我假设您已经安装了 Ollama,并且正在运行 llama3.2 模型。

如果您需要关于 Ollama 的复习,请查看我之前的两篇文章:

将以下代码片段添加到 ChainlitDemo.py 文件中:

import chainlit as cl
import requests

## =======================================================================
## 初始化对话历史
conversation_history = []

@cl.on_chat_start
async def handle_new_chat():
    """
    当新聊天开始时触发此函数。
    使用它来重置对话状态或初始化变量。
    """
    global conversation_history
    # 清除新聊天的对话历史
    conversation_history = []
    # 向用户发送欢迎消息
    await cl.Message(content="你好!今天我能为您提供什么帮助?").send()

def chat(message):
    url = "http://localhost:11434/api/generate"
    model = "llama3.2"  
    headers = {
        "Content-Type": "application/json",
    }

    # 将用户消息添加到对话历史中
    conversation_history.append(
        {
            "role": "User", 
            "content": message
        })
    
    # 用对话历史格式化提示
    formatted_prompt = ""
    for turn in conversation_history:
        formatted_prompt += f"{turn['role']}: {turn['content']}\n"
       
    data = {
        "model": model,
        "prompt": formatted_prompt.strip(),
        "stream": False
    }
    response = requests.post(url, json = data, headers = headers)
    
    # 将助手的响应添加到对话历史中
    conversation_history.append(
        {
            "role": "Assistant", 
            "content": response.json()["response"]
        })    
    return response.json()["response"]
## =======================================================================

@cl.on_message
async def main(message: cl.Message):
    # 如果消息包含附件
    if message.elements:
        for element in message.elements:
            if element.type == "image":            # 如果附件是图片                
                await cl.Message(
                    content=f"您发送了一张图片并询问:'{message.content}'",                    
                ).send()
    else:
        await cl.Message( 
            # =================================
            content=f"{chat(message.content)}",
            # =================================
        ).send()

在上述代码片段中,我们添加了以下内容:

  • conversation_history 变量是一个列表,用于存储用户与模型之间的对话历史。这是至关重要的,以便模型能够在对话之间保持上下文。
  • handle_new_chat() 函数在用户想要创建新对话时被调用。这是清除 conversation_history 变量的地方,以便删除先前的对话。
  • chat() 函数接收来自用户的消息并将其发送到 LLM,在本例中是通过 Ollama 的 REST 端点 (http://localhost:11434/api/generate) 暴露的 llama3.2。请注意,用户输入的所有消息和来自 LLM 的响应都被添加到 conversation_history 列表中。
  • main() 函数接收到用户的文本输入时,它调用 chat() 函数并将响应返回给用户:
    else:
        await cl.Message(            
            content=f"{chat(message.content)}",
        ).send()

让我们试试。首先,让我们请 LLM 给我们讲个笑话:

果然,笑话送到了:

既然它问您是否想听一个笑话,那就让我们回应:“当然,再来一个!”。得益于保存的对话历史,LLM 现在可以理解您回复的上下文并无缝地继续:

要创建新对话,请点击屏幕左上角的图标:

当您点击 确认 时,屏幕会被清除,conversation_history 变量会被重置,所有先前的上下文都会被擦除:

请继续提问!然后,跟进一个相关的问题,以测试 LLM 是否能够保持对话的上下文。这将有助于验证其有效处理多轮对话的能力。

图像标题生成

我们即将实现的下一个功能是 图像标题生成。为此,我们将使用 Salesforce/blip-image-captioning-base 模型,我在之前关于多模态模型的文章中已经介绍过:

将以下代码片段添加到 ChainlitDemo.py 文件中:

import chainlit as cl

## ==================================================================
## Image captioning
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image

## Load the BLIP model and processor
model_name_caption = "Salesforce/blip-image-captioning-base"
processor_caption = BlipProcessor.from_pretrained(model_name_caption)
model_caption = BlipForConditionalGeneration.from_pretrained(model_name_caption)

def caption_image(image):
    # Prepare the image for the model
    inputs = processor_caption(image, return_tensors="pt")

    # Generate the caption
    caption_ids = model_caption.generate(**inputs)
    caption = processor_caption.decode(caption_ids[0], skip_special_tokens=True)
    return caption
## ==================================================================

import requests

## Initialize conversation history
conversation_history = []

@cl.on_chat_start
async def handle_new_chat():
   ...
   ...

def chat(message):
   ...
   ...

@cl.on_message
async def main(message: cl.Message):
    # if the message contains attachments
    if message.elements:
        for element in message.elements:
            if element.type == "image":  # if the attachement in an image                
                # ====================================================
                # Image captioning
                # send back the image caption
                caption = caption_image(Image.open(str(element.path)))
                await cl.Message(
                    content=f"Caption: {caption}",
                ).send()
                # ====================================================
    else:
        await cl.Message(            
            content=f"{chat(message.content)}",
        ).send()

在您添加的上述代码片段中,您:

  • 加载了 Salesforce/blip-image-captioning-base 模型,以帮助您执行图像标题生成。
  • 定义了一个名为 caption_image() 的函数。该函数将用户上传的图像传递给模型,并获取其生成的标题。
  • 将标题发送回用户。

现在让我们试一试。对于这个例子,我将附上以下包含一排校车的图像:

一旦图像附加完成,输入一些文本并按回车:

Salesforce/blip-image-captioning-base 模型现在将获取图像并生成标题,然后将其返回给用户,如下所示:

这不是很有趣吗?尝试各种图像,检查标题是否准确。

视觉问答

接下来我们将实现的功能是 视觉问答 (VQA)。为此,我们将使用 Salesforce/blip-vqa-base 模型。将以下代码片段添加到 ChainlitDemo.py 文件中:

import chainlit as cl
from transformers import BlipProcessor, BlipForConditionalGeneration
from PIL import Image

## Load the BLIP model and processor
model_name_caption = "Salesforce/blip-image-captioning-base"
processor_caption = BlipProcessor.from_pretrained(model_name_caption)
model_caption = BlipForConditionalGeneration.from_pretrained(model_name_caption)

def caption_image(image):
  ...
  ...

## ==================================================================
## VQA
import torch
from PIL import Image
from transformers import BlipProcessor, BlipForQuestionAnswering

## Load the pre-trained BLIP model and processor for VQA
model_name_vqa = "Salesforce/blip-vqa-base"
processor_vqa = BlipProcessor.from_pretrained(model_name_vqa)
model_vqa = BlipForQuestionAnswering.from_pretrained(model_name_vqa)

def visual_qa(image, question):
    inputs = processor_vqa(image, question, return_tensors="pt")
    out = model_vqa.generate(**inputs)
    answer = processor_vqa.decode(out[0], skip_special_tokens=True)
    return answer
## ==================================================================

import requests

## Initialize conversation history
conversation_history = []

@cl.on_chat_start
async def handle_new_chat():
  ...
  ...

def chat(message):
  ...
  ...

@cl.on_message
async def main(message: cl.Message):
    # if the message contains attachments
    if message.elements:
        for element in message.elements:
            if element.type == "image":  # if the attachement in an image  
                # ==========================================================
                # VQA
                # send back the image caption and the answer to the question
                caption = caption_image(Image.open(str(element.path)))
                answer = visual_qa(Image.open(str(element.path)), message.content)
                await cl.Message(
                    content=f"Caption: {caption},\n Answer: {answer}",                    
                ).send()
                # ==========================================================
    else:
        await cl.Message(            
            content=f"{chat(message.content)}",
        ).send()

在您添加的上述代码片段中,您:

  • 加载了 Salesforce/blip-vqa-base 模型。
  • 定义了一个名为 visual_qa() 的函数。该函数接受用户上传的图像,通过模型处理,并生成对用户问题的回答。
  • 将标题和答案发送回用户。

让我们试试,看看它是如何工作的。使用同一张校车的图像,将图像附加到聊天中并问以下问题:“天空的颜色是什么?”。按下回车:

这次,标题和问题的答案都返回给您:

而且答案是准确的!让我们试试另一张图片:

这次,它能够检测到图像中的三个女孩:

摘要

我希望这篇文章能让你清楚地理解使用 Chainlit 构建聊天应用程序是多么简单。Chainlit 简化了这个过程,让你可以专注于开发应用程序的核心逻辑,而不必担心用户界面。你可以创建的应用程序类型几乎是无穷无尽的!例如,你可以扩展这个应用程序:

  1. 连接到 LLM 进行 OCR 操作:例如,你可以提交汽车牌照的图片,并自动提取牌照号码。
  2. 连接到 LLM 进行图像分割:你可以使用该应用程序从图像中去除背景,精确地孤立出感兴趣的对象。
  3. 创建互动教育工具:构建能够解释复杂图表的应用程序,解决手写笔记中的数学问题,或提供科学图像的详细描述。

使用 Chainlit,唯一的限制就是你的想象力。通过利用其直观的框架,你可以快速原型设计并部署强大、互动的应用程序,结合 LLM 和多模态 AI 的优势。祝你构建愉快!

Related Posts

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

结合chatgpt-o3-mini与perplexity Deep Research的3步提示:提升论文写作质量的终极指南

AI 研究报告和论文写作 合并两个系统指令以获得两个模型的最佳效果 Perplexity AI 的 Deep Research 工具提供专家级的研究报告,而 OpenAI 的 ChatGPT-o3-mini-high 擅长推理。我发现你可以将它们结合起来生成令人难以置信的论文,这些论文比任何一个模型单独撰写的都要好。你只需要将这个一次性提示复制到 **

阅读更多
让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

让 Excel 过时的 10 种 Ai 工具:实现数据分析自动化,节省手工作业时间

Non members click here作为一名软件开发人员,多年来的一个发现总是让我感到惊讶,那就是人们还在 Excel

阅读更多
使用 ChatGPT 搜索网络功能的 10 种创意方法

使用 ChatGPT 搜索网络功能的 10 种创意方法

例如,提示和输出 你知道可以使用 ChatGPT 的“搜索网络”功能来完成许多任务,而不仅仅是基本的网络搜索吗? 对于那些不知道的人,ChatGPT 新的“搜索网络”功能提供实时信息。 截至撰写此帖时,该功能仅对使用 ChatGPT 4o 和 4o-mini 的付费会员开放。 ![](https://images.weserv.nl/?url=https://cdn-im

阅读更多
掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

掌握Ai代理:解密Google革命性白皮书的10个关键问题解答

10 个常见问题解答 本文是我推出的一个名为“10 个常见问题解答”的新系列的一部分。在本系列中,我旨在通过回答关于该主题的十个最常见问题来分解复杂的概念。我的目标是使用简单的语言和相关的类比,使这些想法易于理解。 图片来自 [Solen Feyissa](https://unsplash.com/@solenfeyissa?utm_source=medium&utm_medi

阅读更多
在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和技术领域保持领先地位的 10 项必学技能 📚

在人工智能和科技这样一个动态的行业中,保持领先意味着不断提升你的技能。无论你是希望深入了解人工智能模型性能、掌握数据分析,还是希望通过人工智能转变传统领域如法律,这些课程都是你成功的捷径。以下是一个精心策划的高价值课程列表,可以助力你的职业发展,并让你始终处于创新的前沿。 1. 生成性人工智能简介课程: [生成性人工智能简介](https://genai.works

阅读更多
揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

揭开真相!深度探悉DeepSeek AI的十大误区,您被误导了吗?

在AI军备竞赛中分辨事实与虚构 DeepSeek AI真的是它所宣传的游戏规则改变者,还是仅仅聪明的营销和战略炒作?👀 虽然一些人将其视为AI效率的革命性飞跃,但另一些人则认为它的成功建立在借用(甚至窃取的)创新和可疑的做法之上。传言称,DeepSeek的首席执行官在疫情期间像囤积卫生纸一样囤积Nvidia芯片——这只是冰山一角。 从其声称的550万美元培训预算到使用Open

阅读更多
Type something to search...