Xây dựng workflow đa phương thức với LLM chạy cục bộ: Gemma 4 và Ollama
Hướng dẫn xây dựng pipeline chạy hoàn toàn cục bộ với Gemma 4 và Ollama, cho phép LLM nhận đầu vào hình ảnh và trả về dữ liệu có cấu trúc. Quy trình ba giai đoạn từ tiền xử lý ảnh, phân tích từng bức ảnh đến tổng hợp ký ức chuyến đi, kèm cách xử lý lỗi tương thích đa phương thức và minh họa ứng dụng travel-memory.

Xây dựng workflow đa phương thức với LLM chạy cục bộ: Gemma 4 và Ollama
Chạy một mô hình ngôn ngữ lớn (LLM) cục bộ đang trở thành lựa chọn hấp dẫn khi bạn làm việc với dữ liệu nhạy cảm hoặc muốn xây dựng quy trình tự động ngay trên máy tính của mình. Điều thú vị là những quy trình này không còn bị giới hạn ở văn bản. Nhờ các mô hình đa phương thức, bạn có thể đưa cả hình ảnh vào luồng xử lý và nhận lại những kết quả có cấu trúc, sẵn sàng cho các bước phía sau tiêu thụ.
Trong bài viết này, chúng ta sẽ cùng xây dựng một workflow như vậy với Gemma 4 và Ollama. Cụ thể, tác giả dùng chính những bức ảnh chụp trong chuyến đi Phần Lan để phân tích, sau đó áp dụng cùng quy trình để tạo ra một ứng dụng nhỏ quản lý ký ức du lịch.
Workflow đa phương thức là gì?
Thuật ngữ multimodal workflow gợi ý hai ý tưởng chính.
Thứ nhất, đa phương thức. Thay vì chỉ làm việc với văn bản, LLM còn nhận được đầu vào từ các loại dữ liệu khác, chẳng hạn như hình ảnh. Trong bài này, mô hình được sử dụng là Gemma 4 của Google, một dòng mô hình có khả năng xử lý đồng thời ảnh và chữ.
Thứ hai, workflow. Thay vì để mô hình tự quyết định bước tiếp theo như trong một hệ thống agentic, LLM được đặt trong một chuỗi các bước đã được định nghĩa trước. Mỗi giai đoạn nhận đầu vào, thực hiện một phép biến đổi ngữ nghĩa và chuyển kết quả cho giai đoạn kế tiếp.
Với bài toán phân tích ảnh du lịch, chúng ta cần biến một thư mục ảnh thành những bản ghi ký ức có tổ chức. Điều này có thể chia thành ba giai đoạn:
- Tiền xử lý ảnh: Python chuẩn bị từng tấm ảnh, trích xuất metadata như thời gian chụp và tọa độ GPS.
- Phân tích từng ảnh: Gemma 4 xem ảnh và trả về một bản ghi có cấu trúc mô tả nội dung thị giác.
- Tổng hợp chuyến đi: Gemma 4 đọc tất cả các bản ghi để tạo ra bản tóm tắt cấp cao cho toàn bộ chuyến đi.
Xây dựng workflow với Gemma 4
Chạy Gemma 4 cục bộ
Để đưa Gemma 4 vào môi trường local, chúng ta dùng Ollama — một công cụ cung cấp runtime và giao diện tương tác với mô hình ngay trên máy cá nhân.
Trên Windows và macOS, bạn chỉ cần tải bộ cài từ website Ollama. Trên Linux, có thể cài đặt qua terminal:
curl -fsSL https://ollama.com/install.sh | sh
Sau đó kéo mô hình Gemma về:
ollama pull gemma4:e4b
Trong bài viết gốc, tác giả sử dụng biến thể E4B của Gemma 4 — một phiên bản tối ưu cho các thiết bị biên. Tiếp theo, cài các thư viện Python cần thiết:
pip install ollama pillow pydantic
ollama: kết nối Python với LLM cục bộ.pillow: xử lý ảnh.pydantic: khai báo và xác thực đầu ra có cấu trúc.
Từ ảnh đến bản ghi có cấu trúc
Với mỗi bức ảnh, mục tiêu là tạo ra một bản ghi mô tả những gì mô hình nhìn thấy. Trước khi ảnh đến Gemma 4, cần có bước tiền xử lý để resize ảnh và trích xuất EXIF metadata. Hàm prepare_photo() trong repository gốc đảm nhiệm việc này.
Tiếp theo, chúng ta định nghĩa cấu trúc dữ liệu mong muốn bằng Pydantic:
from pydantic import BaseModel, Field
class PhotoMemoryAnalysis(BaseModel):
scene_summary: str
memory_caption: str
place_type: str
visible_activities: list[str]
visible_objects: list[str]
inferred_interest_signals: list[str]
mood: str
uncertainty_notes: list[str]
confidence: float = Field(ge=0, le=1)
Đây là khái niệm structured output — chúng ta định nghĩa trước schema và yêu cầu LLM trả về theo đúng hình dạng đó. Nhờ vậy, mã nguồn phía sau có thể truy cập kết quả thông qua các thuộc tính có kiểu dữ liệu rõ ràng hoặc chuyển thành dictionary bằng model_dump().
Hàm gọi Gemma 4 sẽ trông tương tự như sau:
import ollama
MODEL = "gemma4:e4b"
def analyze_photo(image: bytes, metadata: dict) -> PhotoMemoryAnalysis:
response = ollama.chat(
model=MODEL,
messages=[
{
"role": "system",
"content": PHOTO_ANALYSIS_INSTRUCTION,
},
{
"role": "user",
"content": build_photo_prompt(metadata),
"images": [image],
},
],
format=PhotoMemoryAnalysis.model_json_schema(),
options={"temperature": 0},
)
return PhotoMemoryAnalysis.model_validate_json(response.message.content)
Điểm đáng chú ý là trường images để truyền ảnh vào mô hình, còn format để Ollama tuân theo schema đã khai báo.
Một lỗi tương thích cần xử lý
Tác giả chia sẻ rằng với cấu hình hiện tại — Ollama 0.32.5 trên Windows và gemma4:e4b — Ollama chấp nhận yêu cầu đa phương thức nhưng mô hình lại không thực sự dùng được nội dung hình ảnh.
Giải pháp được sử dụng là nạp Gemma 4 từ hai tệp riêng biệt trong kho Unsloth Gemma 4 E4B GGUF:
mmproj-BF16.gguf: chứa multimodal projector, thành phần giúp mô hình hiểu thông tin hình ảnh.gemma-4-E4B-it-UD-Q4_K_XL.gguf: chứa mô hình đã lượng tử hóa.
Sau khi đặt cả hai tệp vào cùng một thư mục, tạo một Modelfile:
FROM ./gemma-4-E4B-it-UD-Q4_K_XL.gguf
FROM ./mmproj-BF16.gguf
Rồi import vào Ollama:
ollama create gemma4-e4b-split-test -f Modelfile
Cuối cùng, cập nhật tên mô hình trong Python:
MODEL = "gemma4-e4b-split-test"
Với cách này, Gemma có thể đọc và hiểu ảnh đúng như mong đợi. Nếu trên máy bạn gemma4:e4b đã hoạt động bình thường với ảnh thì không cần áp dụng workaround này.
Từ bản ghi ảnh đến tổng hợp chuyến đi
Sau khi phân tích từng ảnh, chúng ta áp dụng analyze_photo() cho toàn bộ thư mục. Mỗi bản ghi ảnh kết hợp hai nguồn thông tin: metadata từ tệp và diễn giải ngữ nghĩa từ Gemma 4.
Giai đoạn cuối cùng cũng dùng Pydantic để định nghĩa đầu ra:
class MemorableMoment(BaseModel):
title: str
description: str
evidence_photo_ids: list[str]
class TripMemorySynthesis(BaseModel):
narrative_summary: str
inferred_interests: list[str]
recurring_themes: list[str]
memorable_moments: list[MemorableMoment]
uncertainty_notes: list[str]
Khác với bước trước, lời gọi mô hình ở giai đoạn này chỉ dùng văn bản. Tất cả thông tin ảnh đã được chuyển thành các bản ghi có cấu trúc, nên Gemma 4 chỉ cần tổng hợp từ các bản ghi đó.
Kết quả cho bảy bức ảnh trong chuyến đi Phần Lan là một bản tóm tắt khá mạch lạc:
Chuyến đi mùa hè này qua Phần Lan là một hành trình đa dạng, hòa trộn giữa trải nghiệm văn hóa và khám phá thiên nhiên. Du khách được chiêm ngưỡng những công trình kiến trúc lớn, từ phòng hòa nhạc hiện đại đến các địa danh tân cổ điển, đồng thời tận hưởng cuộc sống đô thị qua khung cảnh thành phố và trải nghiệm ẩm thực. Một phần quan trọng của chuyến đi tập trung vào thiên nhiên, với những cuộc gặp gỡ động vật hoang dã và hoàng hôn bên sông.
Dưới đây là hai ví dụ minh họa mà Gemma 4 đã phân tích:
Bức ảnh du lịch được sử dụng để phân tích trong workflow
Bức ảnh động vật hoang dã được mô hình nhận diện trong chuyến đi
Với bức ảnh đầu tiên, mô hình nhận diện được vòng quay cảm tình, đọc được dòng chữ hiển thị trên đó và ghi nhận bầu không khí buổi hoàng hôn. Với bức ảnh thứ hai, Gemma 4 mô tả đúng một con cú trong môi trường hoang dã, đồng thời thận trọng ghi chú rằng không thể xác định chính xác loài chim chỉ từ hình ảnh.
Từ workflow đến ứng dụng
Để minh họa sức mạnh thực tế của workflow, tác giả đã xây dựng một ứng dụng nhỏ tên travel-memory. Ứng dụng cho phép người dùng tải ảnh lên, kích hoạt quy trình phân tích ngay từ giao diện, sau đó tự động sắp xếp ảnh theo dòng thời gian và đặt chúng lên bản đồ dựa trên tọa độ GPS.
Giao diện ứng dụng travel-memory được xây dựng từ workflow Gemma 4 và Ollama
Mỗi bức ảnh đều có phần chú thích, thẻ cảnh và các thông tin chi tiết do Gemma 4 tạo ra. Ở cấp độ chuyến đi, người dùng có thể xem tóm tắt, sở thích được suy luận và những khoảnh khắc đáng nhớ. Ứng dụng cũng hỗ trợ tìm kiếm và hỏi đáp về toàn bộ bộ ảnh — tất cả đều được xử lý bởi một LLM cục bộ.
Mã nguồn đầy đủ của dự án nằm tại: https://github.com/ShuaiGuo16/gemma4-multimodal-workflow
Việc kết hợp đầu vào đa phương thức và đầu ra có cấu trúc mở ra cách xây dựng ứng dụng mới mẻ: LLM không chỉ là chatbot, mà còn là một bộ xử lý ngữ nghĩa nằm trong quy trình tự động. Với người dùng quan tâm đến quyền riêng tư dữ liệu, việc chạy toàn bộ pipeline trên máy cá nhân càng trở nên có giá trị khi không cần gửi ảnh hay thông tin nhạy cảm lên đám mây.


