0
0
Lập trình
Thaycacac
Thaycacac thaycacac

Xây dựng AI Agent sẵn sàng sản xuất với LangGraph và Amazon Bedrock

Đăng vào 3 tháng trước

• 11 phút đọc

Giới thiệu

Trong bài viết này, chúng ta sẽ khám phá cách xây dựng một AI agent sẵn sàng sản xuất bằng cách sử dụng LangGraph và triển khai nó thông qua Amazon Bedrock AgentCore. Bài viết này là phần cuối cùng trong chuỗi bài viết về việc sử dụng nhiều framework khác nhau cho AI agents. Chúng ta sẽ đi sâu vào các khía cạnh quan trọng, từ cấu trúc đến triển khai thực tế, với mã nguồn đầy đủ có sẵn trên GitHub.

Nội dung chính

  1. Thiết lập môi trường phát triển
  2. Kiến trúc máy trạng thái LangGraph
  3. Tích hợp tìm kiếm Tavily
  4. Thực thi và lưu trữ kết quả
  5. Triển khai agent
  6. Những lưu ý khi sản xuất
  7. Kết luận

Thiết lập môi trường phát triển

Để bắt đầu, chúng ta cần điều hướng đến dự án LangGraph trong kho lưu trữ của mình:

bash Copy
cd agentcore-multi-framework-examples/agentcore-lang-graph
uv sync
source .venv/bin/activate

Dự án sử dụng hệ sinh thái LangChain với các phụ thuộc sau:

bash Copy
langgraph                # Framework agent dựa trên đồ thị
langchain                # Thư viện LangChain cốt lõi
langchain-aws            # Tích hợp AWS bao gồm Bedrock
langchain-tavily         # Tích hợp tìm kiếm Tavily
bedrock-agentcore        # SDK AgentCore
bedrock-agentcore-starter-toolkit  # Công cụ triển khai

Kiến trúc máy trạng thái LangGraph

LangGraph cung cấp một cách tiếp cận mới để xây dựng agents thông qua trừu tượng StateGraph. Thay vì gọi hàm theo cách thủ tục hay chuỗi các prompt, chúng ta định nghĩa một đồ thị trong đó mỗi nút đại diện cho một bước trong quá trình suy luận của agent.

Định nghĩa trạng thái agent

Cơ sở của bất kỳ agent LangGraph nào là định nghĩa trạng thái của nó. Chúng ta sử dụng TypedDict để xác định thông tin nào sẽ lưu thông qua đồ thị:

python Copy
from typing import Annotated
from typing_extensions import TypedDict
from langgraph.graph.message import add_messages

class State(TypedDict):
    messages: Annotated[list, add_messages]

Annotation add_messages rất đặc biệt - nó cho LangGraph biết rằng cần thêm các tin nhắn mới vào danh sách thay vì thay thế nó. Điều này tạo ra một lịch sử cuộc trò chuyện đang phát triển khi đồ thị thực thi, duy trì ngữ cảnh trong suốt workflow.

Xây dựng đồ thị

Quá trình xây dựng đồ thị theo một mẫu khai báo rõ ràng cho thấy luồng quyết định của agent:

python Copy
from langgraph.graph import StateGraph, START, END
from langgraph.prebuilt import ToolNode, tools_condition

# Khởi tạo đồ thị với loại State của chúng ta
graph_builder = StateGraph(State)

# Cấu hình LLM với các công cụ
llm = init_chat_model(
    "us.anthropic.claude-3-7-sonnet-20250219-v1:0",
    model_provider="bedrock_converse",
)
llm_with_tools = llm.bind_tools(tools)

# Định nghĩa nút chatbot
def chatbot(state: State):
    return {"messages": [llm_with_tools.invoke(state["messages"])]}

# Thêm các nút vào đồ thị
graph_builder.add_node("chatbot", chatbot)
tool_node = ToolNode(tools=[tool])
graph_builder.add_node("tools", tool_node)

Hàm init_chat_model cung cấp một giao diện thống nhất để khởi tạo các mô hình chat từ các nhà cung cấp khác nhau. Bằng cách chỉ định model_provider="bedrock_converse", chúng ta sử dụng API Converse của Amazon Bedrock, cung cấp hành vi nhất quán giữa các mô hình nền tảng khác nhau.

Các cạnh điều kiện và luồng điều khiển

