Gemini 3 Flash 및 AlloyDB AI로 자율 공급망 구축

1. 개요

'읽는 챗봇'의 시대가 끝나고 있습니다. 에이전트 비전의 시대가 다가오고 있습니다.

이 Codelab에서는 추측하지 않는 AI 시스템을 빌드하는 방법인 결정론적 AI 엔지니어링을 구현합니다. 표준 AI 모델은 복잡한 이미지의 항목 수를 세어 달라는 요청을 받으면 '할루시네이션' (추측)하는 경우가 많습니다. 공급망에서는 추측이 위험합니다. 실제로 15개의 상품이 있는데 AI가 12개로 추측하면 비용이 많이 드는 오류가 발생합니다.

Gemini 3 Flash의 새로운 생각하기, 행동하기, 관찰하기 루프를 활용하여 자율 공급망 에이전트를 빌드합니다. 단순히 살펴보는 것이 아니라 조사합니다.

결정론적 아키텍처

'블라인드' 및 '기억상실증' 시스템으로 시작합니다. 다음과 같이 감각을 하나씩 수동으로 '깨워'야 합니다.

17191a91a9c54146.png

  1. The Eyes (Vision Agent): 코드 실행과 함께 Gemini 3 Flash를 사용 설정합니다. 모델은 숫자를 추측하기 위해 토큰을 예측하는 대신 Python 코드 (OpenCV)를 작성하여 픽셀을 결정적으로 계산합니다.
  2. 메모리 (공급업체 에이전트): ScaNN (확장 가능한 최근접 이웃)을 사용하여 AlloyDB AI를 사용 설정합니다. 이를 통해 상담사는 수백만 개의 옵션 중에서 부품의 정확한 공급업체를 밀리초 만에 불러올 수 있습니다.
  3. 핸드셰이크 (A2A 프로토콜): 표준화된 agent_card.json을 사용하여 에이전트 간 통신을 지원하여 Vision Agent가 Supplier Agent로부터 자율적으로 재고를 주문할 수 있습니다.

빌드할 항목

  • 카메라 피드에서 '시각적 수학'을 실행하는 비전 에이전트
  • 고속 벡터 검색을 위해 AlloyDB ScaNN으로 지원되는 공급업체 에이전트
  • 자율 루프를 시각화하는 실시간 WebSocket 업데이트가 있는 관제탑 프런트엔드

학습할 내용

  • 벡터 임베딩 및 ScaNN 색인을 사용하여 AlloyDB를 설정하는 방법
  • Gemini API를 사용하여 gemini-3-flash-preview로 Agentic Vision을 사용 설정하는 방법
  • AlloyDB에서 <=> (코사인 거리) 연산자를 사용하여 벡터 검색을 구현하는 방법
  • AlloyDB Python 커넥터를 사용하여 에이전트를 AlloyDB에 연결하는 방법
  • 동적 에이전트 검색을 위해 A2A 프로토콜을 사용하는 방법

요구사항

  • 브라우저(Chrome 또는 Firefox 등)
  • 결제가 사용 설정된 Google Cloud 프로젝트.
  • 비전 에이전트용 Gemini API 키 (Google AI Studio에서 무료 등급 사용 가능)

2. 시작하기 전에

프로젝트 만들기

  1. Google Cloud 콘솔의 프로젝트 선택기 페이지에서 Google Cloud 프로젝트를 선택하거나 만듭니다.
  2. Cloud 프로젝트에 결제가 사용 설정되어 있어야 하므로 프로젝트에 결제가 사용 설정되어 있는지 확인하는 방법을 알아보세요.
  1. Google Cloud에서 실행되는 명령줄 환경인 Cloud Shell을 사용합니다. Google Cloud 콘솔 상단에서 Cloud Shell 활성화를 클릭합니다.

Cloud Shell 활성화 버튼 이미지

  1. Cloud Shell에 연결되면 다음 명령어를 사용하여 이미 인증되었는지, 프로젝트가 프로젝트 ID로 설정되었는지 확인합니다.
gcloud auth list

데이터베이스 설정[AlloyDB]

다른 작업에 앞서 데이터베이스를 프로비저닝하겠습니다. 이 작업은 15분 정도 걸리므로 먼저 시작합니다.

  1. 아래 버튼을 클릭하여 Cloud Shell에서 AlloyDB 설정 도구를 엽니다.

  1. 설정을 실행합니다.
Sh run.sh
  1. 웹 미리보기 (눈 아이콘 👁️ → 포트 8080에서 미리보기)를 사용하여 설정 UI를 엽니다.
  2. 프로젝트 ID를 입력하고 리전 (예: us-central1)을 선택한 후 데이터베이스 비밀번호를 만듭니다.

⚠️ 이 비밀번호를 저장하세요. 설정 스크립트에서 요청할 때 필요합니다.

  1. '배포 시작'을 클릭하고 클러스터가 프로비저닝될 때까지 약 15분 정도 기다립니다.

