CMS & Content Platforms

Tự động hóa Alt Text trong Optimizely CMS bằng IContentModelUsage

By Ginbok6 min read

Giới thiệu

Văn bản thay thế (alt text) là yếu tố cực kỳ quan trọng đối với cả khả năng tiếp cận (accessibility) và SEO. Trình đọc màn hình dựa vào nó để mô tả hình ảnh cho người dùng khiếm thị, và các công cụ tìm kiếm sử dụng nó để hiểu rõ hơn nội dung của trang.
Trong dự án Optimizely CMS của chúng tôi, chúng tôi đã triển khai một tác vụ tự động “tạo alt text” quét trang web tìm hình ảnh, gửi chúng đến dịch vụ AI để mô tả, và ghi kết quả trở lại các thuộc tính nội dung.

Phiên bản đầu tiên của tác vụ này duyệt qua nội dung thủ công và cố gắng đoán hình ảnh được sử dụng ở đâu. Sau đó, chúng tôi đã cải tiến bằng cách sử dụng API tích hợp sẵn của Optimizely: IContentModelUsage để tìm ra tất cả các vị trí sử dụng của một hình ảnh nhất định một cách đáng tin cậy. Bài viết này sẽ trình bày phương pháp tiếp cận cuối cùng.


Tổng quan về Kịch bản

Mục tiêu của tác vụ là:

Cải tiến quan trọng là thay thế logic "tìm hình ảnh đã sử dụng" mong manh bằng IContentModelUsage, API này hiểu cách media được tham chiếu trên toàn trang ở cấp độ mô hình dữ liệu.


Bước 1: Khám phá Hình ảnh Thiếu Alt Text

Chúng ta bắt đầu bằng cách truy vấn các tài sản media và lọc những tài sản không có alt text có ý nghĩa. Điều này phụ thuộc vào mô hình media của bạn, nhưng một mẫu điển hình trông như sau:

public class ImageFile : ImageData
{
    [Display(Name = "Alt text", Order = 100)]
    public virtual string AltText { get; set; }
}

Trong công việc định kỳ (scheduled job):

var imagesWithoutAlt = _contentRepository
    .GetDescendents(ContentReference.GlobalBlockFolder) // hoặc thư mục media root của bạn
    .Select(x => _contentRepository.Get<ImageFile>(x))
    .Where(img => string.IsNullOrWhiteSpace(img.AltText))
    .ToList();

Điều này cung cấp cho chúng ta tập hợp các hình ảnh ứng cử viên cần làm giàu thông tin.


Bước 2: Lấy Hình ảnh đã Sử dụng bằng ContentModelUsage

Ban đầu, tác vụ cố gắng suy luận vị trí hình ảnh được sử dụng bằng cách quét các thuộc tính nội dung và khớp ID. Cách làm này dễ bị lỗi và dễ hỏng khi các loại nội dung hoặc thuộc tính mới được thêm vào.

Phiên bản cải tiến sử dụng IContentModelUsage:

private readonly IContentModelUsage _contentModelUsage;

public AltTextGenerationJob(
    IContentRepository contentRepository,
    IContentModelUsage contentModelUsage,
    IAltTextService altTextService,
    ILogger logger)
{
    _contentRepository = contentRepository;
    _contentModelUsage = contentModelUsage;
    _altTextService = altTextService;
    _logger = logger;
}

private IEnumerable<UsageInContentModel> GetImageUsages(ContentReference imageRef)
{
    // Lệnh này yêu cầu Optimizely cho biết tài sản cụ thể này được tham chiếu ở đâu
    return _contentModelUsage.ListContentOfContent(imageRef);
}

Mỗi đối tượng UsageInContentModel cho chúng ta biết mục nội dung nào sử dụng hình ảnh, và trong nhiều trường hợp, thuộc tính nào chứa tham chiếu. Điều này mạnh mẽ hơn nhiều so với việc tự viết code reflection, vì nó tôn trọng cách Optimizely lưu trữ các tham chiếu nội bộ.


Bước 3: Tạo Alt Text bằng AI

Đối với mỗi hình ảnh và các vị trí sử dụng của nó, chúng tôi gọi một dịch vụ AI có thể kiểm tra hình ảnh và trả về mô tả ngôn ngữ tự nhiên. Chi tiết triển khai phụ thuộc vào nhà cung cấp của bạn (Azure OpenAI, custom vision, v.v.), nhưng mẫu chung là tương tự:

public interface IAltTextService
{
    Task<string> GenerateAltTextAsync(ImageFile image);
}

public async Task<string> GenerateAltTextAsync(ImageFile image)
{
    var url = _urlResolver.GetUrl(image.ContentLink);
    // Gọi API AI bên ngoài với URL hình ảnh
    var description = await _aiClient.DescribeImageAsync(url);
    return description.Truncate(200); // giữ alt text ngắn gọn hợp lý
}

Công việc định kỳ điều phối luồng:

foreach (var image in imagesWithoutAlt)
{
    var usages = GetImageUsages(image.ContentLink).ToList();
    if (!usages.Any())
    {
        _logger.Information("Image {ImageId} is not used anywhere, skipping.", image.ContentLink);
        continue;
    }

    var altText = await _altTextService.GenerateAltTextAsync(image);
    if (string.IsNullOrWhiteSpace(altText))
    {
        _logger.Warning("AI did not return alt text for image {ImageId}", image.ContentLink);
        continue;
    }

    var writable = image.CreateWritableClone() as ImageFile;
    writable.AltText = altText;
    _contentRepository.Save(writable, SaveAction.Publish, AccessLevel.NoAccess);

    _logger.Information(
        "Generated alt text for image {ImageId} used in {UsageCount} items.",
        image.ContentLink, usages.Count);
}

Ở đây, hàm GetImageUsages được cung cấp bởi IContentModelUsage, vì vậy chúng ta biết chính xác mức độ sử dụng của mỗi hình ảnh và có thể ưu tiên tương ứng (ví dụ: bỏ qua các tài sản không được sử dụng hoặc ghi nhật ký chúng riêng biệt).


Bước 4: Lợi ích của việc sử dụng ContentModelUsage

Chuyển bước "tìm hình ảnh đã sử dụng" sang IContentModelUsage mang lại một số lợi ích cụ thể:

Nhìn chung, sự kết hợp giữa ImageFile.AltText,  IContentModelUsage, và dịch vụ mô tả AI đã mang lại cho chúng tôi một cách thức lặp lại để cải thiện khả năng tiếp cận trên hàng nghìn hình ảnh với nỗ lực thủ công tối thiểu.


Kết luận

Tự động hóa việc tạo alt text là một cách mạnh mẽ để nâng cao nền tảng khả năng tiếp cận của một trang web Optimizely CMS. Lựa chọn thiết kế then chốt trong dự án này là để chính nền tảng cho chúng ta biết hình ảnh được sử dụng ở đâu, thông qua IContentModelUsage, thay vì cố gắng đoán.

#OptimizelyCMS AI SEO Accessibility Automation
← Back to Articles