Luồng điều khiển trong LangGraph được xác định thông qua các cạnh của nó:

python Copy
# Thêm cạnh điều kiện từ chatbot
graph_builder.add_conditional_edges(
    "chatbot",
    tools_condition,
    {"tools": "tools", END: END},
)

# Thêm cạnh từ tools quay lại chatbot
graph_builder.add_edge("tools", "chatbot")

# Thêm cạnh từ START đến chatbot
graph_builder.add_edge(START, "chatbot")

# Biên dịch đồ thị
graph = graph_builder.compile()

Hàm tools_condition là một hàm được xây dựng sẵn kiểm tra đầu ra của chatbot. Nếu mô hình gọi một công cụ, nó sẽ điều hướng đến nút tools; nếu không, nó sẽ kết thúc cuộc trò chuyện. Điều này tạo ra một vòng lặp nơi agent có thể thực hiện nhiều lần gọi công cụ trước khi cung cấp một câu trả lời cuối cùng.

Tích hợp tìm kiếm Tavily

Trong triển khai này, chúng ta đã tích hợp Tavily Search như một công cụ chính, cho thấy cách mà các agent LangGraph có thể truy cập thông tin theo thời gian thực:

python Copy
from langchain_tavily import TavilySearch

tool = TavilySearch(max_results=2)
tools = [tool]

Tavily cung cấp một API tìm kiếm tối ưu hóa bằng AI trả về các đoạn thông tin sạch sẽ, liên quan thay vì các trang web đầy đủ. Điều này giảm thiểu độ phức tạp của việc phân tích HTML khi agents cần thông tin hiện tại. Sự tích hợp là rất liền mạch - LangGraph tự động xử lý việc gọi công cụ và kết quả đưa vào luồng cuộc trò chuyện.

Thực thi và lưu trữ kết quả

Tích hợp với AgentCore Runtime cung cấp cơ sở hạ tầng sản xuất cho agent LangGraph. Hãy cùng xem cách mà hàm entrypoint xử lý các yêu cầu và quản lý bộ nhớ.

Hàm Entry Point

python Copy
from bedrock_agentcore import BedrockAgentCoreApp
from bedrock_agentcore.runtime.context import RequestContext

app = BedrockAgentCoreApp()

@app.entrypoint
def invoke(payload: Dict[str, Any], context: Optional[RequestContext] = None) -> Dict[str, Any]:
    """Hàm entrypoint chính với tích hợp bộ nhớ AgentCore."""

    logger.info("Khởi tạo LangGraph bắt đầu")

Decorator @entrypoint đánh dấu hàm này là trình xử lý cho các yêu cầu đến. Hàm nhận:

  • payload: Chứa dữ liệu yêu cầu, bao gồm prompt từ người dùng
  • context: Một đối tượng RequestContext cung cấp quản lý phiên

Nâng cao bộ nhớ trước khi thực thi đồ thị

Trước khi thực thi đồ thị, chúng ta lấy các bộ nhớ liên quan và thêm chúng vào đầu vào:

python Copy
    # Trích xuất tham số với ưu tiên ngữ cảnh cho session_id
    actor_id = payload.get("actor_id", DEFAULT_ACTOR_ID)
    session_id = context.session_id if context and context.session_id else payload.get("session_id", DEFAULT_SESSION_ID)

    prompt = payload.get("prompt", "Không tìm thấy prompt trong đầu vào")

    # Nâng cao prompt với ngữ cảnh bộ nhớ AgentCore
    memory_context = memory_manager.get_memory_context(
        user_input=prompt,
        actor_id=actor_id,
        session_id=session_id
    )
    enhanced_prompt = f"{memory_context}\n\nTin nhắn hiện tại của người dùng: {prompt}" if memory_context else prompt

    # Tạo tin nhắn cho LangGraph
    messages = {"messages": [{"role": "user", "content": enhanced_prompt}]}

Việc lấy ngữ cảnh bộ nhớ sử dụng hai API Bộ nhớ AgentCore:

  1. get_last_k_turns để tải lịch sử cuộc trò chuyện
  2. RetrieveMemories để tìm kiếm các bộ nhớ liên quan

Thực thi đồ thị và lưu trữ kết quả

Sau khi đồ thị xử lý đầu vào đã được nâng cao, chúng ta lưu trữ cuộc trò chuyện và trả về kết quả:

python Copy
try:
    # Gọi LangGraph
    response = graph.invoke(messages)
    response_message = response['messages'][-1].content

    # Lưu trữ cuộc trò chuyện trong bộ nhớ AgentCore
    memory_manager.store_conversation(
        user_input=prompt,  # Lưu trữ prompt gốc, không phải phiên bản đã nâng cao
        response=response_message,
        actor_id=actor_id,
        session_id=session_id
    )

    return {"result": response_message}

Phương thức store_conversation() gọi API create_event, mà:

  • Lưu trữ cuộc trò chuyện gốc
  • Kích hoạt các chiến lược bộ nhớ để trích xuất sở thích, sự thật và tóm tắt
  • Làm cho những hiểu biết này có sẵn cho các lần truy xuất trong tương lai

Chúng ta lưu trữ prompt của người dùng gốc, không phải phiên bản đã nâng cao với ngữ cảnh bộ nhớ. Điều này ngăn chặn việc mở rộng bộ nhớ đệ quy, giữ cho bộ nhớ tập trung vào nội dung cuộc trò chuyện thực tế.

Hàm trả về một từ điển mà AgentCore Runtime tự động tuần tự hóa thành JSON cho phản hồi HTTP.

Triển khai agent

Quá trình triển khai sử dụng cùng một quy trình Công cụ khởi động AgentCore mà chúng ta đã sử dụng trong suốt chuỗi bài viết này, với một số xem xét cụ thể cho LangGraph.

Cấu hình và thử nghiệm địa phương

Đầu tiên, chúng ta cấu hình agent cho AgentCore:

bash Copy
agentcore configure -n langgraphagent -e main.py

Để thử nghiệm địa phương với tìm kiếm Tavily, chúng ta cần cung cấp khóa API:

bash Copy
agentcore launch --local --env TAVILY_API_KEY=<YOUR_TAVILY_API_KEY>

Điều này sẽ khởi động agent trong môi trường container tại địa phương. Thử nghiệm với ngữ cảnh bộ nhớ:

bash Copy
agentcore invoke --local '{"prompt": "Kiến trúc AI đa agent - Còn gì tôi đã nói về trái cây?"}'

Agent sẽ thực hiện một tìm kiếm web để có được thông tin hiện tại về các kiến trúc AI trong khi cũng truy xuất bộ nhớ đã lưu về sở thích trái cây, cho thấy sức mạnh của việc kết hợp dữ liệu theo thời gian thực với ngữ cảnh bền vững.

Triển khai sản xuất

Triển khai lên AWS yêu cầu phải truyền khóa API Tavily dưới dạng biến môi trường:

bash Copy
agentcore launch --env TAVILY_API_KEY=<YOUR_TAVILY_API_KEY>

AgentCore sẽ lưu trữ an toàn khóa API trong AWS Secrets Manager và tiêm nó vào môi trường chức năng Lambda trong thời gian thực thi. Điều này giữ cho thông tin xác thực được bảo vệ, không bao giờ bị lộ trong mã hoặc tệp cấu hình.

Giám sát triển khai:

bash Copy
aws logs tail /aws/bedrock-agentcore/runtimes/<AGENT_ID_ENDPOINT_ID> --follow

Nhật ký có cấu trúc từ cả LangGraph và AgentCore giúp dễ dàng theo dõi luồng thực thi đồ thị và gỡ lỗi bất kỳ vấn đề nào.

Những lưu ý khi sản xuất

Việc chạy các agent LangGraph trong môi trường sản xuất với AgentCore đã dạy tôi một số bài học quan trọng.

Chiến lược quản lý trạng thái

Quản lý trạng thái rõ ràng của LangGraph đòi hỏi phải cân nhắc cẩn thận điều gì cần được duy trì. Trong khi đồ thị duy trì trạng thái trong quá trình thực thi, Bộ nhớ AgentCore xử lý việc duy trì qua các phiên. Tôi thấy tốt nhất là giữ cho trạng thái đồ thị tập trung vào nhiệm vụ hiện tại trong khi sử dụng Bộ nhớ AgentCore cho ngữ cảnh lâu dài.

So sánh giữa phương pháp dựa trên đồ thị và phương pháp truyền thống