코드 가져오기

AlloyDB가 프로비저닝되는 동안 (또는 완료된 후) Cloud Shell에서 Codelab 저장소를 엽니다.

⚠️ 중요: 버튼을 클릭하면 보안 대화상자가 표시됩니다. '저장소 신뢰' 체크박스를 선택하고 '확인'을 클릭합니다.

또는 수동으로 클론합니다.

git clone https://github.com/MohitBhimrajka/visual-commerce-gemini-3-alloydb.git

cd visual-commerce-gemini-3-alloydb

프로젝트 설정

이 Cloud Shell 터미널에서 프로젝트가 설정되어 있는지 확인합니다.

gcloud config set project <YOUR_PROJECT_ID>

AlloyDB에서 공개 IP 사용 설정

AlloyDB 프로비저닝이 완료되면 Python 커넥터가 Cloud Shell에서 연결할 수 있도록 공개 IP를 사용 설정합니다.

  1. AlloyDB 콘솔로 이동
  2. 클러스터를 클릭하고 기본 인스턴스를 클릭합니다.
  3. 수정을 클릭합니다.
  4. 공개 IP 연결로 스크롤하여 공개 IP 사용 설정을 선택합니다.
  5. 인스턴스 업데이트를 클릭합니다.

💡 참고: AlloyDB Python 커넥터는 인증 및 암호화를 처리하므로 승인된 외부 네트워크를 추가할 필요가 없습니다.

Vertex AI 권한 부여

AlloyDB 서비스 계정에는 삽입을 생성하기 위한 Vertex AI 액세스 권한이 필요합니다. 동일한 Cloud Shell 창에서 다음을 실행합니다.

PROJECT_ID=$(gcloud config get-value project)


gcloud projects add-iam-policy-binding $PROJECT_ID \
  --member="serviceAccount:service-$(gcloud projects describe $PROJECT_ID --format="value(projectNumber)")@gcp-sa-alloydb.iam.gserviceaccount.com" \
  --role="roles/aiplatform.user"

설정 스크립트 실행

이제 설정 스크립트를 실행합니다. AlloyDB 인스턴스가 자동으로 감지됩니다.

sh setup.sh

스크립트 기능:

  • gcloud CLI, 인증, 프로젝트, Python 3을 검증합니다.
  • 필요한 API (AlloyDB, Vertex AI, Compute, Service Networking)를 확인하고 사용 설정합니다.
  • Gemini API 키를 묻는 메시지가 표시됩니다.
  • AlloyDB 인스턴스를 자동 감지하고 리전, 클러스터, 인스턴스 이름을 추출합니다.
  • 데이터베이스 비밀번호를 묻습니다.
  • .env 구성 파일을 생성합니다.
  • Python 종속 항목을 설치합니다.

3. 데이터베이스 설정

애플리케이션의 핵심은 PostgreSQL용 AlloyDB입니다. 강력한 벡터 기능과 ScaNN 색인을 사용하여 거의 실시간 시맨틱 검색을 지원하므로 상담사가 수천 개의 레코드에서 밀리초 단위로 인벤토리 일치 항목을 찾을 수 있습니다.

이 섹션에서는 AlloyDB Studio에서 스키마를 프로비저닝하고, 데이터를 시드하고, 임베딩을 생성합니다.

AlloyDB Studio에 연결

  1. AlloyDB 콘솔에서 AlloyDB 인스턴스로 이동합니다.
  2. 왼쪽 탐색에서 AlloyDB Studio를 클릭합니다.
  3. 다음으로 인증:
  4. 사용자 이름: postgres
  5. 데이터베이스: postgres
  6. 비밀번호: 클러스터 생성 중에 설정한 비밀번호

확장 프로그램 사용 설정

AlloyDB는 벡터 및 AI를 위한 기본 확장 프로그램을 제공합니다. AlloyDB Studio에서 다음 SQL을 실행합니다.

CREATE EXTENSION IF NOT EXISTS google_ml_integration CASCADE;
CREATE EXTENSION IF NOT EXISTS vector;
CREATE EXTENSION IF NOT EXISTS alloydb_scann CASCADE;
  • google_ml_integration: SQL에서 직접 Vertex AI를 호출하는 ai.embedding() 함수를 사용 설정합니다.
  • vector: 768차원 벡터 임베딩을 저장하고 쿼리합니다.
  • alloydb_scann: 초고속 벡터 검색을 위해 Google의 ScaNN 색인을 사용 설정합니다.

인벤토리 테이블 만들기

DROP TABLE IF EXISTS inventory;

CREATE TABLE inventory (
    id SERIAL PRIMARY KEY,
    part_name TEXT NOT NULL,
    supplier_name TEXT NOT NULL,
    description TEXT,
    stock_level INT DEFAULT 0,
    part_embedding vector(768)
);

