이 코드랩에서는 다음을 구축하는 방법을 배웁니다. 호텔 검색 에이전트 사용 LangChain, 카우치베이스 AI 서비스및 상담원 카탈로그. 또한 아리즈 피닉스 관찰 및 평가를 통해 에이전트의 안정적인 성능을 보장합니다.
이 튜토리얼에서는 실제 데이터를 사용하여 호텔을 검색하고, 편의시설별로 필터링하고, 자연어 쿼리에 답변할 수 있는 완전한 기능을 갖춘 에이전트를 만드는 방법을 안내합니다.
참고: 이 코드랩에 대한 전체 Google 코드랩 노트북을 찾을 수 있습니다. 여기.
카우치베이스 AI 서비스란 무엇인가요?
AI 애플리케이션을 구축하려면 메모리를 위한 벡터 데이터베이스, LLM을 위한 추론 공급자(예: OpenAI 또는 Anthropic), 모델 임베딩을 위한 별도의 인프라 등 여러 서비스를 함께 사용해야 하는 경우가 많습니다.
카우치베이스 AI 서비스 는 운영 데이터, 벡터 검색, AI 모델이 함께 있는 통합 플랫폼을 제공하여 이를 간소화합니다. 다음을 제공합니다:
- LLM 추론 및 임베딩 API: 외부 API 키, 추가 인프라, 데이터 이그레스 없이도 인기 있는 LLM(예: Llama 3)과 임베딩 모델을 Couchbase Capella 내에서 바로 이용할 수 있습니다. 애플리케이션 데이터는 Capella 내부에 유지됩니다. 쿼리, 벡터, 모델 추론은 모두 데이터가 있는 곳에서 이루어집니다. 이를 통해 개인정보 보호 및 규정 준수 요건을 충족하면서 안전하고 지연 시간이 짧은 AI 환경을 구현할 수 있습니다. 따라서 중요한 가치: 민감한 정보를 시스템 외부로 전송하지 않고도 데이터와 AI를 함께 사용할 수 있습니다.
- 통합 플랫폼: 데이터베이스 + 벡터화 + 검색 + 모델
- 통합 벡터 검색: 밀리초 단위의 지연 시간으로 JSON 데이터에서 직접 시맨틱 검색을 수행하세요.
왜 필요한가요?
단순한 챗봇에서 에이전트 워크플로, AI 모델이 자율적으로 도구를 사용하는 경우, 지연 시간, 설정의 복잡성이 병목 현상이 될 수 있습니다. 데이터와 AI 서비스를 함께 배치하면 운영 오버헤드와 지연 시간을 줄일 수 있습니다. 또한, 다음과 같은 도구는 상담원 카탈로그 수백 개의 상담원 프롬프트와 도구를 관리하는 데 도움을 주고 상담원을 위한 기본 제공 로깅 기능을 제공합니다.
전제 조건
시작하기 전에 다음 사항을 확인하세요:
- A 카우치베이스 카펠라 계정으로 이동합니다.
- Python 3.10 이상이 설치되어 있어야 합니다.
- Python 및 Jupyter 노트북에 대한 기본적인 지식이 필요합니다.
카우치베이스 카펠라에서 클러스터 만들기
- 카우치베이스 카펠라에 로그인합니다.
- 새 클러스터를 만들거나 기존 클러스터를 사용합니다. 클러스터는 데이터, 쿼리, 인덱스 및 이벤트 서비스와 함께 최신 버전의 Couchbase Server 8.0을 실행해야 한다는 점에 유의하세요.
- 버킷을 만듭니다.
- 데이터의 범위와 컬렉션을 만듭니다.
1단계: 종속성 설치
필요한 패키지를 설치하는 것부터 시작하겠습니다. 여기에는 카우치 기반 인프라 설정 도우미인 agentc 카탈로그용 CLI와 LangChain 통합 패키지를 지원합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
%pip install -q \ "pydantic>=2.0.0,<3.0.0" \ "python-dotenv>=1.0.0,<2.0.0" \ "pandas>=2.0.0,<3.0.0" \ "nest-asyncio>=1.6.0,<2.0.0" \ "langchain-couchbase>=0.2.4,<0.5.0" \ "langchain-openai>=0.3.11,<0.4.0" \ "arize-phoenix>=11.37.0,<12.0.0" \ "openinference-instrumentation-langchain>=0.1.29,<0.2.0" \ "couchbase-infrastructure" # Install Agent Catalog %pip install agentc==1.0.0 |
2단계: 코드로서의 인프라
UI를 수동으로 클릭하는 대신, 저희는 카우치 기반 인프라 패키지를 사용하여 Capella 환경을 프로그래밍 방식으로 프로비저닝할 수 있습니다. 이를 통해 재현 가능한 설정을 보장합니다.
그러겠습니다:
- 프로젝트 및 클러스터를 만듭니다.
- 임베딩 모델 배포(
엔비디아/라마-3.2-NV-EMBEDQA-1B-V2) 및 LLM(메타/llama3-8b-instruct). - 로드
여행 샘플데이터 세트.
카우치베이스 AI 서비스는 상담원이 사용하는 OpenAI 호환 엔드포인트를 제공합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import os from getpass import getpass from couchbase_infrastructure import CapellaConfig, CapellaClient from couchbase_infrastructure.resources import ( create_project, create_developer_pro_cluster, add_allowed_cidr, load_sample_data, create_database_user, deploy_ai_model, create_ai_api_key, ) # 1. Collect Credentials management_api_key = getpass("Enter your MANAGEMENT_API_KEY: ") organization_id = input("Enter your ORGANIZATION_ID: ") config = CapellaConfig( management_api_key=management_api_key, organization_id=organization_id, project_name="agent-app", cluster_name="agent-app-cluster", db_username="agent_app_user", sample_bucket="travel-sample", # Using Couchbase AI Services for models embedding_model_name="nvidia/llama-3.2-nv-embedqa-1b-v2", llm_model_name="meta/llama3-8b-instruct", ) # 2. Provision Cluster client = CapellaClient(config) org_id = client.get_organization_id() project_id = create_project(client, org_id, config.project_name) cluster_id = create_developer_pro_cluster(client, org_id, project_id, config.cluster_name, config) # 3. Network & Data Setup add_allowed_cidr(client, org_id, project_id, cluster_id, "0.0.0.0/0") # Allow all IPs for tutorial load_sample_data(client, org_id, project_id, cluster_id, config.sample_bucket) db_password = create_database_user(client, org_id, project_id, cluster_id, config.db_username, config.sample_bucket) # 4. Deploy AI Models print("Deploying AI Models...") deploy_ai_model(client, org_id, config.embedding_model_name, "agent-hub-embedding-model", "embedding", config) deploy_ai_model(client, org_id, config.llm_model_name, "agent-hub-llm-model", "llm", config) # 5. Generate API Keys api_key = create_ai_api_key(client, org_id, config.ai_model_region) |
보안 루트 인증서를 설정하는 단계를 따르세요. 카우치베이스 카펠라에 보안 연결하려면 TLS 확인을 위한 루트 인증서가 필요합니다. 이 인증서는 ## 📜 루트 인증서 설정 섹션을 확인하세요.
3단계: 상담원 카탈로그 통합
그리고 상담원 카탈로그 는 상담원 기능의 수명 주기를 관리할 수 있는 강력한 도구입니다. Python 파일에 프롬프트와 툴 정의를 하드코딩하는 대신 버전이 지정된 자산으로 관리할 수 있습니다. 개발 팀 전체에서 툴을 중앙 집중화하여 재사용할 수 있습니다. 또한 상담원 추적기를 사용하여 상담원 응답을 검사하고 모니터링할 수 있습니다.
에셋 초기화 및 다운로드
먼저 카탈로그를 초기화하고 미리 정의된 프롬프트와 도구를 다운로드합니다.
|
1 2 3 4 5 6 7 8 |
!git init !agentc init # Download example tools and prompts !mkdir -p prompts tools !wget -O prompts/hotel_search_assistant.yaml https://raw.githubusercontent.com/couchbase-examples/agent-catalog-quickstart/refs/heads/main/notebooks/hotel_search_agent_langchain/prompts/hotel_search_assistant.yaml !wget -O tools/search_vector_database.py https://raw.githubusercontent.com/couchbase-examples/agent-catalog-quickstart/refs/heads/main/notebooks/hotel_search_agent_langchain/tools/search_vector_database.py !wget -O agentcatalog_index.json https://raw.githubusercontent.com/couchbase-examples/agent-catalog-quickstart/refs/heads/main/notebooks/hotel_search_agent_langchain/agentcatalog_index.json |
색인 및 게시
당사는 다음을 사용합니다. agentc 를 사용하여 로컬 파일을 색인하고 Couchbase에 게시합니다. 이렇게 하면 메타데이터가 데이터베이스에 저장되어 에이전트가 런타임에 검색 및 검색할 수 있습니다.
|
1 2 3 4 5 |
# Create local index of tools and prompts !agentc index . # Upload to Couchbase !agentc publish |
4단계: 벡터 스토어 준비하기
에이전트가 의미론적으로 호텔을 검색할 수 있도록 하려면(예: “해변 근처의 아늑한 장소”), 호텔 데이터에 대한 벡터 임베딩을 생성해야 합니다.
위치 및 편의시설에 우선순위를 두고 호텔 데이터를 서식 있는 텍스트 표현으로 변환하는 도우미를 정의합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
from langchain_couchbase.vectorstores import CouchbaseVectorStore def load_hotel_data_to_couchbase(cluster, bucket_name, scope_name, collection_name, embeddings, index_name): # Check if data exists # ... (omitted for brevity) ... # Generate rich text for each hotel # e.g., "Le Clos Fleuri in Giverny, France. Amenities: Free breakfast: Yes..." hotel_texts = get_hotel_texts() # Initialize Vector Store connected to Capella vector_store = CouchbaseVectorStore( cluster=cluster, bucket_name=bucket_name, scope_name=scope_name, collection_name=collection_name, embedding=embeddings, index_name=index_name, ) # Batch upload texts vector_store.add_texts(texts=hotel_texts) print(f"Successfully loaded {len(hotel_texts)} hotel embeddings") |
5단계: LangChain 에이전트 구축
저희는 상담원 카탈로그 를 사용하여 도구 정의와 프롬프트를 동적으로 가져올 수 있습니다. 코드는 일반 코드로 유지되지만 기능(도구)과 성격(프롬프트)은 별도로 관리됩니다. 또한 ReAct 에이전트입니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 |
import agentc from langchain.agents import AgentExecutor, create_react_agent from langchain_core.prompts import PromptTemplate from langchain_core.tools import Tool def create_langchain_agent(self, catalog, span): # 1. Setup AI Services using Capella endpoints embeddings, llm = setup_ai_services(framework="langchain") # 2. Discover Tools from Catalog # The catalog.find() method searches your published catalog tool_search = catalog.find("tool", name="search_vector_database") tools = [ Tool( name=tool_search.meta.name, description=tool_search.meta.description, func=tool_search.func, # The actual python function ), ] # 3. Discover Prompt from Catalog hotel_prompt = catalog.find("prompt", name="hotel_search_assistant") # 4. Construct the Prompt Template custom_prompt = PromptTemplate( template=hotel_prompt.content.strip(), input_variables=["input", "agent_scratchpad"], partial_variables={ "tools": "\n".join([f"{tool.name}: {tool.description}" for tool in tools]), "tool_names": ", ".join([tool.name for tool in tools]), }, ) # 5. Create the ReAct Agent agent = create_react_agent(llm, tools, custom_prompt) agent_executor = AgentExecutor( agent=agent, tools=tools, verbose=True, handle_parsing_errors=True, # Auto-correct formatting errors max_iterations=5, return_intermediate_steps=True, ) return agent_executor |
6단계: 에이전트 실행
에이전트가 초기화되면 복잡한 쿼리를 수행할 수 있습니다. 에이전트가 수행합니다:
- 사용자 입력을 받습니다.
- 사용해야 한다고 결정합니다.
검색_벡터_데이터베이스도구. - 카펠라를 대상으로 검색을 실행합니다.
- 결과를 자연어 응답으로 합성합니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 |
# Initialize Agent Catalog catalog = agentc.catalog.Catalog() span = catalog.Span(name="Hotel Support Agent", blacklist=set()) # Create the agent agent_executor = couchbase_client.create_langchain_agent(catalog, span) # Run a query query = "Find hotels in Giverny with free breakfast" response = agent_executor.invoke({"input": query}) print(f"User: {query}") print(f"Agent: {response['output']}") |
출력 예시:
상담원: 지베르니에서 무료 조식을 제공하는 호텔을 찾았습니다. 르 클로 플뢰리. 이 숙소는 27620 지베르니, 5 rue de la Dîme에 위치해 있습니다. 무료 인터넷과 주차장을 이용하실 수 있습니다.

