Từ nguyên mẫu đến tác nhân bằng ADK

1. Tổng quan

Ngày nay, việc xây dựng bằng AI bắt đầu từ đâu? Đối với hầu hết chúng ta, quá trình này thường bắt đầu bằng một câu hỏi đơn giản: "Liệu mô hình này có thể giúp giải quyết vấn đề mà tôi đang nghĩ đến không?". Đó chính là lúc Google AI Studio phát huy tác dụng. Đây là nơi bạn có thể nhanh chóng tạo mẫu cho mọi thứ. Tôi muốn sửa lại nhà bếp và tôi tin rằng Gemini có thể giúp tôi. Tuy nhiên, tôi là kỹ sư chứ không phải nhà thầu chung. Tôi thậm chí không biết nên yêu cầu những gì – có quá nhiều điều cần cân nhắc: quy định, thiết bị cố định, v.v. Vì vậy, hãy chia nhỏ vấn đề này và yêu cầu Gemini tạo một câu lệnh siêu chi tiết cho chúng ta, sau đó tạo một kế hoạch cải tạo toàn diện và hình dung quá trình cải tạo! Nhưng khoan đã. Làm cách nào để tôi có thể giúp doanh nghiệp mở rộng quy mô từ đây? Nhập AGENTS!!!

Tác nhân là một chương trình tự động trò chuyện với mô hình AI để thực hiện một thao tác dựa trên mục tiêu bằng cách sử dụng các công cụ và bối cảnh mà tác nhân có, đồng thời có khả năng đưa ra quyết định tự động dựa trên sự thật!

Agent Development Kit (ADK)

Agent Development Kit (ADK) là một khung linh hoạt và mô-đun để phát triển và triển khai các tác nhân AI. ADK hỗ trợ việc tạo các ứng dụng phức tạp bằng cách kết hợp nhiều thực thể tác nhân riêng biệt thành một Hệ thống nhiều tác nhân (MAS).

Trong ADK, hệ thống nhiều tác nhân là một ứng dụng mà trong đó các tác nhân khác nhau (thường tạo thành một hệ thống phân cấp) cộng tác hoặc phối hợp để đạt được một mục tiêu lớn hơn. Việc cấu trúc ứng dụng theo cách này mang lại những lợi ích đáng kể, bao gồm khả năng mô-đun hoá, chuyên môn hoá, khả năng sử dụng lại, khả năng duy trì và khả năng xác định các luồng kiểm soát có cấu trúc bằng cách sử dụng các tác nhân quy trình công việc chuyên dụng.

Sản phẩm bạn sẽ tạo ra

Bạn đã sẵn sàng chuyển từ PROMPT nguyên mẫu của chúng tôi sang phần Xây dựng một tác nhân chưa? Chúng ta sẽ tạo một trợ lý để giúp tạo tài liệu đề xuất cho dự án cải tạo nhà bếp. Trong phần này, bạn sẽ:

  1. Tạo một tác nhân đơn giản để tạo Tài liệu đề xuất cải tạo bằng ADK
  2. Lưu trữ Tài liệu đề xuất cải tạo đã tạo trong một bộ chứa Cloud Storage
  3. Kiểm thử tác nhân trong Cloud Shell và trong đầu ra web của tác nhân

Yêu cầu

  • Một trình duyệt, chẳng hạn như Chrome hoặc Firefox
  • Một dự án trên Google Cloud đã bật tính năng thanh toán.

2. Trước khi bắt đầu

Tạo dự án

  1. Trong Google Cloud Console, trên trang chọn dự án, hãy chọn hoặc tạo một dự án trên Google Cloud.
  2. Đảm bảo bạn đã bật tính năng thanh toán cho dự án trên Cloud. Tìm hiểu cách kiểm tra xem tính năng thanh toán có được bật trên một dự án hay không .
  3. Ngoài ra, nếu bạn đang đọc bài viết này và muốn nhận tín dụng để bắt đầu sử dụng Google Cloud và ADK, hãy sử dụng đường liên kết này để đổi tín dụng.
  4. Bạn có thể làm theo hướng dẫn tại đây để sử dụng mã này. Xin lưu ý rằng đường liên kết này chỉ có hiệu lực đến hết ngày 15 tháng 7 năm 2025 để sử dụng.
  5. Kích hoạt Cloud Shell bằng cách nhấp vào đường liên kết này. Bạn có thể chuyển đổi giữa Cloud Shell Terminal (để chạy các lệnh trên đám mây) và Trình chỉnh sửa (để tạo dự án) bằng cách nhấp vào nút tương ứng trong Cloud Shell.
  6. Sau khi kết nối với Cloud Shell, bạn có thể kiểm tra để đảm bảo rằng bạn đã được xác thực và dự án được đặt thành mã dự án của bạn bằng lệnh sau:
gcloud auth list
  1. Chạy lệnh sau trong Cloud Shell để xác nhận rằng lệnh gcloud biết về dự án của bạn.
gcloud config list project
  1. Nếu bạn chưa đặt dự án, hãy dùng lệnh sau để đặt:
gcloud config set project <YOUR_PROJECT_ID>
  1. Đảm bảo bạn có Python 3.9 trở lên

Tham khảo tài liệu để biết các lệnh và cách sử dụng gcloud khác.

3. Nguyên mẫu

Truy cập vào Google AI Studio. Bắt đầu nhập câu lệnh. Đây là câu lệnh của tôi:

I want to renovate my kitchen, basically just remodel it. I don't know where to start. So I want to use Gemini to generate a plan. For that I need a good prompt. Give me a short yet detailed prompt that I can use.

Điều chỉnh và định cấu hình các thông số ở bên phải để nhận được phản hồi tối ưu.

Dựa trên nội dung mô tả đơn giản này, Gemini đã tạo cho tôi một câu lệnh cực kỳ chi tiết để bắt đầu quá trình cải tạo! Trên thực tế, chúng tôi đang sử dụng Gemini để nhận được câu trả lời hiệu quả hơn nữa từ AI Studio và các mô hình của chúng tôi. Bạn cũng có thể chọn nhiều mô hình để sử dụng, tuỳ theo trường hợp sử dụng của mình.

Chúng tôi đã chọn Gemini 2.5 Pro. Đây là mô hình Tư duy, tức là chúng ta sẽ nhận được nhiều mã thông báo đầu ra hơn, trong trường hợp này là tối đa 65.000 mã thông báo, để phân tích dạng dài và tài liệu chi tiết. Hộp suy nghĩ của Gemini xuất hiện khi bạn bật Gemini 2.5 Pro. Mô hình này có khả năng suy luận tự nhiên và có thể xử lý các yêu cầu có ngữ cảnh dài.

Hãy xem đoạn mã của câu trả lời bên dưới:

4e4361663df80964.png

AI Studio đã phân tích dữ liệu của tôi và tạo ra tất cả những thứ này, chẳng hạn như tủ, mặt bàn, tấm chắn, sàn nhà, bồn rửa, độ kết dính, bảng màu và lựa chọn vật liệu. Gemini thậm chí còn trích dẫn nguồn!

Bây giờ, hãy thử xem ý tưởng đó trở nên sống động như thế nào bằng một câu lệnh khác.

  1. Sao chép câu lệnh này rồi dán vào trình chỉnh sửa câu lệnh:
Add flat and circular light accessories above the island area for my current kitchen in the attached image.
  1. Đính kèm hình ảnh nhà bếp hiện tại của bạn (hoặc bạn có thể sử dụng hình ảnh mẫu nhà bếp của tôi).
  2. Thay đổi mô hình thành "Gemini 2.0 Flash Preview Image Generation" (Tạo hình ảnh bằng Gemini 2.0 Flash (bản dùng thử)) để bạn có thể tạo hình ảnh.

Tôi nhận được kết quả sau:

fb33e7b1f6560a0c.png

Đó là sức mạnh của Gemini!

Từ việc hiểu video, đến tạo hình ảnh tự nhiên, đến việc cung cấp thông tin thực tế bằng Google Tìm kiếm – có những việc chỉ có thể thực hiện được nhờ Gemini.

Trong AI Studio, bạn có thể lấy nguyên mẫu này, lấy khoá API và mở rộng thành một ứng dụng có đầy đủ chức năng của tác nhân bằng sức mạnh của Vertex AI ADK.