part_embedding 열에는 text-embedding-005의 768차원 벡터가 저장됩니다. 이것이 시맨틱 검색을 지원합니다.

샘플 데이터 삽입

창고 인벤토리 항목 20개를 삽입합니다.

INSERT INTO inventory (part_name, supplier_name, description, stock_level) VALUES
('Cardboard Shipping Box Large', 'Packaging Solutions Inc', 'Heavy-duty corrugated cardboard shipping container, 24x18x12 inches', 250),
('Warehouse Storage Container', 'Industrial Supply Co', 'Stackable plastic storage bin with snap-lock lid, blue', 180),
('Product Shipping Boxes', 'Acme Packaging', 'Medium corrugated boxes for warehouse storage, 18x14x10 inches', 320),
('Industrial Widget X-9', 'Acme Corp', 'Heavy-duty industrial coupling for pneumatic systems', 50),
('Precision Bolt M4', 'Global Fasteners Inc', 'Stainless steel M4 allen bolt, 20mm length, grade A2-70', 200),
('Hexagonal Nut M6', 'Metro Supply Co', 'Galvanized steel hex nut M6, DIN 934 standard', 150),
('Phillips Head Screw 3x20', 'Acme Corp', 'Zinc-plated Phillips head wood screw, 3mm x 20mm', 500),
('Wooden Dowel 10mm', 'Craft Materials Ltd', 'Hardwood birch dowel rod, 10mm diameter x 300mm length', 80),
('Rubber Gasket Small', 'SealTech Industries', 'Buna-N rubber gasket, 25mm OD x 15mm ID, oil resistant', 120),
('Spring Tension 5kg', 'Mechanical Parts Co', 'Stainless steel compression spring, 5kg load capacity', 60),
('Bearing 6204', 'Bearings Direct', 'Deep groove ball bearing 6204-2RS, 20x47x14mm sealed', 45),
('Warehouse Shelf Boxes', 'Storage Systems Ltd', 'Standardized warehouse inventory boxes, corrugated, bulk pack', 400),
('Inventory Container Units', 'Supply Chain Pros', 'Modular stackable storage units for warehouse racking', 95),
('Aluminum Extrusion Bar', 'MetalWorks International', 'T-slot aluminum extrusion 20x20mm profile, 1 meter length', 110),
('Cable Tie Pack 200mm', 'ElectroParts Depot', 'Nylon cable ties, 200mm x 4.8mm, UV resistant black, pack of 100', 600),
('Hydraulic Hose 1/2 inch', 'FluidPower Systems', 'High-pressure hydraulic hose, 1/2 inch ID, 3000 PSI rated', 35),
('Safety Goggles Clear', 'WorkSafe Equipment Co', 'ANSI Z87.1 rated clear safety goggles, anti-fog coating', 275),
('Packing Tape Industrial', 'Packaging Solutions Inc', 'Heavy-duty polypropylene packing tape, 48mm x 100m, clear', 450),
('Stainless Steel Sheet 1mm', 'MetalWorks International', '304 stainless steel sheet, 1mm thickness, 300x300mm', 70),
('Silicone Sealant Tube', 'SealTech Industries', 'Industrial-grade RTV silicone sealant, 300ml cartridge, grey', 190);

퍼가기 권한 부여

GRANT EXECUTE ON FUNCTION embedding TO postgres;

벡터 임베딩 생성

AlloyDB의 기본 제공 ai.embedding() 함수를 사용하여 SQL에서 직접 Vertex AI의 text-embedding-005 모델을 호출합니다. Python 코드는 필요하지 않습니다.

UPDATE inventory
SET part_embedding = ai.embedding(
    'text-embedding-005',
    part_name || '. ' || description
)::vector
WHERE part_embedding IS NULL;

이렇게 하면 각 부품의 이름과 설명의 시맨틱 의미를 포착하는 768차원 벡터가 생성됩니다. ScaNN 색인은 이를 사용하여 매우 빠른 유사성 검색을 실행합니다. [완료하는 데 약 3~5분 정도 걸립니다.]

ScaNN 색인 만들기

SET scann.allow_blocked_operations = true;

CREATE INDEX IF NOT EXISTS idx_inventory_scann
ON inventory USING scann (part_embedding cosine)
WITH (num_leaves=5, quantizer='sq8');

모든 항목이 작동하는지 확인

SELECT part_name, supplier_name, stock_level,
       (part_embedding IS NOT NULL) as has_embedding
FROM inventory
ORDER BY id;

has_embedding = true인 행이 20개 표시됩니다.

4. 아키텍처 이해

코드를 변경하기 전에 시스템이 어떻게 빌드되는지 알아보겠습니다. 이 아키텍처는 점진적인 '각성' 패턴을 따릅니다.

상담사 스택

