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.