4. Thiết lập ADK

Bây giờ, hãy chuyển đến Cloud Shell Terminal mà chúng ta đã kích hoạt trong phần "Trước khi bắt đầu":

  1. Tạo và kích hoạt môi trường ảo (Nên dùng)

Trong Cloud Shell Terminal, hãy tạo một Môi trường ảo:

python -m venv .venv

Kích hoạt Môi trường ảo:

source .venv/bin/activate
  1. Cài đặt ADK
pip install google-adk

5. Cấu trúc dự án

  1. Trong Cloud Shell Terminal, hãy tạo một thư mục gốc cho các ứng dụng dựa trên tác nhân ở vị trí dự án mà bạn muốn:
mkdir agentic-apps
  1. Trong thư mục chính, hãy tạo một thư mục dành riêng cho dự án hiện tại của chúng ta:
mkdir renovation-agent
  1. Chuyển đến trình chỉnh sửa Cloud Shell và tạo cấu trúc dự án sau bằng cách tạo các tệp (ban đầu là tệp trống):
renovation-agent/
        __init__.py
        agent.py
        requirements.txt
        .env

6. Mã nguồn

  1. Chuyển đến "init.py" rồi cập nhật nội dung sau:
from . import agent
  1. Chuyển đến agent.py rồi cập nhật tệp bằng nội dung sau từ đường dẫn sau:

Trong agent.py, chúng ta nhập các phần phụ thuộc cần thiết, truy xuất các tham số cấu hình từ tệp .env và xác định root_agent để tạo một tài liệu đề xuất và lưu trữ tài liệu đó trong một Nhóm lưu trữ trên đám mây. Để thực hiện bước Cloud Storage, chúng ta sẽ dùng một công cụ có tên là store_pdf.

LƯU Ý: Hiện tại, tệp PDF này CHƯA ĐƯỢC ĐỊNH DẠNG! Dựa trên PR của cộng đồng dev, đoạn mã sau đây đã được đưa vào đây [chưa được kiểm thử], bạn có thể thoải mái điều chỉnh đoạn mã này trong phương thức store_pdf:

doc = SimpleDocTemplate(
        pdf_buffer,
        pagesize=letter,
        rightMargin=0.75 * inch,
        leftMargin=0.75 * inch,
        topMargin=0.75 * inch,
        bottomMargin=0.75 * inch
    )

    styles = getSampleStyleSheet()
    story = []

    # --- CUSTOM STYLES FOR HEADERS ---
    # Define a new style for section headers
    styles.add(ParagraphStyle(name='SectionHeader',
                              parent=styles['Normal'],
                              fontName='Helvetica-Bold', # Make it bolder
                              fontSize=14,               # Make it slightly larger
                              leading=16,                # Line spacing
                              spaceAfter=0.15 * inch,    # Space after the header
                              spaceBefore=0.25 * inch,   # Space before the header
                              textColor=black            # Ensure color is bright/black (default is usually black, but explicit is good)
                             ))

    # Define a style for the main document title
    styles.add(ParagraphStyle(name='DocumentTitle',
                              parent=styles['Normal'],
                              fontName='Helvetica-Bold',
                              fontSize=20,
                              leading=24,
                              spaceAfter=0.25 * inch,
                              alignment=TA_CENTER, # Center align the title
                              textColor=black
                             ))
    # ---------------------------------

    paragraphs_raw = pdf_text.split('\n\n')

    # Heuristic for the garbled line issue (as before, temporary)
    if paragraphs_raw and len(paragraphs_raw[-1]) < 50 and any(char in paragraphs_raw[-1] for char in ['io', 'og', 'al', 'op']):
         logger.warning("Detected potentially garbled last paragraph. Attempting to trim/omit.")
         paragraphs_raw[-1] = "11. Entire Agreement:\nThis proposal constitutes the entire agreement between the parties and supersedes all prior discussions and agreements."


    for i, para_text in enumerate(paragraphs_raw):
        para_text = para_text.strip()
        if not para_text:
            continue

        # Special handling for the main document title (PROPOSAL DOCUMENT)
        if i == 0 and "PROPOSAL DOCUMENT" in para_text.upper():
            p = Paragraph("PROPOSAL DOCUMENT", styles['DocumentTitle'])
            story.append(p)
            story.append(Spacer(1, 0.15 * inch)) # Add space after the title
            # Skip the rest of this initial block if it's just the title
            remaining_text_lines = para_text.splitlines()[1:]
            if remaining_text_lines:
                formatted_text = "<br/>".join(remaining_text_lines)
                p = Paragraph(formatted_text, styles['Normal'])
                story.append(p)
                story.append(Spacer(1, 0.1 * inch))
            continue # Move to the next paragraph

        # Check if the paragraph looks like a section header (e.g., starts with a number and dot or just bold text)
        # This is a heuristic and might need fine-tuning based on actual proposal content variability.
        is_section_header = False
        # Check for numbered sections (e.g., "1. Scope of Work:")
        if para_text.startswith(('1.', '2.', '3.', '4.', '5.', '6.', '7.', '8.', '9.', '10.', '11.')):
            is_section_header = True
        # Check for Exhibit headers (e.g., "Exhibit A: Cabinet Design") or Roman numeral headings
        elif para_text.startswith(('Exhibit ', 'I.', 'II.', 'III.', 'IV.', 'V.', 'VI.', 'VII.')):
            is_section_header = True
        # Check for specific known headers
        elif para_text.strip().upper() in ["IN WITNESS WHEREOF,", "EXHIBITS:"]:
            is_section_header = True


        if is_section_header:
            p = Paragraph(para_text, styles['SectionHeader'])
            story.append(p)
            # No additional Spacer here, as SectionHeader style has spaceAfter
        else:
            formatted_text = para_text.replace('\n', '<br/>')
            p = Paragraph(formatted_text, styles['Normal'])
            story.append(p)
            story.append(Spacer(1, 0.1 * inch)) # Standard space after body paragraphs

    doc.build(story)

    pdf_buffer.seek(0)

    # Upload the PDF to GCS
    storage_client = storage.Client()
    bucket = storage_client.bucket(STORAGE_BUCKET)
    blob = bucket.blob(PROPOSAL_DOCUMENT_FILE_NAME)

    blob.upload_from_file(pdf_buffer, content_type="application/pdf")

    logger.info(f"Successfully uploaded PDF to gs://{STORAGE_BUCKET}/{PROPOSAL_DOCUMENT_FILE_NAME}")

except Exception as e:
    logger.error(f"Error writing text to PDF and uploading: {e}")
    raise
finally:
    if 'pdf_buffer' in locals():
        pdf_buffer.close()
return "Successfully uploaded PDF to GCS!!"
  1. Đảm bảo bạn có Bộ chứa Cloud Storage

Thư mục này dùng để lưu trữ tài liệu đề xuất mà tác nhân tạo ra. Tạo và cấp quyền truy cập để hệ thống dựa trên tác nhân mà chúng ta tạo bằng Vertex AI có thể truy cập vào đó. Sau đây là cách thực hiện:

https://cloud.google.com/storage/docs/creating-buckets#console