Vision Agent (agents/vision-agent/)

  • agent.py - 핵심 Gemini 3 Flash 로직 코드 실행이 사용 설정된 상태로 이미지를 모델에 전송하여 항목을 결정적으로 계산하는 Python (OpenCV)을 작성합니다.
  • agent_executor.py: A2A 프로토콜 요청을 에이전트 로직에 연결합니다.
  • main.py - /.well-known/agent-card.json을 제공하고 요청을 처리하는 Uvicorn A2A 서버입니다.

공급업체 에이전트 (agents/supplier-agent/)

  • inventory.py - AlloyDB Python 커넥터를 통해 AlloyDB에 연결합니다 (인증 프록시 필요 없음). ScaNN 벡터 검색을 실행하는 find_supplier() 함수를 포함합니다.
  • agent_executor.py - A2A 프로토콜을 인벤토리 검색 로직에 연결합니다.
  • main.py - 에이전트 카드와 상태 엔드포인트가 있는 Uvicorn A2A 서버

Control Tower (frontend/)

  • app.py - A2A를 통해 에이전트를 검색하고, 비전 → 검색 → 주문 파이프라인을 오케스트레이션하고, 브라우저로 실시간 업데이트를 스트리밍하는 FastAPI + WebSocket 서버입니다.

A2A 흐름

  • Control Tower는 각 에이전트에서 /.well-known/agent-card.json을 읽습니다.
  • 하드코딩된 URL 없이 기능 (기술, 엔드포인트)을 검색합니다.
  • Vision Agent에 이미지를 전송하여 상품 수와 설명을 가져옵니다.
  • 설명을 삽입 쿼리로 공급업체 에이전트에 전송 → 부분 일치 획득
  • 자율적으로 주문을 처리합니다.

AlloyDB 연결

공급업체 에이전트는 기존 인증 프록시 대신 AlloyDB Python 커넥터를 사용합니다.

from google.cloud.alloydbconnector import Connector

connector = Connector()
conn = connector.connect(
    inst_uri,       # Full instance URI
    "pg8000",       # Driver
    user="postgres",
    password=DB_PASS,
    ip_type="PUBLIC",  # Cloud Shell uses Public IP
)

이렇게 하면 IAM 인증, SSL/TLS, 연결 라우팅이 자동으로 처리됩니다. 나중에 Cloud Run에 배포할 때는 VPC 액세스를 위해 ip_type을 'PRIVATE'로 변경하면 됩니다.

5. 1단계: 메모리 (공급업체 에이전트)

공급업체 에이전트는 AlloyDB ScaNN을 사용하여 수백만 개의 부품을 기억합니다. 현재는 자리표시자 쿼리가 함께 제공됩니다. 이 자리표시자 쿼리는 검색어와 관계없이 첫 번째 행을 반환하는 기억상실증 환자와 같습니다.

감사: 기억상실증

지금 공급업체 에이전트를 쿼리하면 무작위 결과가 반환됩니다. 유사성 개념이 없습니다. 이 문제를 해결해보겠습니다.

공급업체 에이전트 시작

A2A 서버 (main.py)는 inventory.py의 비즈니스 로직에 프로토콜을 연결하는 agent_executor.py에 위임합니다.

pkill -f uvicorn #Kill all uvicorn processes

1단계: 에이전트 디렉터리로 이동

cd agents/supplier-agent

2단계: 종속 항목 설치

pip install -r requirements.txt

3단계: 에이전트 서버 시작하기

uvicorn main:app --host 0.0.0.0 --port 8082 > /dev/null 2>&1 &

> /dev/null 2>&1 &는 백그라운드에서 서버를 실행하고 출력을 억제하여 터미널을 방해하지 않습니다.

4단계: 에이전트가 실행 중인지 확인 (시작 후 2~3초 대기)

curl http://localhost:8082/.well-known/agent-card.json

예상 출력: 에이전트 구성이 포함된 JSON (오류 없이 반환되어야 함)

해결 방법: <=> 연산자 구현

agents/supplier-agent/inventory.py를 열고 60~70행 근처에서 find_supplier() 함수를 찾습니다. 다음과 같은 자리표시자가 표시됩니다.

# TODO: Replace this placeholder query with ScaNN vector search

sql = "SELECT part_name, supplier_name FROM inventory LIMIT 1;"
cursor.execute(sql)

이 두 줄을 다음으로 바꿉니다.

sql = """
SELECT part_name, supplier_name,
       part_embedding <=> %s::vector as distance
FROM inventory
ORDER BY part_embedding <=> %s::vector
LIMIT 1;
"""
cursor.execute(sql, (embedding_str, embedding_str))

기능:

  • <=>는 PostgreSQL의 코사인 거리 연산자입니다.
  • ORDER BY part_embedding <=> %s::vector는 가장 가까운 일치 항목 (거리가 가장 짧음 = 의미가 가장 가까움)을 찾습니다.
  • %s::vector는 임베딩 배열을 PostgreSQL의 벡터 유형으로 변환합니다.
  • ScaNN 색인은 이 쿼리를 자동으로 가속화합니다.