참고: 아카펠라 모델 서비스에서 모델 출력은 다음과 같습니다. 캐시 (시맨틱 캐시와 표준 캐시 모두). 캐싱 메커니즘은 특히 반복되거나 유사한 쿼리를 처리할 때 RAG의 효율성과 속도를 향상시킵니다. 쿼리가 처음 처리될 때 LLM은 응답을 생성한 다음 이 응답을 Couchbase에 저장합니다. 나중에 유사한 쿼리가 들어올 때 캐시된 응답이 반환됩니다. 캐싱 기간은 Capella 모델 서비스에서 구성할 수 있습니다.
시맨틱 캐싱 추가
캐싱은 사용자가 유사한 쿼리를 여러 번 제출하거나 특정 정보를 자주 요청하는 시나리오에서 특히 유용합니다. 이러한 정보를 캐시에 저장하면 이러한 쿼리에 응답하는 데 걸리는 시간을 크게 단축하여 사용자 경험을 개선할 수 있습니다.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 |
## Semantic Caching Demonstration # This section demonstrates how to enable and use Semantic Caching with Capella Model Services. # Semantic caching stores responses for queries and reuses them for semantically similar future queries, significantly reducing latency and cost. # 1. Setup LLM with Semantic Caching enabled # We pass the "X-cb-cache": "semantic" header to enable the feature print(" Setting up LLM with Semantic Caching enabled...") llm_with_cache = ChatOpenAI( model=os.environ["CAPELLA_API_LLM_MODEL"], base_url=os.environ["CAPELLA_API_LLM_ENDPOINT"] + "/v1" if not os.environ["CAPELLA_API_LLM_ENDPOINT"].endswith("/v1") else os.environ["CAPELLA_API_LLM_ENDPOINT"], api_key=os.environ["CAPELLA_API_LLM_KEY"], temperature=0, # Deterministic for caching default_headers={"X-cb-cache": "semantic"} ) # 2. Define a query and a semantically similar variation query_1 = "What are the best hotels in Paris with a view of the Eiffel Tower?" query_2 = "Recommend some hotels in Paris where I can see the Eiffel Tower." print(f"\n Query 1: {query_1}") print(f" Query 2 (Semantically similar): {query_2}") # 3. First execution (Cache Miss) print("\n Executing Query 1 (First run - Cache MISS)...") start_time = time.time() response_1 = llm_with_cache.invoke(query_1) end_time = time.time() time_1 = end_time - start_time print(f" Time taken: {time_1:.4f} seconds") print(f" Response: {response_1.content[:100]}...") # 4. Second execution (Cache Hit) # The system should recognize query_2 is semantically similar to query_1 and return the cached response print("\n Executing Query 2 (Semantically similar - Cache HIT)...") start_time = time.time() response_2 = llm_with_cache.invoke(query_2) end_time = time.time() time_2 = end_time - start_time print(f" Time taken: {time_2:.4f} seconds") print(f" Response: {response_2.content[:100]}...") |
7단계: 아리즈 피닉스를 통한 관찰 가능성
프로덕션에서는 상담원이 특정 답변을 한 이유를 알아야 합니다. 저희는 아리즈 피닉스 를 사용하여 에이전트의 “사고 과정”(ReAct 체인)을 추적합니다.
또한 평가를 실행하여 다음을 확인할 수도 있습니다. 환각 또는 관련성.
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
import phoenix as px from phoenix.evals import llm_classify, LENIENT_QA_PROMPT_TEMPLATE # 1. Start Phoenix Server session = px.launch_app() # 2. Instrument LangChain from openinference.instrumentation.langchain import LangChainInstrumentor LangChainInstrumentor().instrument() # ... Run your agent queries ... # 3. Evaluate Results # We use an LLM-as-a-judge to grade our agent's responses hotel_qa_results = llm_classify( data=hotel_eval_df[["input", "output", "reference"]], model=evaluator_llm, template=LENIENT_QA_PROMPT_TEMPLATE, rails=["correct", "incorrect"], provide_explanation=True, ) |
Phoenix UI를 검사하면 도구 호출의 정확한 순서를 시각화하고 체인의 각 단계의 지연 시간을 확인할 수 있습니다.
결론
강력한 호텔 검색 에이전트를 성공적으로 구축했습니다. 이 아키텍처를 활용합니다:
- 카우치베이스 AI 서비스: 지연 시간이 짧은 통합 데이터 및 AI 레이어를 제공합니다.
- 상담원 카탈로그: 상담원 도구와 프롬프트를 체계적으로 버전별로 관리할 수 있습니다. 에이전트 카탈로그는 추적 기능도 제공합니다. 사용자는 추적과 함께 SQL++를 사용하고, Couchbase의 성능을 활용하며, 동일한 플랫폼에서 프롬프트 및 도구의 세부 정보를 파악할 수 있습니다.
- LangChain: 유연한 오케스트레이션을 위해.
- 아리즈 피닉스: 관찰 가능성을 위해.
이 접근 방식은 데이터 관리 및 도구 검색이 중요한 과제인 복잡한 멀티 에이전트 시스템을 구축하는 팀에 적합합니다.