Đặt tên cho nhóm của bạn là "next-demo-store". Nếu bạn đặt tên khác, hãy nhớ cập nhật giá trị của STORAGE_BUCKET trong tệp .env (trong bước Thiết lập biến môi trường).

  1. Để thiết lập quyền truy cập vào bộ chứa, hãy chuyển đến bảng điều khiển Cloud Storage và đến bộ chứa lưu trữ của bạn (trong trường hợp này, tên bộ chứa là "next-demo-storage": https://console.cloud.google.com/storage/browser/next-demo-storage.

Chuyển đến phần Permissions (Quyền) -> View Principals (Xem người dùng) -> Grant Access (Cấp quyền truy cập). Chọn Principals (Chủ thể) là "allUsers" và Role (Vai trò) là "Storage Object User" (Người dùng đối tượng lưu trữ).

Make sure to not enable "prevent public access". Since this is a demo/study application we are going with a public bucket. Remember to configure permission settings appropriately when you are building your application.
  1. Tạo danh sách các phần phụ thuộc

Liệt kê tất cả các phần phụ thuộc trong requirements.txt. Bạn có thể sao chép mã này từ repo.

Giải thích mã nguồn hệ thống của một tác nhân

Tệp agent.py xác định cấu trúc và hành vi của hệ thống nhiều tác nhân cải tạo nhà bếp bằng Agent Development Kit (ADK). Hãy phân tích các thành phần chính:

Định nghĩa về nhân viên hỗ trợ

Tác nhân gốc (Orchestrator): proposal_agent

root_agent đóng vai trò là đơn vị điều phối của hệ thống một tác nhân này. Nó nhận được yêu cầu cải tạo ban đầu và xác định những công cụ cần gọi dựa trên nhu cầu của yêu cầu.

Sau đó, root_agent sẽ thu thập các phản hồi từ các công cụ và kết hợp chúng để cung cấp cho người dùng một phản hồi toàn diện. Trong trường hợp này, chúng ta chỉ có một công cụ "store_pdf".

7. Luồng dữ liệu và các khái niệm chính

Người dùng bắt đầu một yêu cầu thông qua giao diện ADK (thiết bị đầu cuối hoặc giao diện người dùng web).

  1. root_agent sẽ nhận được yêu cầu.
  2. root_agent phân tích yêu cầu và định tuyến yêu cầu đó đến công cụ khi cần.
  3. Công cụ "store_pdf" được thiết kế để ghi nội dung văn bản đã được cải tiến vào một tệp PDF, sau đó tải tệp đó lên Google Cloud Storage.
  4. Sau đó, thao tác này sẽ trả về phản hồi cho root_agent.
  5. root_agent kết hợp các câu trả lời và cung cấp kết quả cuối cùng cho người dùng.

LLM (Mô hình ngôn ngữ lớn)

Các tác nhân này dựa nhiều vào LLM để tạo văn bản, trả lời câu hỏi và thực hiện các tác vụ suy luận. LLM là "bộ não" giúp các tác nhân có thể hiểu và phản hồi yêu cầu của người dùng. Chúng tôi đang sử dụng Gemini 2.5 trong ứng dụng này.

Google Cloud Storage

Được dùng để lưu trữ các tài liệu đề xuất cải tạo đã tạo. Bạn cần tạo một vùng lưu trữ và cấp các quyền cần thiết để các tác nhân có thể truy cập vào vùng lưu trữ đó.

Cloud Run (Không bắt buộc)

OrderingAgent sử dụng một hàm Cloud Run để tương tác với AlloyDB. Cloud Run cung cấp một môi trường phi máy chủ để thực thi mã nhằm phản hồi các yêu cầu HTTP.

AlloyDB

Nếu đang sử dụng OrderingAgent, bạn cần thiết lập một cơ sở dữ liệu AlloyDB để lưu trữ thông tin đơn đặt hàng.

Tệp.env

Tệp .env lưu trữ thông tin nhạy cảm như khoá API, thông tin đăng nhập cơ sở dữ liệu và tên bộ chứa. Bạn cần phải giữ an toàn cho tệp này và không xác nhận (commit) tệp đó vào kho lưu trữ của mình. Thư mục này cũng lưu trữ các chế độ cài đặt cấu hình cho các tác nhân và dự án của bạn trên Google Cloud. root_agent hoặc các hàm hỗ trợ thường sẽ đọc các giá trị từ tệp này. Đảm bảo tất cả các biến bắt buộc đều được thiết lập đúng cách trong tệp .env. Trong đó có tên bộ chứa Cloud Storage

8. Thiết lập mô hình

Khả năng hiểu yêu cầu của người dùng và tạo câu trả lời của trợ lý ảo được hỗ trợ bởi Mô hình ngôn ngữ lớn (LLM). Trợ lý của bạn cần thực hiện các lệnh gọi an toàn đến dịch vụ LLM bên ngoài này, yêu cầu thông tin xác thực. Nếu không có hoạt động xác thực hợp lệ, dịch vụ LLM sẽ từ chối các yêu cầu của tác nhân và tác nhân sẽ không thể hoạt động.

  1. Lấy khoá API từ Google AI Studio.
  2. Ở bước tiếp theo khi bạn thiết lập tệp .env, hãy thay thế <<your API KEY>> bằng giá trị API KEY thực tế của bạn.

9. Thiết lập biến ENV

  1. Thiết lập các giá trị cho các tham số trong tệp .env mẫu trong repo này. Trong trường hợp của tôi, .env có các biến sau:
GOOGLE_GENAI_USE_VERTEXAI=FALSE
GOOGLE_API_KEY=<<your API KEY>>
GOOGLE_CLOUD_LOCATION = us-central1 <<or your region>>
GOOGLE_CLOUD_PROJECT = <<your project id>>
PROJECT_ID = <<your project id>>
GOOGLE_CLOUD_REGION=us-central1 <<or your region>>
STORAGE_BUCKET = next-demo-store <<or your storage bucket name>>

Thay thế trình giữ chỗ bằng các giá trị của bạn.

10. Chạy tác nhân

  1. Sử dụng thiết bị đầu cuối, chuyển đến thư mục mẹ của dự án tác nhân:
cd agentic-apps/renovation-agent
  1. Cài đặt tất cả các phần phụ thuộc
pip install -r requirements.txt
  1. Bạn có thể chạy lệnh sau trong thiết bị đầu cuối Cloud Shell để thực thi tác nhân:
adk run .
  1. Bạn có thể chạy lệnh sau để chạy trong giao diện người dùng web được cung cấp ADK:

Lưu ý: Bạn phải chạy lệnh này bên NGOÀI thư mục dự án tác nhân, sau đó thoát ra một bước rồi chạy lệnh:

adk web
  1. Hãy thử với các câu lệnh sau:
user>> 

Hello. Generate Proposal Document for the kitchen remodel requirement in a proper format that applies to a renovation contract. Remember this text will eventually be stored as a pdf file so make sure to have the formatting appropriate. I have no other specification.

11. Kết quả

Đối với lệnh adk run . kết quả như sau"

2703603a907329ae.png

ae56b38cc6da9afe.png

...

91452a4de933a75b.png

Bạn có thể xác thực xem tài liệu Đề xuất cải tạo có được tạo trong Bộ chứa của bộ nhớ trên đám mây hay không.

12. Triển khai lên Cloud Run

  1. Tạo một tệp có tên là Dockerfile trong thư mục gốc của dự án:
cd agentic-apps/renovation-agent
  1. Sao chép nội dung từ kho lưu trữ trên GitHub
https://github.com/AbiramiSukumaran/adk-renovation-single-agent/blob/main/Dockerfile

vào tệp Dockerfile này.

  1. Triển khai trên Cloud Run bằng lệnh sau:
adk deploy cloud_run --project=abis-345004 --region=us-central1 --service_name=renovation-agent --app_name=renovation-app --with_ui .

Vậy là xong. Sau khi triển khai, bạn sẽ thấy điểm cuối trong thiết bị đầu cuối và có thể sử dụng điểm cuối đó.

13. Dọn dẹp

Để tránh phát sinh phí cho tài khoản Google Cloud của bạn đối với các tài nguyên được dùng trong bài đăng này, hãy làm theo các bước sau:

  1. Trong Google Cloud Console, hãy chuyển đến trang Quản lý tài nguyên.
  2. Trong danh sách dự án, hãy chọn dự án mà bạn muốn xoá, rồi nhấp vào Xoá.
  3. Trong hộp thoại, hãy nhập mã dự án rồi nhấp vào Tắt để xoá dự án.

14. Xin chúc mừng

Xin chúc mừng! Bạn đã tạo và tương tác thành công với ứng dụng có nhiều tác nhân bằng ADK! Hệ thống đa tác nhân được thiết kế để đơn giản hoá quy trình cải tạo nhà bếp bằng cách tự động hoá các công việc như tạo đề xuất, kiểm tra giấy phép và theo dõi trạng thái đơn đặt hàng. Mỗi tác nhân đều có một vai trò cụ thể và root_agent sẽ điều phối các hoạt động của chúng để đưa ra một giải pháp toàn diện. Hệ thống tận dụng các LLM, dịch vụ Google Cloud và có thể là các API bên ngoài để cung cấp chức năng của mình. Tại đây là đường liên kết đến tài liệu về sản phẩm.