4단계: 파일 저장 (Ctrl+S 또는 Cmd+S)

이제 에이전트가 무작위 결과를 반환하는 대신 시맨틱 검색을 사용합니다.

인증

A2A 검색 및 인벤토리를 테스트합니다.

curl http://localhost:8082/.well-known/agent-card.json

44500cdeeca3cee8.png

python3 -c "
from inventory import find_supplier
import json
vec = [0.1]*768
r = find_supplier(vec)
if r:
    result = {'part': r[0], 'supplier': r[1]}
    if len(r) > 2:
        result['distance'] = float(r[2]) if r[2] else None
    print(json.dumps(result))
else:
    print('No result found')
"

예상: agent-card.json이 에이전트 카드를 반환합니다. Python 스니펫은 시드된 데이터에서 부품과 공급업체를 반환합니다.

6. 2단계: 눈 (비전 에이전트)

데이터베이스에 액세스할 수 있는 동안 Gemini 3 Flash를 사용하여 눈을 깨워 보겠습니다. Vision Agent는 코드 실행을 통해 '시각적 수학'을 실행합니다.

감사: 할루시네이션

표준 멀티모달 모델에 '이 어수선한 이미지에 상자가 몇 개 있어?'라고 물으면 이미지를 정적 스냅샷으로 처리하고 추측합니다.

  • 모델이 '상자가 12개 정도 있습니다.'라고 말합니다.
  • 실제: 상자가 15개 있습니다.
  • 결과: 공급망 실패

해결 방법: 사고-행동-관찰 루프 활성화

모델이 결정적으로 계산할 수 있도록 Python (OpenCV)을 작성할 수 있도록 코드 실행ThinkingConfig를 사용 설정합니다.

  1. agents/vision-agent/agent.py를 엽니다 .
  2. GenerateContentConfig 섹션을 찾습니다 (68~78번째 줄).
  3. thinking_config=types.ThinkingConfig(...) 블록과 tools=[types.Tool(code_execution=...)]을 모두 주석 해제합니다.
  4. 클라이언트는 환경에서 GEMINI_API_KEY를 사용하도록 이미 구성되어 있습니다.

파일: agents/vision-agent/agent.py

config = types.GenerateContentConfig(
    temperature=0,
    # CODELAB STEP 1: Uncomment to enable reasoning
    thinking_config=types.ThinkingConfig(
        thinking_level="MINIMAL",  # Valid: "MINIMAL", "LOW", "MEDIUM", "HIGH"
        include_thoughts=False    # Set to True for debugging
    ),
    # CODELAB STEP 2: Uncomment to enable code execution
    tools=[types.Tool(code_execution=types.ToolCodeExecution)]
)

thinking_level="MINIMAL"인 이유는 무엇인가요?

이 작업 (코드 실행을 통한 항목 수 세기)의 경우 스크립트를 계획하고 개수를 확인하기에 'MINIMAL'이 충분한 근거를 제공합니다. 'HIGH'를 사용하면 결정적 작업의 정확도를 개선하지 않고도 지연 시간이 2~3배 증가합니다. 비용-성능 최적화: 추론 깊이를 작업 복잡도에 맞춥니다.

비용 대비 성능 최적화는 프로덕션 AI 엔지니어링의 핵심 기술입니다. 추론 깊이를 작업 복잡도에 맞추세요.

Vision 에이전트 시작

🔄 경로 확인: 아직 agents/supplier-agent/에 있는 경우 먼저 cd ../..를 사용하여 저장소 루트로 돌아갑니다.

1단계: 비전 에이전트 디렉터리로 이동하기

cd agents/vision-agent

2단계: 종속 항목 설치

pip install -r requirements.txt

3단계: 비전 에이전트 서버 시작하기

uvicorn main:app --host 0.0.0.0 --port 8081 > /dev/null 2>&1 &

> /dev/null 2>&1 &는 백그라운드에서 서버를 실행하고 출력을 억제하여 터미널을 방해하지 않습니다.

인증

A2A 검색 테스트:

curl http://localhost:8081/.well-known/agent-card.json

예상: 에이전트 이름과 기술이 포함된 JSON 8단계에서 Control Tower UI를 사용하여 실제 비전 카운팅을 테스트합니다.

dc9bc53007336472.png

7. 3단계: 핸드셰이크 (A2A 에이전트 카드)

에이전트는 문제를 확인하고 (비전) 공급업체를 알고 있습니다 (메모리). A2A 프로토콜을 사용하면 동적 검색이 가능합니다. 프런트엔드는 카드를 읽어 각 에이전트와 통신하는 방법을 학습합니다.

A2A와 기존 REST API 비교

측면

기존 REST

A2A 프로토콜

엔드포인트 검색

구성의 하드코딩된 URL

/.well-known/agent-card.json을 통한 동적 방식

기능 설명

API 문서 (사람용)

