0

Tự động hóa việc tạo tài liệu bằng AI trong Ruby on Rails

Trong các dự án phần mềm hiện đại, việc tự động hóa các tác vụ lặp đi lặp lại là rất quan trọng để tăng tốc độ phát triển và giảm thiểu sai sót do con người. Một ví dụ tuyệt vời là tạo tài liệu — dù đó là tài liệu yêu cầu sản phẩm (PRD), đề xuất dự án hay bài thuyết trình.

Gần đây, tôi đã làm việc trên một hệ thống sử dụng AI để tạo ra nội dung có cấu trúc từ các cuộc hội thoại, sau đó xuất tài liệu dưới nhiều định dạng như Word (.odt), PowerPoint (.pptx), Markdown (.md) và nhiều định dạng khác. Kiến trúc hệ thống tận dụng AI hội thoại để tạo nội dung có cấu trúc, và hoàn toàn có thể tích hợp với Ruby on Rails. Dưới đây là cách bạn có thể xây dựng hệ thống như vậy.

Cách hoạt động: Kiến trúc hệ thống

User Input (Q&A + files)
        ↓
Conversational AI (OpenAI)
        ↓
Structured JSON PRD (document sections)
        ↓
Output Generators:
  ├─ DOCX (Word templates)
  ├─ PPTX (PowerPoint templates)
  ├─ Markdown (MD templates)
  ├─ YAML (configuration/data serialization)
  ├─ ODT (OpenDocument Text)
  ├─ PDF (final polished document)
  └─ TXT (plain text export)
        ↓
Export & Delivery (files to users)

Luồng này đảm bảo việc tách biệt rõ ràng giữa quá trình tạo nội dung và hiển thị định dạng, giúp hệ thống có thể mở rộng và dễ bảo trì.

Ruby on Rails: Ví dụ triển khai

1. AI hội thoại

Sử dụng gem ruby-openai để tương tác với API của OpenAI:

require 'openai'

class AiPrdService
  def initialize(user_prompt)
    @client = OpenAI::Client.new(access_token: ENV['OPENAI_API_KEY'])
    @user_prompt = user_prompt
  end

  def generate_prd_json
    response = @client.chat(
      parameters: {
        model: "gpt-4o-mini",
        messages: [
          { role: "system", content: "You are an AI assistant that generates structured PRDs." },
          { role: "user", content: @user_prompt }
        ],
        temperature: 0.7
      }
    )

    # Extract JSON from response (assuming AI outputs JSON)
    prd_content = JSON.parse(response.dig("choices", 0, "message", "content"))
    prd_content
  rescue JSON::ParserError => e
    Rails.logger.error "Failed to parse AI response: #{e.message}"
    nil
  end
end

2. Tạo DOCX bằng template

Sử dụng gem caracal để tạo tài liệu Word:

require 'caracal'

class DocxGenerator
  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_docx(output_path)
    Caracal::Document.save(output_path) do |docx|
      docx.h1 @prd_json['title']
      @prd_json['sections'].each do |section|
        docx.h2 section['heading']
        docx.p section['content']
      end
    end
  end
end

3. Tạo Markdown (MD)

Sử dụng ERB để render mẫu:

class MarkdownGenerator
  TEMPLATE = <<~MD
    # <%= @prd_json['title'] %>

    <% @prd_json['sections'].each do |section| %>
    ## <%= section['heading'] %>

    <%= section['content'] %>

    <% end %>
  MD

  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_markdown
    ERB.new(TEMPLATE).result(binding)
  end
end

4. Xuất YAML cho cấu hình hoặc chia sẻ dữ liệu

require 'yaml'

class YamlGenerator
  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_yaml(output_path)
    File.write(output_path, @prd_json.to_yaml)
  end
end

5. Tạo ODT (OpenDocument Text)

Sử dụng gem odf-report:

require 'odf-report'

class OdtGenerator
  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_odt(output_path)
    report = ODFReport::Report.new("template.odt") do |r|
      r.add_field("TITLE", @prd_json['title'])
      @prd_json['sections'].each_with_index do |section, index|
        r.add_field("HEADING#{index+1}", section['heading'])
        r.add_field("CONTENT#{index+1}", section['content'])
      end
    end

    report.generate(output_path)
  end
end

6. Tạo PDF

Sử dụng gem prawn (hoặc wicked_pdf cho HTML sang PDF):

require 'prawn'

class PdfGenerator
  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_pdf(output_path)
    Prawn::Document.generate(output_path) do |pdf|
      pdf.text @prd_json['title'], size: 24, style: :bold
      @prd_json['sections'].each do |section|
        pdf.move_down 10
        pdf.text section['heading'], size: 18, style: :bold
        pdf.text section['content'], size: 12
      end
    end
  end
end

7. Xuất văn bản thuần túy (TXT)

class TxtGenerator
  def initialize(prd_json)
    @prd_json = prd_json
  end

  def generate_txt(output_path)
    content = []
    content << @prd_json['title']
    @prd_json['sections'].each do |section|
      content << "\n#{section['heading']}\n"
      content << "#{section['content']}\n"
    end
    File.write(output_path, content.join("\n"))
  end
end

Tại sao xây dựng hệ thống này bằng Rails?

  • Dễ bảo trì: Kiến trúc MVC và pattern service object của Rails giúp tách biệt rõ trách nhiệm.
  • Dễ mở rộng: Thêm định dạng mới như PDF, ODT chỉ cần vài bước.
  • Tích hợp tốt: Có thể sử dụng ActiveJob và xử lý nền để tạo tài liệu không đồng bộ.
  • Hệ sinh thái phong phú: Có nhiều gem hỗ trợ tạo mẫu tài liệu và HTTP client.

Tổng kết

Bằng cách kết hợp các mô hình hội thoại mạnh mẽ của OpenAI với kiến trúc linh hoạt của Ruby on Rails, bạn có thể xây dựng các pipeline mạnh mẽ để tự động chuyển đổi hội thoại của người dùng thành tài liệu có cấu trúc rõ ràng — tiết kiệm thời gian và giảm thiểu công việc thủ công.


All Rights Reserved

Viblo
Let's register a Viblo Account to get more interesting posts.