Sau khi triển khai agents với nhiều framework khác nhau, tôi nhận thấy rằng cách tiếp cận dựa trên đồ thị của LangGraph hoạt động tốt nhất. Các framework agent truyền thống thường gặp khó khăn với các quy trình phức tạp, nhiều bước mà yêu cầu quay lại hoặc xử lý song song. LangGraph làm cho những mẫu này trở nên tự nhiên và rõ ràng.

Cấu trúc đồ thị cũng giúp việc triển khai các ràng buộc an toàn dễ dàng hơn. Bằng cách kiểm soát các cạnh và thêm các nút xác minh, tôi có thể làm cho các agent tuân theo các quy trình đã được phê duyệt ngay cả khi sử dụng các mô hình nền tảng mạnh mẽ. Điều này rất quan trọng trong các môi trường sản xuất nơi tính khả thi cũng quan trọng như khả năng.

Tuy nhiên, sức mạnh này đi kèm với độ phức tạp. Những agent chỉ hỏi-đáp đơn giản có thể bị thiết kế quá mức dưới dạng đồ thị. Chìa khóa là chọn công cụ phù hợp cho công việc - LangGraph cho các quy trình phức tạp, các framework đơn giản hơn cho các nhiệm vụ đơn giản.

Kết luận

Triển khai LangGraph này hoàn thành hành trình của chúng ta qua năm framework agent khác nhau, tất cả đều kết hợp thông qua Amazon Bedrock AgentCore. Cách tiếp cận dựa trên đồ thị cung cấp những lợi thế độc đáo cho các quy trình phức tạp trong khi vẫn duy trì cùng một cơ sở hạ tầng bộ nhớ và triển khai chất lượng sản xuất mà chúng ta đã sử dụng trong suốt loạt bài viết.

Sự linh hoạt của AgentCore cho phép mỗi framework tận dụng những điểm mạnh của nó trong khi cung cấp xuất sắc về hoạt động nhất quán. Dù bạn đang xây dựng các agent gọi công cụ đơn giản với Strands, hệ thống đa agent với CrewAI, ứng dụng an toàn kiểu với Pydantic AI, các agent tập trung vào dữ liệu với LlamaIndex hay các quy trình phức tạp với LangGraph, AgentCore xử lý các thách thức sản xuất để bạn có thể tập trung vào logic agent.

Kiến trúc bộ nhớ chung mà chúng ta đã sử dụng qua tất cả các framework cho thấy những lợi ích của việc chuẩn hóa. Bằng cách tạo ra một giao diện bộ nhớ chung, chúng ta đã cho phép khả năng di động thực sự - các agent được xây dựng với các framework khác nhau có thể chia sẻ bộ nhớ và thậm chí chuyển giao cuộc trò chuyện cho nhau.

Các bước tiếp theo và hướng phát triển tương lai

Mặc dù loạt bài này tập trung vào Runtime và Bộ nhớ, AgentCore cung cấp các dịch vụ bổ sung để tăng cường triển khai sản xuất. Các khám phá trong tương lai có thể bao gồm việc sử dụng AgentCore Identity cho xác thực và ủy quyền agent đầu vào và đầu ra, triển khai AgentCore Gateways để biến các API và hàm AWS Lambda hiện có thành các máy chủ MCP, hoặc tận dụng AgentCore Monitoring để có sự quan sát nâng cao.

Mã nguồn hoàn chỉnh cho cả năm framework có sẵn trên GitHub. Tôi khuyến khích bạn khám phá các triển khai, thử nghiệm với việc kết hợp các framework khác nhau và xây dựng các agent sẵn sàng sản xuất của riêng bạn.

Hệ sinh thái AI agent đang phát triển nhanh chóng, với các công cụ và mẫu mới liên tục xuất hiện. Điều còn lại là nhu cầu về hạ tầng chất lượng sản xuất có thể thích ứng với những thay đổi này. Amazon Bedrock AgentCore cung cấp nền tảng đó, cho phép bạn thử nghiệm với các công nghệ agent tiên tiến trong khi duy trì triển khai và hoạt động sẵn sàng cho doanh nghiệp.

Cảm ơn bạn đã tham gia cùng tôi trên hành trình đa framework này. Giờ là lúc bạn xây dựng điều gì đó tuyệt vời!

Gợi ý câu hỏi phỏng vấn
Không có dữ liệu

Không có dữ liệu

Bài viết được đề xuất
Bài viết cùng tác giả

Bình luận

Chưa có bình luận nào

Chưa có bình luận nào