기술 (컴퓨터가 읽을 수 있음)

통합

서비스별 수동 코드

시맨틱 매칭: '인벤토리 검색이 필요해' → 스킬 검색

새 상담사가 추가됨

모든 클라이언트의 구성 업데이트

구성 불필요 - 자동 검색

실제 이점: 기존 마이크로서비스에서는 세 번째 '물류 대행업체'를 추가하는 경우 URL과 API 계약으로 Control Tower의 코드를 업데이트해야 합니다. A2A를 사용하면 Control Tower가 이를 자동으로 검색하고 자연어 기술 설명을 통해 기능을 이해합니다.

이러한 이유로 A2A는 자율 시스템의 아키텍처 패턴인 플러그 앤 플레이 에이전트 구성을 지원합니다.

상담사 카드 만들기

🔄 경로 확인: 여전히 agents/vision-agent/에 있는 경우 먼저 cd ../..를 사용하여 저장소 루트로 돌아갑니다.

에이전트 카드는 이미 agents/supplier-agent/agent_card.json에 포함되어 있습니다. 파일을 열고 다음을 검토합니다.

{
  "name": "Acme Supplier Agent",
  "description": "Autonomous fulfillment for industrial parts via AlloyDB ScaNN.",
  "version": "1.0.0",
  "skills": [{
    "id": "search_inventory",
    "name": "Search Inventory",
    "description": "Searches the warehouse database for semantic matches using AlloyDB ScaNN vector search.",
    "tags": ["inventory", "search", "alloydb"],
    "examples": ["Find stock for Industrial Widget X-9", "Who supplies ball bearings?"]
  }]
}

사용 사례에 맞게 이름, 설명 또는 예시를 자유롭게 맞춤설정하세요.

공급업체 에이전트를 다시 시작하여 카드를 로드합니다.

1단계: 실행 중인 에이전트 중지하기

pkill -f "uvicorn main:app.*8082"

2단계: 에이전트 디렉터리로 이동

cd agents/supplier-agent

3단계: 에이전트 다시 시작하기

uvicorn main:app --host 0.0.0.0 --port 8082 > /dev/null 2>&1 &

> /dev/null 2>&1 &는 백그라운드에서 서버를 실행하고 출력을 억제하여 터미널을 방해하지 않습니다.

4단계: 새 상담사 카드 확인 (시작 후 2~3초 대기)

curl http://localhost:8082/.well-known/agent-card.json

예상 출력: 이름, 설명, 기술이 입력된 JSON

dd352ca2e7e6109a.png

8. 4단계: 관제탑

FastAPI + WebSockets로 Control Tower 프런트엔드를 실행합니다. A2A를 통해 에이전트를 검색하고 실시간 업데이트를 통해 전체 루프를 조정합니다.

모든 서비스 시작

모든 서비스를 시작하는 가장 쉬운 방법:

저장소 루트에 있는지 확인

pwd  # Should end with: visual-commerce-gemini-3-alloydb

그런 다음 다음 단계를 따르세요.

sh run.sh

이 단일 명령어는 다음을 시작합니다.

  • 포트 8081의 Vision Agent
  • 포트 8082의 공급업체 에이전트
  • 포트 8080의 Control Tower

모든 서비스가 초기화될 때까지 약 10초 동안 기다립니다.

시스템 테스트

Control Tower에 액세스:

  1. Cloud Shell 툴바에서 웹 미리보기 버튼 (눈 아이콘 👁️)을 클릭합니다.
  2. '포트 8080에서 미리보기'를 선택합니다.
  3. 새 탭에서 Control Tower 대시보드가 열립니다.

데모 실행:

  1. 오른쪽 상단: 연결 상태 (녹색 '라이브' 점), 데모/자동 모드 전환, 오디오 컨트롤
  2. 센터: 이미지 업로드 및 분석 시각화가 포함된 기본 워크플로 캔버스
  3. 측면 패널 (분석 중에 표시됨): 워크플로 타임라인 (왼쪽), 진행 상황 추적 및 코드 뷰어 (오른쪽)

옵션 1: 빠른 시작 (권장)

  1. 홈페이지에 샘플 이미지가 포함된 '빠른 시작' 섹션이 표시됩니다.
  2. 샘플 이미지를 클릭하여 분석을 자동 시작
  3. 자율 워크플로를 시청합니다 (약 30~45초).

옵션 2: 직접 업로드

  1. 창고/선반 이미지를 드래그 앤 드롭하거나 (PNG, JPG, 최대 10MB) 클릭하여 찾아보기
  2. '자율 워크플로 시작'을 클릭합니다.
  3. 4단계 파이프라인 관찰

