Hướng dẫn chi tiết xây dựng pipeline tự động hóa xử lý PDF, tạo embeddings với OpenAI và lưu trữ vào Zilliz Cloud, sử dụng AWS Lambda và CircleCI cho CI/CD.
Bạn muốn triển khai AI/API lên AWS Lambda mà không đau đầu với Serverless? Khám phá Mastra Lambda Docker Deploy – giải pháp giúp bạn đưa ứng dụng vào sản xuất chỉ với Docker, đơn giản hóa mọi phức tạp và tăng tốc độ phát triển. Tạm biệt rắc rối, đón chào hiệu quả!
Chào bạn, bạn có bao giờ tò mò làm thế nào để quản lý cơ sở dữ liệu vector một cách “siêu mượt” và tự động hóa toàn bộ quá trình tạo embeddings cho các ứng dụng AI không? Trong thời đại AI bùng nổ như hiện nay, việc tìm kiếm sự tương đồng, đề xuất thông minh hay truy xuất dữ liệu quy mô lớn đều phụ thuộc rất nhiều vào các vector database. Nhưng khi dữ liệu cứ “phình to” không ngừng, việc cập nhật embeddings mới thủ công chẳng khác nào “mò kim đáy bể”, vừa tốn thời gian lại dễ mắc lỗi. Đó là lúc chúng ta cần đến sự “phù phép” của tự động hóa! Trong bài viết này, tôi sẽ cùng bạn khám phá một “bí kíp” xây dựng quy trình tự động hoàn toàn để xử lý và cập nhật vector database, sử dụng bộ ba quyền lực: AWS Lambda, Docker và CircleCI. Chúng ta sẽ cùng nhau biến những file PDF khô khan thành embeddings “thông minh” bằng OpenAI, rồi lưu trữ chúng gọn gàng trong Zilliz Cloud – một cơ sở dữ liệu vector được quản lý cực kỳ tiện lợi. Đồng thời, chúng ta cũng sẽ “dựng nhà” trên AWS (với S3, ECR, Lambda) và triển khai một đường ống CI/CD “siêu tốc” bằng CircleCI để mọi thứ diễn ra tự động như một phép màu. Bạn sẽ học được gì sau chuyến hành trình này? Cách quản lý vector database và tự động hóa việc tạo embeddings. Xây dựng một hàm AWS Lambda để xử lý và cập nhật embeddings. “Đóng gói” hàm Lambda bằng Docker để chạy hiệu quả. Thiết lập CircleCI để tự động hóa kiểm thử và triển khai. Áp dụng các mẹo hay về vai trò IAM và bảo mật trên AWS. Sau khi đọc xong bài hướng dẫn này, bạn sẽ có trong tay một quy trình làm việc tự động hoàn chỉnh để xử lý và cập nhật vector embeddings một cách trơn tru, không cần động tay động chân! Bài viết này giả định bạn đã có chút “làm quen” với Python, AWS và Docker nhé. Bạn có thể xem toàn bộ mã nguồn trên GitHub nếu tò mò, nhưng tôi sẽ dẫn bạn đi từng bước một, không bỏ sót chi tiết nào đâu! https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/example_pipeline_diagram.png Trước khi bắt đầu: Chuẩn bị hành trang Để chuyến hành trình của chúng ta diễn ra suôn sẻ, bạn cần chuẩn bị một vài thứ nhỏ xinh sau đây: 1. **Tài khoản AWS:** Nếu chưa có, hãy đăng ký ngay một tài khoản AWS. Chúng ta sẽ cần đến AWS Lambda và Elastic Container Registry (ECR) để triển khai ứng dụng của mình đó. 2. **AWS CLI:** Đảm bảo bạn đã cài đặt và cấu hình AWS Command Line Interface (CLI) với các thông tin đăng nhập của mình. Nếu chưa, hãy tìm hướng dẫn cài đặt AWS CLI nhé. 3. **Kiến thức cơ bản về LangChain hoặc Vector Databases:** Việc hiểu biết những điều căn bản về LangChain và Vector Databases sẽ giúp bạn dễ dàng hình dung kiến trúc của quy trình này hơn. 4. **Làm quen với AWS Lambda và Docker:** Bạn nên biết những khái niệm cơ bản về AWS Lambda và Docker, vì chúng ta sẽ dùng chúng để “đóng gói” và triển khai ứng dụng. 5. **Tài khoản GitHub và CircleCI:** Hãy tạo tài khoản trên GitHub để quản lý mã nguồn và CircleCI để tự động hóa quy trình CI/CD “thần thánh” của chúng ta. 6. **OpenAI API Key:** Để “triệu hồi” các mô hình GPT của OpenAI, bạn sẽ cần một API key. Đăng ký một chiếc key trên website của OpenAI nhé. 7. **Tài khoản Zilliz Cloud:** Đăng ký một tài khoản Zilliz Cloud để “làm chủ” cơ sở dữ liệu vector của bạn. Bạn sẽ có một cụm miễn phí, cung cấp URI endpoint và Token để giao tiếp với nó. Sau khi đã “tích kê” đủ hết các thứ này, bạn đã sẵn sàng để cùng tôi thiết lập quy trình tự động rồi đó! https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/checklist_prerequisites.png Thiết lập cấu trúc dự án: Ngôi nhà của mã nguồn Trước khi “xắn tay áo” vào code, chúng ta cần xây dựng một “ngôi nhà” gọn gàng cho dự án của mình. Một cấu trúc dự án tốt sẽ giúp việc phát triển, kiểm thử và triển khai trở nên mượt mà hơn rất nhiều, đặc biệt là khi chúng ta làm việc với các dịch vụ đám mây và tự động hóa CI/CD. **Tổ chức dự án và các thành phần chính:** Dự án của bạn sẽ trông giống như một “gia đình” với các thành viên sau đây: * `.circleci/`: Nơi chứa “kịch bản” tự động hóa của CircleCI (config.yml). * `data/`: Thư mục chứa các file dữ liệu đầu vào, ví dụ như file PDF của chúng ta. * `src/`: Đây là “trái tim” của dự án, chứa các mã nguồn chính như `create_collection.py`, `drop_collection.py`, `insert_documents.py`. * `aws_lambda/`: Nơi ở của “bộ não” hệ thống – hàm Lambda `lambda_function.py`. * `scripts/`: Chứa các “người thực hiện kịch bản” là các shell script giúp tự động hóa các tác vụ AWS (`build_deploy.sh`, `create_roles.sh`, `create_image.sh`, `create_lambda.sh`). * `tests/`: “Đội ngũ kiểm định chất lượng” của chúng ta, với các file kiểm thử `test_collection_exists.py`, `test_lambda_function.py`, `test_collection_mock.py`. * `Dockerfile`: “Công thức đóng gói” hàm Lambda vào Docker container. * `pyproject.toml`: “Danh sách mua sắm” các thư viện cần dùng. https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/project_structure_diagram.png **Cài đặt các thư viện với UV Package Manager:** Đầu tiên, hãy “chép” toàn bộ mã nguồn về máy tính của bạn bằng cách clone repository: `git clone https://github.com/benitomartin/embeddings-aws-circlecicd embeddings-aws-circleci` *Lưu ý nhỏ:* Repository này đã có sẵn tất cả các đoạn mã mà chúng ta sẽ nhắc đến trong bài. Bạn không cần phải “khổ công” tạo lại từ đầu đâu nhé! Cứ theo dõi và so sánh là được. Và tất nhiên, bạn hoàn toàn có thể tùy chỉnh cấu trúc này cho phù hợp với dự án “cưng” của mình. Tiếp theo, chúng ta sẽ cài đặt tất cả các thư viện cần thiết bằng UV Package Manager. Nếu bạn chưa có UV, hãy xem hướng dẫn cài đặt của nó nhé: `uv sync --all-extras` `source .venv/bin/activate` Hai câu lệnh này sẽ giúp bạn cài đặt tất cả các “nguyên liệu” (dependencies) đã liệt kê trong file `pyproject.toml` và “kích hoạt” môi trường ảo của dự án. Đơn giản phải không? https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/uv_install.png Cấu hình môi trường: Sổ tay bí mật Hãy tạo một file `.env` ở thư mục gốc của dự án và thêm các biến môi trường sau vào đó. Hãy coi đây là “sổ tay bí mật” chứa các thông tin nhạy cảm của bạn, tuyệt đối không được chia sẻ lung tung nhé! `ZILLIZ_CLOUD_URI=your-zilliz-uri` `ZILLIZ_TOKEN=your-zilliz-token` `COLLECTION_NAME=your-collection-name` `PDF_BUCKET_NAME=your-bucket-name` `OPENAI_API_KEY=your-openai-key` `AWS_REGION=your-aws-region` `AWS_ACCESS_KEY_ID=your-access-key` `AWS_SECRET_ACCESS_KEY=your-secret-key` `AWS_ACCOUNT_ID=your-account-id` `LAMBDA_ECR_REPOSITORY_NAME=your-ecr-repo-name` `LAMBDA_IMAGE_NAME=your-image-name` `LAMBDA_FUNCTION_NAME=your-lambda-name` `ROLE_NAME=your-role-name` `ROLE_POLICY_NAME=your-policy-name` Hãy nhớ thay thế các giá trị `your-something` bằng thông tin thật của bạn nhé. Đây là “chìa khóa” để các dịch vụ của chúng ta có thể liên lạc với nhau! https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/env_file_security.png Thiết lập cơ sở dữ liệu vector: Kho lưu trữ “siêu trí nhớ” Để lưu trữ và truy xuất các embeddings một cách hiệu quả, chúng ta cần thiết lập một cơ sở dữ liệu vector. Phần này sẽ hướng dẫn bạn cấu hình Zilliz Cloud (Milvus), định nghĩa schema và tối ưu hóa cơ sở dữ liệu cho việc tìm kiếm vector nhanh chóng. **Thiết lập Collection trên Zilliz Cloud:** Zilliz Cloud là phiên bản Milvus được quản lý, một cơ sở dữ liệu vector hiệu suất cao. Chúng ta sẽ tạo một “collection” (tạm hiểu là một ngăn kéo chứa dữ liệu) để lưu trữ văn bản đã trích xuất và các embeddings vector tương ứng. Để tạo collection, bạn cần làm theo các bước sau: 1. Đăng ký và tạo một Cluster miễn phí trong Zilliz Cloud. 2. Lấy thông tin kết nối: * **URI:** Tìm thấy trong cài đặt cluster (public endpoint). * **Token:** Cần cho việc xác thực. 3. Đặt các biến môi trường vào file `.env` của bạn và cung cấp một tên cho collection: `ZILLIZ_CLOUD_URI=your-zilliz-uri` `ZILLIZ_TOKEN=your-zilliz-token` `COLLECTION_NAME=your-collection-name` https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fga1zq0ki32z7plrjkzk0.png **Tạo Collection:** Khi đã có thông tin kết nối, bạn có thể tạo một collection trong Zilliz Cloud. Collection này sẽ lưu trữ văn bản đã trích xuất và các embeddings vector tương ứng. Trong thư mục `src`, bạn có thể tạo một script tên là `create_collection.py` với vài hàm để định nghĩa schema và tạo collection: * `create_schema`: Định nghĩa schema, bao gồm: * `id`: Khóa chính tự động tạo (INT64). * `pdf_text`: Văn bản được trích xuất, lưu dưới dạng VARCHAR. * `my_vector`: Embeddings vector, lưu dưới dạng FLOAT_VECTOR (chiều mặc định: 1536). * `create_collection`: Tạo collection trong Zilliz Cloud với schema đã định nghĩa. Nó tối ưu hóa việc tìm kiếm vector bằng cách thiết lập AUTOINDEX với độ tương đồng COSINE, đảm bảo truy xuất hiệu quả. ```python import os from typing import Optional from pymilvus import DataType, MilvusClient def create_schema(dimension: int = 1536) -> MilvusClient.create_schema: """Define the schema for the Milvus collection.""" schema = MilvusClient.create_schema( auto_id=True, enable_dynamic_field=True, ) schema.add_field(field_name="id", datatype=DataType.INT64, is_primary=True) schema.add_field(field_name="pdf_text", datatype=DataType.VARCHAR, max_length=65535) schema.add_field(field_name="my_vector", datatype=DataType.FLOAT_VECTOR, dim=dimension) return schema def create_collection( collection_name: Optional[str] = None, uri: Optional[str] = None, token: Optional[str] = None, dimension: int = 1536, ) -> None: """Create a new Milvus collection with the specified parameters. Args: collection_name (str, optional): Name of the collection. Defaults to env var COLLECTION_NAME. uri (str, optional): Zilliz Cloud URI. Defaults to env var ZILLIZ_CLOUD_URI. token (str, optional): Zilliz token. Defaults to env var ZILLIZ_TOKEN. dimension (int, optional): Vector dimension. Defaults to 1536. """ # Use environment variables as fallback collection_name = collection_name or os.getenv("COLLECTION_NAME") uri = uri or os.getenv("ZILLIZ_CLOUD_URI") token = token or os.getenv("ZILLIZ_TOKEN") if not all([collection_name, uri, token]): raise ValueError("Missing required parameters: collection_name, uri, or token") # Connect to Zilliz Cloud (Milvus) client = MilvusClient(uri=uri, token=token) # Create schema schema = create_schema(dimension) # Prepare index parameters index_params = client.prepare_index_params() index_params.add_index(field_name="my_vector", index_type="AUTOINDEX", metric_type="COSINE") # Create collection client.create_collection(collection_name=collection_name, schema=schema, index_params=index_params) if __name__ == "__main__": # Create collection print("Creating collection...") create_collection() print("Collection created successfully.") ``` Khi cụm Zilliz Cloud của bạn đã sẵn sàng và `.env` đã được cấu hình, hãy chạy lệnh sau: `uv run src/create_collection.py` Lệnh này sẽ tạo một collection trong cụm Zilliz Cloud của bạn. Trong trường hợp bạn muốn “dọn dẹp” collection này, bạn có thể tạo một script `drop_collection.py` trong thư mục `src` để xóa collection và sau đó tạo lại bằng script trước đó. ```python import os from typing import Optional from pymilvus import MilvusClient def drop_collection( collection_name: Optional[str] = None, uri: Optional[str] = None, token: Optional[str] = None, ) -> None: """Drop a Milvus collection. Args: collection_name (str, optional): Name of the collection. Defaults to env var COLLECTION_NAME. uri (str, optional): Zilliz Cloud URI. Defaults to env var ZILLIZ_CLOUD_URI. token (str, optional): Zilliz token. Defaults to env var ZILLIZ_TOKEN. """ # Use environment variables as fallback collection_name = collection_name or os.getenv("COLLECTION_NAME") uri = uri or os.getenv("ZILLIZ_CLOUD_URI") token = token or os.getenv("ZILLIZ_TOKEN") if not all([collection_name, uri, token]): raise ValueError("Missing required parameters: collection_name, uri, or token") # Connect to Zilliz Cloud (Milvus) client = MilvusClient(uri=uri, token=token) # Drop the collection client.drop_collection(collection_name=collection_name) if __name__ == "__main__": # Drop collection print("Dropping collection...") drop_collection() print("Collection dropped successfully.") ``` Để xóa collection, hãy chạy: `uv run src/drop_collection.py` https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/milvus_collection_management.png Triển khai quy trình xử lý PDF: Biến PDF thành “ngôn ngữ” AI Để lưu trữ và tìm kiếm văn bản hiệu quả, chúng ta cần xử lý các file PDF, trích xuất văn bản, chuyển đổi chúng thành embeddings, và lưu trữ vào Zilliz Cloud để truy xuất nhanh chóng. Đảm bảo bạn đã đặt biến môi trường `OPENAI_API_KEY` trong file `.env` của mình nhé. Sau đó, tạo một script `insert_documents.py` trong thư mục `src`. Script này sẽ là “phiên dịch viên” chính của chúng ta, thực hiện các công việc sau: * **Tải văn bản từ PDF:** Sử dụng `PyPDFLoader` từ LangChain để lấy đối tượng `Document`. * **Chia nhỏ văn bản:** Chia văn bản thành các “đoạn” nhỏ dễ quản lý bằng `CharacterTextSplitter` để đảm bảo embeddings chính xác. * **Tạo embeddings:** Sử dụng OpenAI để tạo các embeddings vector. * **Lưu trữ vào Zilliz Cloud:** Lưu văn bản và embeddings vào Zilliz Cloud bằng `MilvusClient` để tìm kiếm sự tương đồng hiệu quả. ```python import os from typing import Optional from langchain_community.document_loaders import PyPDFLoader from langchain_openai import OpenAIEmbeddings from langchain_text_splitters import CharacterTextSplitter from pymilvus import MilvusClient def process_pdf(pdf_path: str, chunk_size: int = 512, chunk_overlap: int = 100) -> list[dict]: """Process a PDF file and generate embeddings for its content.""" if not os.path.exists(pdf_path): raise FileNotFoundError(f"PDF file not found at {pdf_path}") # Load and process PDF loader = PyPDFLoader(pdf_path) documents = loader.load() # Split text text_splitter = CharacterTextSplitter(chunk_size=chunk_size, chunk_overlap=chunk_overlap) chunks = text_splitter.split_documents(documents) # Generate embeddings openai_embeddings = OpenAIEmbeddings() # Prepare data for insertion data = [] for chunk in chunks: text = chunk.page_content embedding = openai_embeddings.embed_documents([text])[0] data.append({"pdf_text": text, "my_vector": embedding}) return data def insert_documents( pdf_path: str, collection_name: Optional[str] = None, uri: Optional[str] = None, token: Optional[str] = None, chunk_size: int = 512, chunk_overlap: int = 100, ) -> None: """Insert documents from a PDF file into a Milvus collection.""" # Use environment variables as fallback collection_name = collection_name or os.getenv("COLLECTION_NAME") uri = uri or os.getenv("ZILLIZ_CLOUD_URI") token = token or os.getenv("ZILLIZ_TOKEN") if not all([collection_name, uri, token]): raise ValueError("Missing required parameters: collection_name, uri, or token") # Connect to Zilliz Cloud (Milvus) client = MilvusClient(uri=uri, token=token) # Process PDF and get data data = process_pdf(pdf_path, chunk_size, chunk_overlap) # Insert data client.insert(collection_name, data) # Verify collection load state load_state = client.get_load_state(collection_name=collection_name) print(f"Collection load state: {load_state}") if __name__ == "__main__": # Insert documents print("Inserting documents...") insert_documents("data/1706.03762v7.pdf") print("Documents inserted successfully.") ``` Để chạy script này, bạn hãy dùng lệnh sau. Bạn có thể tìm thấy một file PDF mẫu trong thư mục `data` nhưng cứ thoải mái dùng file của riêng bạn nhé: `uv run src/insert_documents.py` Script này sẽ “xử lý” file PDF của bạn, tạo embeddings và lưu chúng vào collection trong cụm Zilliz Cloud của bạn. Tuyệt vời phải không nào? https://truyentranh.letranglan.top/api/v1/proxy?url=https://media2.dev.to/dynamic/image/width=800%2Cheight=%2Cfit=scale-down%2Cgravity=auto%2Cformat=auto/https%3A%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Farticles%2Fzskssf09tmbz92ziffx2.png Tạo vai trò và chính sách IAM: Bộ phận an ninh của AWS Giờ đây chúng ta đã có một quy trình hoạt động, bước tiếp theo là thiết lập AWS Lambda để kích hoạt quy trình này mỗi khi có một file PDF mới được tải lên một S3 bucket. Để triển khai các hàm AWS Lambda, bạn cần tạo các vai trò (IAM roles) và quyền (permissions) cụ thể trước tiên. Bạn có thể tạo script `create_roles.sh` dưới thư mục `scripts`. Script này tự động hóa quá trình tạo một vai trò IAM với chính sách `AWSLambdaExecute` cần thiết để AWS Lambda thực thi hàm và truy cập S3. Trước khi chạy script, hãy đảm bảo bạn đã đặt các biến môi trường `ROLE_NAME` và `AWS_REGION` trong file `.env` của mình. AWS Lambda sẽ đảm nhận vai trò này khi thực thi hàm, cho phép nó truy cập S3 bucket, như được định nghĩa trong chính sách `AWSLambdaExecute`. Nó cũng sẽ có quyền truy cập CloudWatch Logs cho mục đích ghi nhật ký, giúp bạn giám sát và gỡ lỗi hàm. ```bash #!/bin/bash # Exit immediately if a command exits with a non-zero status set -e # Load environment variables from .env file set -o allexport source .env set +o allexport echo "Environment variables loaded." # Check IAM role... echo "Checking IAM role..." # Check if the role exists if ! aws iam get-role --role-name ${ROLE_NAME} --region ${AWS_REGION} 2>/dev/null; then echo "Creating new IAM role for Lambda with S3 access..." # Fix: Remove space after = and use proper JSON formatting ASSUME_ROLE_POLICY='{ "Version": "2012-10-17", "Statement": [{ "Effect": "Allow", "Principal": { "Service": "lambda.amazonaws.com" }, "Action": "sts:AssumeRole" }] }' # Create the IAM role aws iam create-role \ --role-name ${ROLE_NAME} \ --assume-role-policy-document "${ASSUME_ROLE_POLICY}" \ --region ${AWS_REGION} # Add Lambda execution policy. Provides Put, Get access to S3 and full access to CloudWatch Logs. aws iam attach-role-policy \ --role-name ${ROLE_NAME} \ --policy-arn arn:aws:iam::aws:policy/AWSLambdaExecute \ --region ${AWS_REGION} echo "IAM role created and policy attached." # Wait for role to propagate echo "Waiting for role to propagate..." sleep 20 else echo "IAM role ${ROLE_NAME} already exists. Skipping role creation." fi ``` Để thực thi script này, bạn hãy dùng lệnh sau: `uv run scripts/create_roles.sh` https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/iam_roles_permissions.png Xây dựng hàm AWS Lambda: Bộ não của hệ thống Hàm AWS Lambda là thành phần cốt lõi tự động hóa toàn bộ quá trình xử lý tải lên PDF, tạo embeddings và lưu trữ chúng trong Zilliz Cloud. Hàm này được kích hoạt bởi một sự kiện S3, xử lý PDF đã tải lên và lưu trữ dữ liệu kết quả vào collection Milvus của bạn. **Triển khai Lambda Handler:** Bây giờ bạn có thể tạo file `lambda_function.py` dưới đây và lưu nó vào thư mục `aws_lambda`. File này chứa phần triển khai của hàm AWS Lambda. Trong trường hợp này, hàm AWS Lambda được kích hoạt bởi một sự kiện S3 mỗi khi một file PDF mới được tải lên một S3 bucket. Nó xử lý sự kiện, trích xuất file, tạo embeddings và chèn dữ liệu vào collection Zilliz Cloud. ```python import json import os import boto3 from langchain_community.document_loaders import PyPDFLoader from langchain_openai import OpenAIEmbeddings from langchain_text_splitters import CharacterTextSplitter from pymilvus import MilvusClient # Global variables for reuse across invocations client = None openai_embeddings = None text_splitter = None def init_clients(): """Initialize global clients if not already initialized""" global client, openai_embeddings, text_splitter if client is None: print("Initializing Milvus client...") client = MilvusClient(uri=os.getenv("ZILLIZ_CLOUD_URI"), token=os.getenv("ZILLIZ_TOKEN")) if openai_embeddings is None: print("Initializing OpenAI embeddings...") openai_embeddings = OpenAIEmbeddings(openai_api_key=os.getenv("OPENAI_API_KEY")) if text_splitter is None: print("Initializing text splitter...") text_splitter = CharacterTextSplitter(chunk_size=512, chunk_overlap=100) def lambda_handler(event, context): try: print(f"Received event: {json.dumps(event)}") # Initialize clients init_clients() # Validate event structure if "Records" not in event or not event["Records"]: print("No records found in event") return {"statusCode": 400, "body": json.dumps("No records found in event")} # Get bucket and file info from S3 event record = event["Records"][0] bucket = record["s3"]["bucket"]["name"] key = record["s3"]["object"]["key"] print(f"Processing file {key} from bucket {bucket}") # Verify bucket expected_bucket = os.getenv("PDF_BUCKET_NAME") if bucket != expected_bucket: print(f"Invalid bucket. Expected {expected_bucket}, got {bucket}") return { "statusCode": 400, "body": json.dumps(f"Invalid bucket. Expected {expected_bucket}, got {bucket}"), } # Download PDF local_path = f"/tmp/{os.path.basename(key)}" print(f"Downloading file to {local_path}") s3 = boto3.client("s3") s3.download_file(bucket, key, local_path) # Process PDF print("Loading and splitting PDF...") documents = PyPDFLoader(local_path).load() chunks = text_splitter.split_documents(documents) print(f"Split PDF into {len(chunks)} chunks") # Prepare and insert data print("Generating embeddings and preparing data...") data = [ { "pdf_text": chunk.page_content, "my_vector": openai_embeddings.embed_documents([chunk.page_content])[0], } for chunk in chunks ] print(f"Inserting {len(data)} records into collection {os.getenv('COLLECTION_NAME')}") client.insert(os.getenv("COLLECTION_NAME"), data) # Cleanup os.remove(local_path) print("Processing completed successfully") return {"statusCode": 200, "body": json.dumps(f"Successfully processed {key}")} except Exception as e: print(f"Error processing document: {str(e)}") import traceback print(f"Traceback: {traceback.format_exc()}") return {"statusCode": 500, "body": json.dumps(str(e))} ``` Các tính năng chính của hàm Lambda: * **Xử lý sự kiện S3:** Hàm AWS Lambda được kích hoạt bởi một sự kiện S3 khi một file PDF mới được tải lên S3 bucket được chỉ định. * **Khởi tạo Client:** Hàm khởi tạo client Milvus để lưu trữ embeddings, client OpenAI embeddings và text splitter để chia nhỏ văn bản PDF. * **Xử lý văn bản:** Văn bản PDF được trích xuất bằng `PyPDFLoader`, sau đó được chia thành các đoạn nhỏ hơn để đảm bảo việc tạo embedding đúng cách. * **Tạo và lưu trữ Embeddings:** Các embeddings của OpenAI được tạo cho mỗi đoạn văn bản, và dữ liệu kết quả được chèn vào collection Milvus đã chỉ định trong Zilliz Cloud. * **Xử lý lỗi:** Hàm bao gồm xử lý lỗi để bắt và ghi lại bất kỳ ngoại lệ nào xảy ra trong quá trình xử lý PDF. https://truyentranh.letranglan.top/api/v1/proxy?url=https://i.imgur.com/lambda_s3_flow.png Đóng gói AWS Lambda với Docker: Hộp thần kỳ Khi hàm AWS Lambda đã sẵn sàng, nó cần được “đóng gói” bằng Docker. Vì AWS Lambda hoạt động tốt hơn với `requirements.txt` thay vì `pyproject.toml`, bạn cần tạo một file `requirements.txt` từ file `pyproject.toml` của bạn ở thư mục gốc của dự án với các dependencies sau: * `langchain-community` * `langchain_milvus` * `boto3` * `langchain-openai` * `pypdf` `Dockerfile` dưới đây thiết lập môi trường cho hàm AWS Lambda, bao gồm các dependencies cần thiết và mã hàm. Bạn có thể lưu file này trong thư mục gốc của dự án. ```dockerfile FROM public.ecr.aws/lambda/python:3.12.2025.04.01.18 # Set the working directory to /var/task WORKDIR ${LAMBDA_TASK_ROOT} # Copy requirements first to leverage Docker cache COPY requirements.txt ./ # Install dependencies RUN pip install --no-cache-dir -r requirements.txt # Copy source code COPY aws_lambda/lambda_function.py ./lambda_function.py # Command to run the Lambda handler function CMD [ "lambda_function.lambda_handler" ] ``` Tương tự như việc tạo vai trò IAM, việc tạo repository ECR và Docker image có thể được tự động hóa bằng một shell script. Đảm bảo các biến môi trường tương ứng được đặt trong file `.env`. Lưu script dưới đây vào thư mục `scripts`. ```bash #!/bin/bash # Exit immediately if a command exits with a non-zero status set -e # Load environment variables from .env file set -o allexport source .env set +o allexport echo "Environment variables loaded." # Check if the ECR repository exists, create it if it does not if ! aws ecr describe-repositories --repository-names ${LAMBDA_ECR_REPOSITORY_NAME} --region ${AWS_REGION} 2>/dev/null; then echo "Repository ${LAMBDA_ECR_REPOSITORY_NAME} does not exist. Creating..." aws ecr create-repository --repository-name ${LAMBDA_ECR_REPOSITORY_NAME} --region ${AWS_REGION} echo "Repository ${LAMBDA_ECR_REPOSITORY_NAME} created." else echo "Repository ${LAMBDA_ECR_REPOSITORY_NAME} already exists." fi # Build Docker image # To make your image compatible with Lambda, you must use the --provenance=false option. echo "Building Docker image ${LAMBDA_IMAGE_NAME}..." docker buildx build --platform linux/amd64 --provenance=false -t ${LAMBDA_IMAGE_NAME}:latest . # Authenticate Docker to your Amazon ECR registry echo "Authenticating Docker to ECR..." aws ecr get-login-password --region ${AWS_REGION}
Bạn có bao giờ thấy 'đau đầu' với mớ chi phí điện toán đám mây lộn xộn không? Đừng lo lắng nữa! Giới thiệu người hùng mới của chúng ta: AWS AI Cost Optimizer! Tưởng tượng có một trợ lý siêu thông minh dùng công nghệ AI tạo sinh (generative AI) "đỉnh của chóp" từ AWS Bedrock. Anh bạn này sẽ "soi" từng ngóc ngách chi tiêu của bạn trên đám mây, từ cái nhỏ nhất đến cái lớn nhất. Sau đó, không chỉ tìm ra những chỗ lãng phí đâu nhé, mà còn "mách nước" cho bạn những giải pháp tối ưu cực kỳ thiết thực để cắt giảm chi phí một cách thông minh và hiệu quả nhất. Tiền của bạn sẽ được sử dụng "đúng nơi, đúng chỗ" hơn bao giờ hết! Muốn biết AWS AI Cost Optimizer hoạt động "xịn sò" thế nào? Xem ngay video dưới đây nhé: <video controls src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://www.youtube.com/embed/TCw85U-dmZs'></video> <img src='https://truyentranh.letranglan.top/api/v1/proxy?url=https://d1.awsstatic.com/r2023/images/cloud-cost-management/Cloud-Cost-Management_Feature-Icon_Cost-Optimization.4a4387d8985c5b3d5b0c793f773a98e826b5c00e.png' alt='Tối ưu chi phí đám mây với AI'>.
Tìm hiểu 6 bí kíp quan trọng nhất để xây dựng và quản lý AWS Lambda function hiệu quả, an toàn và tiết kiệm chi phí. Từ bộ nhớ, quyền hạn đến biến môi trường, hãy biến Lambda của bạn thành một "siêu năng lực"!