Computer Vision - Đôi mắt cho Jarvis (Xử lý hình ảnh với GPT-4o)

AI Hunter

Member
Jarvis của chúng ta đã biết nghe (Whisper), biết nói (TTS), biết suy nghĩ (LangGraph). Nhưng nó vẫn còn một điểm yếu chí mạng: Nó bị mù.

Bạn gửi cho nó tấm ảnh cái tủ lạnh và hỏi: "Gợi ý món ăn từ những thứ trong này", nó sẽ chịu chết.
Hôm nay, chúng ta sẽ mở khóa khả năng Vision (Thị giác máy tính), biến Jarvis thành một trợ lý AI toàn năng (Multi-modal).

Computer Vision - Đôi mắt cho Jarvis (Xử lý hình ảnh với GPT-4o).jpg

1. Cơ chế hoạt động​


Các mô hình ngôn ngữ lớn đời mới (như GPT-4o, Claude 3.5 Sonnet, Gemini 1.5 Pro) đều là Multi-modal. Tức là chúng không chỉ hiểu text mà còn hiểu cả pixel ảnh.

Quy trình xử lý ảnh như sau:
  1. Frontend (Chainlit): User upload ảnh -> Chuyển ảnh thành chuỗi mã hóa Base64.
  2. Backend (FastAPI): Nhận chuỗi Base64 -> Đóng gói vào Prompt gửi cho OpenAI.
  3. AI Model: "Nhìn" ảnh và trả lời câu hỏi liên quan.

2. Bước 1: Nâng cấp Backend (FastAPI)​


Mở file server.py (đã tạo ở bài 18). Chúng ta cần sửa lại cấu trúc nhận tin nhắn để chấp nhận cả hình ảnh.

Python:
import base64
from fastapi import FastAPI, HTTPException
from pydantic import BaseModel
from openai import OpenAI
from typing import Optional

app = FastAPI()
client = OpenAI(api_key="sk-proj-xxxx")

# 1. Cập nhật Model đầu vào: Thêm trường 'image_base64'
class ChatRequest(BaseModel):
    user_id: str
    message: str
    image_base64: Optional[str] = None # Ảnh là tùy chọn (có thể None)

class ChatResponse(BaseModel):
    answer: str

@app.post("/chat", response_model=ChatResponse)
async def chat_endpoint(req: ChatRequest):
    try:
        # Chuẩn bị tin nhắn gửi cho GPT-4o
        user_content = [{"type": "text", "text": req.message}]

        # Nếu có ảnh, nhét thêm vào payload
        if req.image_base64:
            print("📸 Phát hiện hình ảnh! Đang xử lý...")
            user_content.append({
                "type": "image_url",
                "image_url": {
                    "url": f"data:image/jpeg;base64,{req.image_base64}"
                }
            })

        # Gọi OpenAI GPT-4o
        response = client.chat.completions.create(
            model="gpt-4o", # Model này nhìn ảnh cực chuẩn
            messages=[
                {"role": "system", "content": "Bạn là Jarvis. Bạn có khả năng nhìn và phân tích hình ảnh."},
                {"role": "user", "content": user_content}
            ],
            max_tokens=1000
        )
       
        return ChatResponse(answer=response.choices[0].message.content)

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

3. Bước 2: Nâng cấp Frontend (Chainlit)​


Mở file app.py. Chainlit xử lý việc upload file cực kỳ đơn giản.

Python:
import chainlit as cl
import requests
import base64

API_URL = "http://localhost:8000/chat"

# Hàm phụ trợ: Chuyển file ảnh sang Base64
def encode_image(image_path):
    with open(image_path, "rb") as image_file:
        return base64.b64encode(image_file.read()).decode('utf-8')

@cl.on_chat_start
async def start():
    await cl.Message(content="Jarvis Vision Online! Gửi ảnh cho tôi xem nào 📸").send()

@cl.on_message
async def main(message: cl.Message):
    image_base64 = None
   
    # Kiểm tra xem user có đính kèm ảnh không?
    if message.elements:
        for element in message.elements:
            # Chỉ xử lý nếu là ảnh (jpg, png...)
            if "image" in element.mime:
                # Đọc ảnh và chuyển sang Base64
                image_base64 = encode_image(element.path)
               
                # Báo cho user biết đã nhận ảnh
                await cl.Message(content=f"Đã nhận diện ảnh: {element.name}").send()
   
    # Gửi sang Backend
    payload = {
        "user_id": "user_vision",
        "message": message.content,
        "image_base64": image_base64
    }

    msg = cl.Message(content="")
    await msg.send()

    try:
        response = requests.post(API_URL, json=payload)
        if response.status_code == 200:
            data = response.json()
            msg.content = data["answer"]
            await msg.update()
        else:
            msg.content = f"Lỗi Server: {response.text}"
            await msg.update()
    except Exception as e:
        msg.content = f"Lỗi kết nối: {str(e)}"
        await msg.update()

4. Trải nghiệm thực tế​


Sau khi chạy cả 2 file (server.pyapp.py), hãy thử các case sau:

  • Case Debug: Chụp ảnh màn hình một đoạn code đang bị lỗi đỏ lòm trong VS Code. Gửi cho Jarvis và hỏi: "Sửa lỗi này giúp tôi".
    -> Jarvis: Sẽ đọc được nội dung text trong ảnh và đưa ra giải pháp fix bug.
  • Case Đời sống: Chụp ảnh các nguyên liệu trong tủ lạnh. Hỏi: "Nấu món gì ngon với đống này?".
    -> Jarvis: Nhận diện trứng, cà chua, hành... và gợi ý món trứng bác cà chua.
  • Case Web Design: Vẽ nguệch ngoạc ý tưởng website ra giấy, chụp ảnh lại. Hỏi: "Viết code HTML/CSS cho giao diện này".
    -> Jarvis: Viết code khung sườn dựa trên bản vẽ tay của bạn.

5. Option cho dân chơi Local (Ollama)​


Nếu bạn không muốn tốn tiền API OpenAI, bạn có thể dùng **Ollama** để chạy model **LLaVA** (Large Language-and-Vision Assistant).

Chỉ cần đổi backend một chút:
Python:
import ollama

response = ollama.chat(
    model='llava', # Cần pull trước: ollama pull llava
    messages=[{
        'role': 'user',
        'content': req.message,
        'images': [req.image_base64] # Ollama nhận trực tiếp base64 bytes hoặc path
    }]
)
Tuy nhiên, LLaVA chạy local sẽ "ngốn" RAM và GPU kha khá đấy nhé!

Tổng kết​


Chúc mừng! Bạn đã hoàn thành việc xây dựng một "Super AI Assistant".
Jarvis giờ đây đã:
  • Nghe - Nói - Đọc - Viết - Nhìn.
  • Có não bộ xử lý logic phức tạp.
  • Có kiến trúc API chuyên nghiệp.
 
Back
Top