결과:

  1. 에이전트 검색: A2A 프로토콜 모달에는 비전 에이전트 및 공급업체 에이전트 카드와 해당 기술 및 엔드포인트가 표시됩니다.
  2. 시각적 분석: Gemini 3 Flash는 Python 코드 (OpenCV)를 생성하고 실행하여 항목을 계산합니다. 진행률 표시줄에 하위 단계가 표시됩니다. 감지된 항목에 오버레이된 경계 상자 결과 배지에 '✓ 코드 검증됨' 또는 '~ 추정됨'이 표시됨
  3. 공급업체 일치: AlloyDB ScaNN 벡터 검색 애니메이션 검색어가 표시됩니다 (예: '산업용 금속 상자'). 결과 카드에 일치하는 부품, 공급업체, 신뢰도 점수가 표시됨
  4. 주문 완료: 주문 ID, 수량, 세부정보가 포함된 영수증 카드

도움말: 프레젠테이션을 위해 각 단계에서 일시중지하려면 데모 모드 (오른쪽 상단)를 사용 설정하세요. AUTO 모드에서는 워크플로가 지속적으로 실행됩니다.

1a031c4fd407a183.png

무슨 일이 일어났나요?

Control Tower는 A2A 프로토콜을 사용하여 /.well-known/agent-card.json을 통해 두 에이전트를 모두 검색하고, 비전 분석 (코드 실행이 포함된 Gemini 3 Flash)을 오케스트레이션하고, 벡터 검색 (AlloyDB ScaNN)을 실행하고, 자율 주문을 했습니다. 이 모든 작업은 실시간 WebSocket 업데이트를 통해 이루어졌습니다. 각 에이전트는 A2A 표준을 통해 기능을 노출하므로 맞춤 SDK 없이 플러그 앤 플레이 구성이 가능합니다. 자세히 알아보기: A2A 프로토콜

문제 해결

경로 관련 오류:

  • 명령어를 실행할 때 '해당 파일 또는 디렉터리가 없음' 오류가 표시됨: 저장소 루트에 있지 않습니다.
# Check where you are
pwd

# If you're lost, navigate to home and back to repo
cd
cd visual-commerce-gemini-3-alloydb

서비스 오류:

  • 'Address already in use': 이전 실행의 프로세스가 아직 활성 상태입니다.
# Kill all services and restart
pkill -f uvicorn
sh run.sh  # Or manually restart individual agents
  • 서비스가 시작되지 않음: 포트가 사용 중인지 확인합니다.
# Check which processes are using the ports
lsof -i :8080  # Control Tower
lsof -i :8081  # Vision Agent
lsof -i :8082  # Supplier Agent
  • AlloyDB에 대한 '연결 거부': AlloyDB 인스턴스에서 공개 IP가 사용 설정되어 있는지 확인합니다.

9. 🎁 보너스: Cloud Run에 배포

선택사항 - 모든 항목이 로컬에서 작동합니다. 하지만 공개 URL로 만든 콘텐츠를 공유하려면 다음 단계를 따르세요.

# From repo root
sh deploy/deploy.sh

발생하는 상황:

  1. .env 구성을 읽습니다.
  2. 배포된 앱에 표시되는 이름을 묻습니다.
  3. 3개의 서비스를 모두 단일 Cloud Run 컨테이너로 배포
  4. AlloyDB 액세스 권한을 위한 IAM 역할을 부여합니다.
  5. 공유 가능한 URL을 출력합니다.

URL을 여는 방문자에게는 다음과 같은 팝업이 표시됩니다.

10. 삭제

요금이 발생하지 않도록 자동 정리 스크립트로 모든 리소스를 삭제합니다.

# From repo root
sh deploy/cleanup.sh

다음 항목이 안전하게 삭제됩니다.

  • AlloyDB 클러스터 (기본 비용 동인)
  • Cloud Run 서비스 (배포된 경우)
  • 연결된 서비스 계정

스크립트에서 삭제하기 전에 확인 메시지를 표시합니다.

11. 참조 및 추가 자료

이 Codelab의 모든 기술적 주장은 공식 Google Cloud 및 Google AI 문서에서 확인되었습니다.

공식 문서

Gemini 3 Flash:

AlloyDB AI 및 ScaNN:

데이터베이스용 MCP 도구 상자 (대체 접근 방식):

가격 정보:

인증된 성능 주장

기능

클레임

소스

ScaNN과 HNSW 비교 (필터링됨)

속도 10배 개선

Google Cloud 블로그 (인증됨)

ScaNN과 HNSW (표준) 비교

4배 더 빠름

Google Cloud 블로그 (인증됨)

ScaNN 메모리 사용량

3~4배 작음

Google Cloud 블로그 (인증됨)

ScaNN 색인 빌드 시간

8배 더 빠름

Google Cloud 블로그 (인증됨)

코드 실행 제한 시간

최대 30초

Google Cloud 문서 (인증됨)

코드 실행 파일 I/O

지원되지 않음

Google Cloud 문서 (인증됨)

온도=0 동작

결정론적 출력

커뮤니티 확인 완료

추가 리소스

에이전트 간 (A2A) 프로토콜:

  • A2A는 에이전트 검색 및 통신을 표준화합니다.
  • /.well-known/agent-card.json에 표시되는 상담사 카드
  • 자율 에이전트 협업을 위한 새로운 표준

ScaNN 연구:

  • 12년간의 Google 연구를 기반으로 함
  • 수십억 규모의 Google 검색, YouTube 지원
  • 정식 버전 출시: 2024년 10월
  • 수백만에서 수십억 개의 벡터에 적합한 첫 번째 PostgreSQL 벡터 색인

12. 챌린지 모드: 에이전트 역량 강화

작동하는 자율 공급망을 구축했습니다. 더 나아가 볼까요? 이러한 챌린지에서는 학습한 패턴을 새로운 문제에 적용합니다.

챌린지 1: 이미지 기반 검색 (멀티모달 임베딩)

현재 흐름: 시각 에이전트가 항목을 계산하고 텍스트 쿼리를 생성하며 공급업체 에이전트가 텍스트를 삽입하고 AlloyDB를 검색합니다.

챌린지: 텍스트를 완전히 무시하고 잘린 이미지를 공급업체 상담사에게 직접 보냅니다.

힌트:

  1. Vision 에이전트의 코드 실행은 선반 이미지에서 개별 항목을 자를 수 있습니다.
  2. Vertex AI의 multimodalembedding@001 모델은 이미지를 직접 삽입할 수 있습니다.
  3. 텍스트 대신 이미지 바이트를 허용하도록 inventory.py 수정
  4. '허용: image/jpeg 또는 text'를 나타내도록 A2A 기술 설명을 업데이트합니다.

중요한 이유: 시각적 검색은 외관이 복잡한 부분 (색상 변화, 손상, 포장 차이)에서 더 정확합니다.

과제 2: 관측 가능성 - 투명성을 통한 신뢰

현재 상태: 시스템은 작동하지만 '내부'를 볼 수 없음

챌린지: AlloyDB의 쿼리 로그를 검사하여 벡터 검색이 실행되고 있음을 증명합니다.

단계:

  • 쿼리 통계는 AlloyDB에서 기본적으로 사용 설정되어 있습니다. 확인하려면 다음을 실행합니다.
gcloud alloydb instances describe INSTANCE_NAME \
  --cluster=CLUSTER_NAME \
  --region=us-central1 \
  --format="value(queryInsightsConfig.queryPlansPerMinute)"
  • UI를 통해 공급업체 검색 실행
  • 실제로 실행된 SQL을 확인합니다.
gcloud logging read \
  'resource.type="alloydb.googleapis.com/Instance" AND textPayload:"ORDER BY part_embedding"' \
  --limit 5 \
  --format=json

예상 출력: 실행 시간이 포함된 정확한 ORDER BY part_embedding <=> $1::vector LIMIT 1 쿼리가 표시됩니다.

중요한 이유: 관측 가능성은 신뢰를 구축합니다. 이해관계자가 '이 에이전트는 어떻게 결정을 내리나요?'라고 물으면 출력뿐만 아니라 쿼리 계획도 보여줄 수 있습니다.

과제 3: 멀티 에이전트 구성

챌린지: 창고 위치와 상품 무게를 기준으로 배송비를 계산하는 세 번째 에이전트 (물류 에이전트)를 추가합니다.

아키텍처:

  • Vision Agent 출력: 상품 수
  • 공급업체 에이전트 출력: 공급업체 위치
  • 물류 에이전트 (신규): 목적지, 무게 입력 → 배송비 + 예상 도착 시간 출력

도움말: A2A 프로토콜을 사용하면 간단합니다. calculate_shipping 기술이 있는 새 에이전트 카드를 만드세요. Control Tower에서 자동으로 검색합니다.

학습 중인 패턴: 이는 에이전트 중심 아키텍처의 핵심입니다. 즉, 작은 구성 가능한 전문가로 빌드된 복잡한 시스템입니다.

13. 결론

생성형 AI에서 에이전트 AI로 전환되었습니다.

개발된 기능:

  • 비전: '추측'을 코드 실행 (API 키를 통한 Gemini 3 Flash)으로 대체했습니다.
  • 메모리: '느린 검색'이 AlloyDB ScaNN (GCP를 통해)으로 대체되었습니다.
  • 조치: 'API 통합'이 A2A 프로토콜로 대체되었습니다.

하이브리드 아키텍처의 이점:

이 Codelab에서는 다음과 같은 하이브리드 접근 방식을 보여주었습니다.

  • Vision Agent: Gemini API (API 키) 사용 - 간단하고 무료 등급 제공, GCP 결제 불필요
  • 공급업체 에이전트: GCP (Vertex AI + AlloyDB) 사용 - 엔터프라이즈급, 규정 준수 지원

이것이 자율 경제의 아키텍처입니다. 코드는 계속 사용할 수 있습니다.

다음 단계