AI 에이전트
AI 에이전트는 사용자를 위해 특정 작업을 수행하고, 질문에 답변하고, 프로세스를 자동화하도록 설계되었습니다. 이러한 에이전트는 복잡성이 매우 다양합니다. 단순한 챗봇부터 Copilot, 복잡한 워크플로를 자율적으로 실행할 수 있는 디지털 또는 로봇 시스템 형태의 고급 AI 도우미까지 다양합니다.
이 문서에서는 AI 에이전트에 대한 개념적 개요와 자세한 구현 샘플을 제공합니다.
AI 에이전트란?
독립형 LLM(대규모 언어 모델) 또는 규칙 기반 소프트웨어/하드웨어 시스템과 달리 AI 에이전트에는 다음과 같은 공통 기능이 있습니다.
- 계획: AI 에이전트는 특정 목적을 달성하기 위해 작업을 계획하고 시퀀스를 지정할 수 있습니다. LLM의 통합은 계획 기능에 혁명을 일으켰습니다.
- 도구 사용: 고급 AI 에이전트는 코드 실행, 검색, 계산 기능 등 다양한 도구를 사용하여 작업을 효과적으로 수행할 수 있습니다. AI 에이전트는 함수 호출을 통해 도구를 사용하는 경우가 많습니다.
- 인식: AI 에이전트는 환경의 정보를 인식하고 처리하여 더욱 상호 작용적이고 상황을 인식하도록 할 수 있습니다. 이 정보에는 시각, 청각 및 기타 감각 데이터가 포함됩니다.
- 기억: AI 에이전트는 과거의 상호 작용(도구 사용 및 인식)과 동작(도구 사용 및 계획)을 기억하는 기능이 있습니다. 이러한 환경을 저장하고 향후 작업을 알리기 위해 자기 성찰도 수행합니다. 이 메모리 구성 요소는 시간이 지남에 따라 에이전트 성능의 연속성과 개선을 허용합니다.
참고 항목
AI 에이전트의 컨텍스트에서 메모리라는 용어의 사용법은 컴퓨터 메모리(예: 휘발성, 비휘발성, 영구 메모리) 개념과 다릅니다.
Copilot
Copilot은 AI 에이전트의 일종입니다. 독립적으로 작동하기보다는 사용자와 함께 작업합니다. 완전 자동화된 에이전트와 달리 Copilot은 사용자가 작업을 완료하는 데 도움이 되는 제안 및 권장 사항을 제공합니다.
예를 들어, 사용자가 이메일을 작성할 때 Copilot은 구, 문장 또는 단락을 제안할 수 있습니다. 사용자는 제안을 뒷받침하기 위해 다른 이메일이나 파일에서 관련 정보를 찾도록 Copilot에게 요청할 수도 있습니다(검색 증강 생성 참조). 사용자는 제안된 문구를 수락, 거부 또는 편집할 수 있습니다.
자율 에이전트
자율 에이전트는 보다 독립적으로 작동할 수 있습니다. 이메일 작성을 지원하도록 자율 에이전트를 설정할 때 이를 통해 해당 에이전트가 다음 작업을 수행할 수 있습니다.
- 해당 주제와 관련된 기존 이메일, 채팅, 파일, 기타 내부 및 공용 정보를 참조하세요.
- 수집된 정보에 대해 정성적 분석 또는 정량적 분석을 수행하고 이메일과 관련된 결론을 도출합니다.
- 결론을 바탕으로 전체 이메일을 작성하고 뒷받침하는 증거를 통합합니다.
- 이메일에 관련 파일을 첨부합니다.
- 이메일을 검토하여 포함된 모든 정보가 실제로 정확한지, 어설션이 유효한지 확인합니다.
- 수신자, 참조 및 숨은 참조에 대한 적절한 수신자를 선택하고 이메일 주소를 조회합니다.
- 이메일을 보낼 적절한 시간을 예약합니다.
- 응답이 예상되었으나 받지 못한 경우 후속 조치를 수행합니다.
사용자의 승인 여부에 관계없이 이전 작업을 각각 수행하도록 에이전트를 구성할 수 있습니다.
다중 에이전트 시스템
성능이 뛰어난 자율 에이전트를 달성하기 위한 인기 있는 전략은 다중 에이전트 시스템을 사용하는 것입니다. 다중 에이전트 시스템에서는 디지털 또는 로봇 형태의 여러 자율 에이전트가 상호 작용하거나 함께 작업하여 개인 또는 집단 목표를 달성합니다. 시스템의 에이전트는 독립적으로 작동할 수 있으며 자신의 지식이나 정보를 소유할 수 있습니다. 각 에이전트는 환경을 인식하고, 결정을 내리고, 목표에 따라 작업을 실행할 수 있는 기능도 가질 수 있습니다.
다중 에이전트 시스템에는 다음과 같은 주요 특성이 있습니다.
- 자율: 각 에이전트는 독립적으로 작동합니다. 직접적인 사용자 개입이나 다른 에이전트의 제어 없이 자체적으로 결정을 내립니다.
- 대화형: 에이전트는 서로 통신하고 협업하여 정보를 공유하고 협상하고 작업을 조정합니다. 이러한 상호 작용은 다양한 프로토콜과 통신 채널을 통해 발생할 수 있습니다.
- 목표 지향: 다중 에이전트 시스템의 에이전트는 특정 목적을 달성하도록 설계되었으며, 이는 개별 목표 또는 에이전트 간의 공유 목표에 맞춰 조정될 수 있습니다.
- 분산형: 다중 에이전트 시스템은 단일 제어 지점 없이 분산 방식으로 작동합니다. 이러한 배포는 시스템의 견고성, 확장성 및 리소스 효율성을 향상합니다.
다중 에이전트 시스템은 Copilot 또는 LLM 유추의 단일 인스턴스에 비해 다음과 같은 이점을 제공합니다.
- 동적 추론: 생각의 사슬 또는 생각의 나무 프롬프트 작성과 비교하여 다중 에이전트 시스템은 다양한 추론 경로를 통해 동적 탐색을 허용합니다.
- 정교한 기능: 다중 에이전트 시스템은 철저한 의사 결정 프로세스를 수행하고 여러 에이전트 간에 작업을 분산함으로써 복잡하거나 대규모의 문제를 처리할 수 있습니다.
- 향상된 메모리: 메모리가 있는 다중 에이전트 시스템은 LLM의 컨텍스트 창을 극복하여 더 나은 이해와 정보 보존을 가능하게 합니다.
AI 에이전트 구현
추론과 계획
복잡한 추론과 계획은 고급 자율 에이전트의 특징입니다. 자율 에이전트를 위한 널리 사용되는 프레임워크는 추론 및 계획을 위해 다음 방법론(arXiv 보관 페이지 링크 포함) 중 하나 이상을 통합합니다.
-
모델이 초기 질문에 답하기 전에 후속 질문을 명시적으로 스스로에게 묻고 답하도록 하여 생각의 사슬을 개선합니다.
-
LLM을 사용하여 인터리브 방식으로 추론 추적과 태스크별 작업을 모두 생성합니다. 추론 추적은 모델이 예외 처리와 함께 작업 계획을 유도, 추적 및 업데이트하는 데 도움이 됩니다. 작업을 통해 모델은 기술 자료이나 환경과 같은 외부 원본과 연결하여 추가 정보를 수집할 수 있습니다.
-
전체 작업을 더 작은 하위 작업으로 나누는 계획을 세우고, 그 계획에 따라 하위 작업을 수행합니다. 이 접근 방식은 제로샷 생각의 사슬 프롬프트 작성에서 흔히 나타나는 계산 오류, 단계 누락 오류, 의미 체계 오해 오류를 완화합니다.
-
작업 피드백 신호를 구두로 반영하는 반사 에이전트를 사용합니다. 이러한 에이전트는 후속 평가판에서 더 나은 의사 결정을 유도하기 위해 에피소드 메모리 버퍼에 자체 반사 텍스트를 유지합니다.
프레임워크
다양한 프레임워크와 도구를 사용하면 AI 에이전트의 개발과 배포를 지원할 수 있습니다.
정교한 계획과 메모리가 필요하지 않은 도구 사용 및 인식을 위해 널리 사용되는 LLM 오케스트레이터 프레임워크로는 LangChain, LlamaIndex, 프롬프트 흐름 및 의미 체계 커널이 있습니다.
고급 자율 계획 및 실행 워크플로를 위해 AutoGen은 2022년 후반에 시작된 다중 에이전트 웨이브를 추진했습니다. OpenAI의 도우미 API를 사용하면 사용자가 GPT 에코시스템 내에서 기본적으로 에이전트를 만들 수 있습니다. LangChain 에이전트와 LlamaIndex 에이전트도 비슷한 시기에 등장했습니다.
팁
이 문서 뒷부분에 나오는 구현 샘플에서는 널리 사용되는 프레임워크 중 하나와 통합 에이전트 메모리 시스템을 사용하여 단순한 다중 에이전트 시스템을 빌드하는 방법을 보여 줍니다.
AI 에이전트 메모리 시스템
2022년부터 2024년까지 AI 강화 애플리케이션을 실험하기 위한 일반적인 사례는 다양한 데이터 워크플로 또는 형식에 대해 독립형 데이터베이스 관리 시스템을 사용하는 것입니다. 예를 들어, 캐싱을 위한 메모리 내 데이터베이스, 작동 데이터(추적/활동 로그 및 LLM 대화 기록 포함)를 위한 관계형 데이터베이스, 포함 관리를 위한 순수 벡터 데이터베이스 등을 사용할 수 있습니다.
그러나 독립형 데이터베이스의 복잡한 웹을 사용하는 이러한 사례는 AI 에이전트의 성능을 저하시킬 수 있습니다. 이러한 서로 다른 모든 데이터베이스를 AI 에이전트를 위한 응집력 있고 상호 운용 가능하며 복원력 있는 메모리 시스템에 통합하는 것은 그 자체의 과제입니다.
또한, 자주 사용되는 데이터베이스 서비스 중 다수는 AI 에이전트 시스템에 필요한 속도와 확장성에 적합하지 않습니다. 이러한 데이터베이스의 개별적인 약점은 다중 에이전트 시스템에서 줄어듭니다.
메모리 내 데이터베이스
메모리 내 데이터베이스는 속도 면에서 탁월하지만 AI 에이전트에 필요한 대규모 데이터 지속성 때문에 어려움을 겪을 수 있습니다.
관계형 데이터베이스
관계형 데이터베이스는 에이전트가 처리하는 데이터의 다양한 형식과 유동적 스키마에 적합하지 않습니다. 또한, 관계형 데이터베이스는 프로비전, 분할, 분할을 관리하기 위해 수동 작업은 물론 가동 중지 시간까지 필요합니다.
순수 벡터 데이터베이스
순수 벡터 데이터베이스는 트랜잭션 작업, 실시간 업데이트 및 분산 워크로드에 덜 효과적인 경향이 있습니다. 요즘 인기 있는 순수 벡터 데이터베이스의 일반적인 제공 사항:
- 읽기 및 쓰기가 보장되지 않습니다.
- 제한된 수집 처리량.
- 낮은 가용성(99.9% 미만 또는 연간 9시간 이상의 중단)
- 단일 일관성 수준(최종).
- 리소스 집약적인 메모리 내 벡터 인덱스
- 다중 테넌트에 대한 제한된 옵션.
- 제한된 보안.
강력한 AI 에이전트 메모리 시스템의 특성
효율적인 데이터베이스 관리 시스템이 소프트웨어 애플리케이션의 성능에 중요한 것처럼 LLM 기반 에이전트에 유추를 안내하는 관련 있고 유용한 정보를 제공하는 것도 중요합니다. 강력한 메모리 시스템을 통해 에이전트가 유추 시 검색할 수 있는 다양한 종류의 정보를 구성하고 저장할 수 있습니다.
현재 LLM 기반 애플리케이션은 기본 의미 체계 검색 또는 벡터 검색을 사용하여 구절이나 문서를 검색하는 검색 증강 생성을 사용하는 경우가 많습니다. 벡터 검색은 일반 정보를 찾는 데 유용할 수 있습니다. 그러나 벡터 검색은 특정 작업이나 영역과 관련된 특정 컨텍스트, 구조 또는 관계를 캡처하지 못할 수도 있습니다.
예를 들어, 작업이 코드를 작성하는 것이라면 벡터 검색은 일관되고 올바른 코드를 생성하는 데 중요한 구문 트리, 파일 시스템 레이아웃, 코드 요약 또는 API 서명을 검색하지 못할 수 있습니다. 마찬가지로, 작업이 표 형식 데이터로 작업하는 경우 벡터 검색은 데이터 쿼리 또는 분석에 유용한 스키마, 외래 키, 저장 프로시저 또는 보고서를 쿼리하지 못할 수 있습니다.
앞서 설명한 대로 독립형 메모리 내, 관계형 및 벡터 데이터베이스의 웹을 함께 엮는 것은 다양한 데이터 형식에 대한 최적의 솔루션이 아닙니다. 이 방식은 프로토타입 에이전트 시스템에 적합할 수 있습니다. 그러나 고급 자율 에이전트의 성능을 저하시킬 수 있는 복잡성과 성능 병목 현상이 추가됩니다.
견고한 메모리 시스템은 다음과 같은 특성을 가져야 합니다.
다중 모달
AI 에이전트 메모리 시스템은 다양한 작업과 도메인에 유용할 수 있는 메타데이터, 관계, 엔터티, 요약 또는 기타 형식의 정보를 저장하는 컬렉션을 제공해야 합니다. 이러한 컬렉션은 문서, 테이블, 코드 등 데이터의 구조와 형식을 기반으로 할 수 있습니다. 또는 개념, 연관성 또는 절차 단계와 같은 데이터의 콘텐츠와 의미를 기반으로 할 수도 있습니다.
메모리 시스템은 AI 에이전트에게만 중요한 것이 아닙니다. 또한 이러한 에이전트를 개발, 유지 관리 및 사용하는 사용자에게도 중요합니다.
예를 들어, 사용자는 에이전트의 계획 및 실행 워크플로를 거의 실시간으로 감독해야 할 수 있습니다. 감독하는 동안 사용자는 지침에 개입하거나 에이전트의 대화나 독백을 인라인 편집할 수 있습니다. 사용자는 최종 출력의 유효성을 확인하기 위해 에이전트의 추론과 작업을 감사해야 할 수도 있습니다.
인간/에이전트 상호 작용은 자연 언어 또는 프로그래밍 언어로 이루어질 가능성이 높지만 에이전트는 포함을 통해 "생각", "학습" 및 "기억"합니다. 이러한 차이는 데이터 형식 전반에 걸쳐 메모리 시스템의 일관성에 대한 또 다른 요구 사항을 제시합니다.
작동
메모리 시스템은 사용자 및 환경과의 상호 작용과 관련된 정보를 저장하는 메모리 뱅크를 제공해야 합니다. 이러한 정보에는 채팅 기록, 사용자 기본 설정, 감각 데이터, 의사 결정, 학습된 사실 또는 높은 빈도로 대량으로 업데이트되는 기타 작동 데이터가 포함될 수 있습니다.
이러한 메모리 뱅크는 에이전트가 단기 및 장기 정보를 기억하고, 반복 또는 모순을 피하고, 작업 일관성을 유지하는 데 도움이 될 수 있습니다. 이러한 요구 사항은 에이전트가 관련되지 않은 여러 작업을 연속적으로 수행하는 경우에도 적용되어야 합니다. 고급 사례에서는 에이전트가 서로 다른 분기에서 분기되거나 수렴되는 수많은 분기 계획을 테스트할 수도 있습니다.
공유 가능하지만 분리 가능
거시적 수준에서 메모리 시스템은 모든 에이전트가 액세스할 수 있는 공유 메모리를 제공함으로써 여러 AI 에이전트가 문제에 대해 협업하거나 문제의 다양한 측면을 처리할 수 있도록 해야 합니다. 공유 메모리는 에이전트 간의 정보 교환과 작업 조정을 용이하게 할 수 있습니다.
동시에 메모리 시스템은 에이전트가 프롬프트 및 메모리의 고유한 컬렉션과 같은 자신의 가상 사용자와 특성을 보존할 수 있도록 해야 합니다.
강력한 AI 에이전트 메모리 시스템 빌드
위의 특성을 위해서는 AI 에이전트 메모리 시스템이 확장성이 뛰어나고 신속해야 합니다. 서로 다른 메모리 내, 관계형 및 벡터 데이터베이스(이전 설명 참조)를 힘들여서 함께 연결한 것은 초기 단계의 AI 지원 애플리케이션에 적합할 수 있습니다. 그러나 이 방식은 고급 자율 에이전트의 성능을 저하시킬 수 있는 복잡성과 성능 병목 현상을 추가합니다.
모든 독립 실행형 데이터베이스 대신 Azure Cosmos DB는 AI 에이전트 메모리 시스템을 위한 통합 솔루션 역할을 할 수 있습니다. 그 견고성 덕분에 안정성을 높이고 유지 관리 필요성을 낮추면서 OpenAI의 ChatGPT 서비스를 동적으로 크기 조정할 수 있습니다. atom-record-sequence 엔진으로 구동되는 이 서비스는 서버리스 모드를 제공하는 세계 최초의 전 세계적으로 분산된 NoSQL, 관계형 및 벡터 데이터베이스 서비스입니다. Azure Cosmos DB를 기반으로 빌드된 AI 에이전트는 속도, 규모 및 단순성을 제공합니다.
속도
Azure Cosmos DB는 한 자릿수 밀리초의 대기 시간을 제공합니다. 이 기능은 신속한 데이터 액세스 및 관리가 필요한 프로세스에 적합합니다. 이러한 프로세스에는 캐싱(기존 캐싱 및 의미 체계 캐싱, 트랜잭션 및 운영 워크로드 모두)이 포함됩니다.
낮은 대기 시간은 복잡한 추론을 수행하고, 실시간 결정을 내리고, 즉각적인 응답을 제공해야 하는 AI 에이전트에 매우 중요합니다. 또한 이 서비스는 DiskANN 알고리즘을 사용량하여 최소 메모리 사용량으로 정확하고 빠른 벡터 검색을 제공합니다.
확장
Azure Cosmos DB는 글로벌 배포 및 수평적 확장성을 위해 설계되었습니다. 다중 지역 I/O 및 다중 테넌트를 지원합니다.
이 서비스는 메모리 시스템이 원활하게 확장되고 빠르게 증가하는 에이전트 및 관련 데이터를 따라갈 수 있도록 보장합니다. SLA(서비스 수준 계약)의 가용성 보장은 연간 가동 중지 시간이 5분 미만이라는 의미입니다. 이와 대조적으로 순수 벡터 데이터베이스 서비스에는 9시간 이상의 가동 중지 시간이 있습니다. 이러한 가용성은 중요 업무용 워크로드를 위한 견고한 기반을 제공합니다. 동시에 예약된 용량 또는 서버리스와 같은 Azure Cosmos DB의 다양한 서비스 모델은 재정적 비용을 줄이는 데 도움이 될 수 있습니다.
단순함
Azure Cosmos DB는 여러 데이터베이스 기능을 응집력 있는 단일 플랫폼으로 통합하여 데이터 관리 및 아키텍처를 간소화할 수 있습니다.
통합 벡터 데이터베이스 기능은 자연어 또는 프로그래밍 언어로 해당 데이터와 함께 포함을 저장, 인덱싱 및 쿼리할 수 있습니다. 이 기능을 사용하면 데이터 일관성, 규모 및 성능이 향상됩니다.
그 유연성은 메타데이터, 관계, 엔터티, 요약, 채팅 기록, 사용자 기본 설정, 감각 데이터, 의사 결정, 학습된 사실 또는 에이전트 워크플로와 관련된 기타 작동 데이터의 다양한 형식과 유동적 스키마를 지원합니다. 데이터베이스는 스키마나 인덱스 관리 없이 모든 데이터를 자동으로 인덱싱하므로 AI 에이전트가 복잡한 쿼리를 빠르고 효율적으로 수행하는 데 도움이 됩니다.
Azure Cosmos DB는 완전 관리형이므로 크기 조정, 패치, 백업과 같은 데이터베이스 관리 작업의 오버헤드가 제거됩니다. 이러한 오버헤드가 없으면 개발자는 기본 데이터 인프라에 대해 걱정하지 않고 AI 에이전트를 빌드하고 최적화하는 데 집중할 수 있습니다.
고급 기능
Azure Cosmos DB에는 변경 피드와 같은 유용한 기능이 통합되어 있어 데이터 변경 내용을 실시간으로 추적하고 대응할 수 있습니다. 이 기능은 새로운 정보에 즉각적으로 반응해야 하는 AI 에이전트에 유용합니다.
또한 다중 마스터 쓰기에 대한 기본 지원을 통해 고가용성과 복원력을 구현하여 지역적 장애가 발생하는 후에도 AI 에이전트의 지속적인 작동을 보장할 수 있습니다.
사용 가능한 5가지 일관성 수준(강력한 수준에서 최종 수준까지)은 시나리오 요구 사항에 따라 다양한 분산 워크로드를 충족할 수도 있습니다.
팁
두 가지 Azure Cosmos DB API 중에서 선택하여 AI 에이전트 메모리 시스템을 빌드할 수 있습니다.
- 99.999% 가용성을 보장하고 세 가지 벡터 검색 알고리즘(IVF, HNSW 및 DiskANN)을 제공하는 Azure Cosmos DB for NoSQL
- 99.995% 가용성을 보장하고 두 가지 벡터 검색 알고리즘(IVF 및 HNSW)을 제공하는 vCore 기반 Azure Cosmos DB for MongoDB(DiskANN 출시 예정)
이러한 API의 가용성 보장에 대한 자세한 내용은 서비스 SLA를 참조하세요.
구현 샘플
이 섹션에서는 크루즈 노선의 여행 애플리케이션에서 여행자 문의 및 예약을 처리하기 위한 자율 에이전트의 구현을 살펴봅니다.
챗봇은 오랜 개념이지만 AI 에이전트는 사용자의 기본적인 대화를 넘어 자연어를 기반으로 작업을 수행하는 방향으로 발전하고 있습니다. 이러한 작업에는 전통적으로 코딩된 논리가 필요했습니다. 이 구현 샘플의 AI 여행사는 에이전트 계획, 도구 사용 및 인식을 위해 LangChain Agent 프레임워크를 사용합니다.
AI 여행사의 통합 메모리 시스템은 Azure Cosmos DB의 벡터 데이터베이스 및 문서 저장소 기능을 사용하여 여행자 문의를 처리하고 여행 예약을 용이하게 합니다. 이러한 목적으로 Azure Cosmos DB를 사용하면 앞서 설명한 대로 속도, 규모 및 단순성을 보장하는 데 도움이 됩니다.
샘플 에이전트는 Python FastAPI 백 엔드 내에서 작동합니다. React JavaScript 사용자 인터페이스를 통해 사용자 인터페이스를 지원합니다.
필수 구성 요소
- Azure 구독 계정이 없으면 Azure 계정을 만들지 않고도 30일 동안 Azure Cosmos DB를 무료로 사용해 볼 수 있습니다. 평가판에는 신용 카드가 필요하지 않으며 평가판 기간 이후에는 어떠한 약정도 따르지 않습니다.
- OpenAI API 또는 Azure OpenAI Service에 대한 계정입니다.
- Azure Cosmos DB for MongoDB의 vCore 클러스터입니다. 이 빠른 시작에 따라 계정을 만들 수 있습니다.
- Visual Studio Code와 같은 통합 개발 환경.
- 개발 환경에 Python 3.11.4가 설치되어 있습니다.
프로젝트를 다운로드합니다.
모든 코드와 샘플 데이터 세트는 이 GitHub 리포지토리에서 사용할 수 있습니다. 리포지토리에는 다음 폴더가 포함되어 있습니다.
- loader: 이 폴더에는 Azure Cosmos DB에서 샘플 문서 및 벡터 포함을 로드하기 위한 Python 코드가 포함되어 있습니다.
- api: 이 폴더에는 AI 여행사를 호스팅하기 위한 Python FastAPI 프로젝트가 포함되어 있습니다.
- web: 이 폴더에는 React 웹 인터페이스용 코드가 포함되어 있습니다.
Azure Cosmos DB에 여행 문서 로드
GitHub 리포지토리의 loader 디렉터리에 Python 프로젝트가 포함되어 있습니다. 샘플 여행 문서를 Azure Cosmos DB에 로드하기 위한 것입니다.
환경 설정
다음 명령을 실행하여 loader 디렉터리에 Python 가상 환경을 설정합니다.
python -m venv venv
환경을 활성화하고 loader 디렉터리에 종속성을 설치합니다.
venv\Scripts\activate
python -m pip install -r requirements.txt
loader 디렉터리에 .env라는 파일을 만들어 다음 환경 변수를 저장합니다.
OPENAI_API_KEY="<your OpenAI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
문서 및 벡터 로드
Python 파일 main.py는 Azure Cosmos DB에 데이터를 로드하기 위한 중앙 진입점 역할을 합니다. 이 코드는 선박 및 목적지에 대한 정보를 포함하여 GitHub 리포지토리의 샘플 여행 데이터를 처리합니다. 또한 코드는 선박별, 대상별 여행 일정 패키지를 생성해 여행자가 AI 에이전트를 이용해 예약할 수 있도록 합니다. CosmosDBLoader 도구는 Azure Cosmos DB 인스턴스에서 컬렉션, 벡터 포함 및 인덱스를 만드는 일을 담당합니다.
main.py의 콘텐츠는 다음과 같습니다.
from cosmosdbloader import CosmosDBLoader
from itinerarybuilder import ItineraryBuilder
import json
cosmosdb_loader = CosmosDBLoader(DB_Name='travel')
#read in ship data
with open('documents/ships.json') as file:
ship_json = json.load(file)
#read in destination data
with open('documents/destinations.json') as file:
destinations_json = json.load(file)
builder = ItineraryBuilder(ship_json['ships'],destinations_json['destinations'])
# Create five itinerary packages
itinerary = builder.build(5)
# Save itinerary packages to Cosmos DB
cosmosdb_loader.load_data(itinerary,'itinerary')
# Save destinations to Cosmos DB
cosmosdb_loader.load_data(destinations_json['destinations'],'destinations')
# Save ships to Cosmos DB, create vector store
collection = cosmosdb_loader.load_vectors(ship_json['ships'],'ships')
# Add text search index to ship name
collection.create_index([('name', 'text')])
loader 디렉터리에서 다음 명령을 실행하여 문서를 로드하고, 벡터를 로드하고, 인덱스를 만듭니다.
python main.py
main.py의 출력은 다음과 같습니다.
--build itinerary--
--load itinerary--
--load destinations--
--load vectors ships--
Python FastAPI를 사용하여 AI 여행사 빌드
AI 여행사는 Python FastAPI를 통해 백 엔드 API에서 호스트되며, 이는 프런트 엔드 사용자 인터페이스와의 통합을 용이하게 합니다. API 프로젝트는 데이터 레이어, 특히 Azure Cosmos DB의 벡터 및 문서에 대한 LLM 프롬프트에 근거하여 에이전트 요청을 처리합니다.
에이전트는 다양한 도구, 특히 API 서비스 계층에서 제공되는 Python 함수를 사용합니다. 이 문서는 API 코드 내에서 AI 에이전트에 필요한 코드를 중점적으로 다룹니다.
GitHub 리포지토리의 API 프로젝트는 다음과 같이 구성됩니다.
- 데이터 모델링 구성 요소는 Pydantic 모델을 사용합니다.
- 웹 계층 구성 요소는 요청 라우팅 및 통신 관리를 담당합니다.
- 서비스 계층 구성 요소는 기본 비즈니스 논리와 데이터 레이어, LangChain 에이전트 및 에이전트 도구와의 상호 작용을 담당합니다.
- 데이터 레이어 구성 요소는 Azure Cosmos DB for MongoDB 문서 스토리지 및 벡터 검색과 상호 작용하는 역할을 담당합니다.
API 환경 설정
API 개발 및 테스트에는 Python 버전 3.11.4를 사용했습니다.
api 디렉터리에 Python 가상 환경을 설정합니다.
python -m venv venv
환경을 활성화하고 api 디렉터리의 요구 사항 파일을 사용하여 종속성을 설치합니다.
venv\Scripts\activate
python -m pip install -r requirements.txt
환경 변수를 저장할 api 디렉터리에 .env라는 파일을 만듭니다.
OPENAI_API_KEY="<your Open AI key>"
MONGO_CONNECTION_STRING="mongodb+srv:<your connection string from Azure Cosmos DB>"
이제 환경을 구성하고 변수를 설정했으므로 api 디렉터리에서 다음 명령을 실행하여 서버를 시작합니다.
python app.py
FastAPI 서버는 기본적으로 localhost 루프백 127.0.0.1 포트 8000에서 시작됩니다. 다음 로컬 호스트 주소를 사용하여 Swagger 문서에 액세스할 수 있습니다. http://127.0.0.1:8000/docs
AI 에이전트 메모리에 세션 사용
여행사는 진행 중인 대화에서 이전에 제공된 정보를 참조할 수 있어야 합니다. 이 기능은 일반적으로 LLM 컨텍스트에서 기억이라고 합니다.
이 목표를 달성하려면 Azure Cosmos DB 인스턴스에 저장된 채팅 메시지 기록을 사용합니다. 각 채팅 세션의 기록은 세션 ID를 통해 저장되어 현재 대화 세션의 메시지에만 액세스할 수 있습니다. 이러한 필요성은 API에 Get Session
메서드가 존재하는 이유입니다. 이는 채팅 메시지 기록 사용을 설명하기 위해 웹 세션을 관리하는 자리 표시자 방법입니다.
/session/
에 대해 시도를 선택합니다.
{
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
AI 에이전트의 경우 세션을 시뮬레이션하기만 하면 됩니다. 스텁 아웃된 메서드는 메시지 기록을 추적하기 위해 생성된 세션 ID를 반환할 뿐입니다. 실제 구현에서 이 세션은 Azure Cosmos DB에 저장되며 잠재적으로 React localStorage
에 저장됩니다.
web/session.py의 콘텐츠는 다음과 같습니다.
@router.get("/")
def get_session():
return {'session_id':str(uuid.uuid4().hex)}
AI 여행사와 대화 시작
이전 단계에서 가져오는 세션 ID를 사용하여 AI 에이전트와 새 대화를 시작하면 해당 기능의 유효성을 검사할 수 있습니다. "편안한 휴가를 보내고 싶어."라는 구를 제출하여 테스트를 진행합니다.
/agent/agent_chat
에 대해 시도를 선택합니다.
다음 매개 변수 예를 사용합니다.
{
"input": "I want to take a relaxing vacation.",
"session_id": "0505a645526f4d68a3603ef01efaab19"
}
에이전트가 벡터 검색을 통해 사용할 수 있는 가장 편안한 크루즈라고 예상하므로, 초기 실행 결과 Tranquil Breeze Cruise 및 Fantasy Seas Adventure Cruise에 대한 권장 사항이 생성됩니다. 이 문서는 API의 데이터 레이어인 data.mongodb.travel.similarity_search()
에서 호출된 similarity_search_with_score
에 대해 가장 높은 점수를 갖습니다.
유사성 검색 점수는 디버깅 목적으로 API의 출력으로 표시됩니다. 다음은 data.mongodb.travel.similarity_search()
호출 후의 출력입니다.
0.8394561085977978
0.8086545112328692
2
팁
벡터 검색에 대해 문서가 반환되지 않는 경우 필요에 따라 data.mongodb.travel.similarity_search()
에서 similarity_search_with_score
제한 또는 점수 필터 값([doc for doc, score in docs if score >=.78]
)을 수정합니다.
처음으로 agent_chat
를 호출하면 Azure Cosmos DB에 history
라는 새 컬렉션이 만들어져 세션별 대화를 저장합니다. 이 호출을 통해 에이전트는 필요에 따라 저장된 채팅 메시지 기록에 액세스할 수 있습니다. 동일한 매개 변수를 사용하여 agent_chat
를 연속적으로 실행하면 메모리에서 가져오기 때문에 다양한 결과가 생성됩니다.
AI 에이전트 살펴보기
AI 에이전트를 API에 통합할 때 웹 검색 구성 요소는 모든 요청을 시작하는 역할을 담당합니다. 웹 검색 구성 요소 다음에는 검색 서비스가 오고 마지막으로 데이터 구성 요소가 옵니다.
이 특정한 사례에서는 Azure Cosmos DB에 연결하는 MongoDB 데이터 검색을 사용합니다. 계층은 서비스 계층에 있는 AI 에이전트 및 AI 에이전트 도구 코드를 사용하여 모델 구성 요소의 교환을 용이하게 합니다. 이 방식을 사용하면 데이터 원본의 원활한 상호 교환이 가능합니다. 또한 더욱 복잡한 추가 기능이나 도구를 사용하여 AI 에이전트의 기능을 확장합니다.
서비스 계층
서비스 계층은 핵심 비즈니스 논리의 초석을 형성합니다. 이 특정 시나리오에서 서비스 계층은 LangChain 에이전트 코드의 리포지토리로서 중요한 역할을 합니다. 이를 통해 사용자 프롬프트를 Azure Cosmos DB 데이터, 대화 메모리 및 AI 에이전트용 에이전트 함수와 원활하게 통합할 수 있습니다.
서비스 계층은 init.py 파일에서 에이전트 관련 초기화를 처리하기 위해 싱글톤 패턴 모듈을 사용합니다. service/init.py의 콘텐츠는 다음과 같습니다.
from dotenv import load_dotenv
from os import environ
from langchain.globals import set_llm_cache
from langchain_openai import ChatOpenAI
from langchain_mongodb.chat_message_histories import MongoDBChatMessageHistory
from langchain_core.prompts import ChatPromptTemplate, MessagesPlaceholder
from langchain_core.runnables.history import RunnableWithMessageHistory
from langchain.agents import AgentExecutor, create_openai_tools_agent
from service import TravelAgentTools as agent_tools
load_dotenv(override=False)
chat : ChatOpenAI | None=None
agent_with_chat_history : RunnableWithMessageHistory | None=None
def LLM_init():
global chat,agent_with_chat_history
chat = ChatOpenAI(model_name="gpt-3.5-turbo-16k",temperature=0)
tools = [agent_tools.vacation_lookup, agent_tools.itinerary_lookup, agent_tools.book_cruise ]
prompt = ChatPromptTemplate.from_messages(
[
(
"system",
"You are a helpful and friendly travel assistant for a cruise company. Answer travel questions to the best of your ability providing only relevant information. In order to book a cruise you will need to capture the person's name.",
),
MessagesPlaceholder(variable_name="chat_history"),
("user", "Answer should be embedded in html tags. {input}"),
MessagesPlaceholder(variable_name="agent_scratchpad"),
]
)
#Answer should be embedded in HTML tags. Only answer questions related to cruise travel, If you can not answer respond with \"I am here to assist with your travel questions.\".
agent = create_openai_tools_agent(chat, tools, prompt)
agent_executor = AgentExecutor(agent=agent, tools=tools, verbose=True)
agent_with_chat_history = RunnableWithMessageHistory(
agent_executor,
lambda session_id: MongoDBChatMessageHistory( database_name="travel",
collection_name="history",
connection_string=environ.get("MONGO_CONNECTION_STRING"),
session_id=session_id),
input_messages_key="input",
history_messages_key="chat_history",
)
LLM_init()
init.py 파일은 load_dotenv(override=False)
메서드를 사용하여 .env 파일에서 환경 변수 로드를 시작합니다. 그런 다음 에이전트에 대해 agent_with_chat_history
라는 전역 변수가 인스턴스화됩니다. 이 에이전트는 TravelAgent.py에서 사용하도록 만들어졌습니다.
API 웹 계층을 통한 대화를 위해 AI 에이전트를 구성하기 위해 모듈 초기화 중에 LLM_init()
메서드가 호출됩니다. OpenAI chat
개체는 GPT-3.5 모델을 통해 인스턴스화되며 모델 이름 및 온도와 같은 특정 매개 변수를 통합합니다. chat
개체, 도구 목록 및 프롬프트 템플릿이 결합되어 AI 여행사로 작동하는 AgentExecutor
를 생성합니다.
기록이 있는 에이전트 agent_with_chat_history
는 채팅 기록(MongoDBChatMessageHistory
)이 있는 RunnableWithMessageHistory
를 통해 설정됩니다. 이 작업을 통해 Azure Cosmos DB를 통해 전체 대화 기록을 유지할 수 있습니다.
프롬프트
LLM 프롬프트는 처음에 "너는 크루즈 회사의 친절하고 유용한 여행 도우미야."라는 단순한 문으로 시작되었습니다. 그러나 테스트 결과 다음 지침을 포함하면 보다 일관된 결과를 가져올 수 있는 것으로 나타났습니다. "여행 관련 질문에 최선을 다해 답변하고 관련 정보만 제공해 줘. 크루즈를 예약하려면 예약하는 사람의 이름을 캡처해야 해." 결과는 웹 인터페이스의 시각적 매력을 향상시키기 위해 HTML 형식으로 나타납니다.
에이전트 도구
도구는 에이전트가 종종 함수 호출을 통해 세상과 상호 작용하는 데 사용할 수 있는 인터페이스입니다.
에이전트를 만들 때 사용할 수 있는 도구 집합을 제공해야 합니다. @tool
데코레이터는 사용자 지정 도구 정의에 대한 가장 간단한 방식을 제공합니다.
기본적으로 데코레이터는 함수 이름을 도구 이름으로 사용하지만 문자열을 첫 번째 인수로 제공하여 바꿀 수 있습니다. 데코레이터는 함수의 Docstring을 도구 설명으로 사용하므로 Docstring 프로비전이 필요합니다.
service/TravelAgentTools.py의 콘텐츠는 다음과 같습니다.
from langchain_core.tools import tool
from langchain.docstore.document import Document
from data.mongodb import travel
from model.travel import Ship
@tool
def vacation_lookup(input:str) -> list[Document]:
"""find information on vacations and trips"""
ships: list[Ship] = travel.similarity_search(input)
content = ""
for ship in ships:
content += f" Cruise ship {ship.name} description: {ship.description} with amenities {'/n-'.join(ship.amenities)} "
return content
@tool
def itinerary_lookup(ship_name:str) -> str:
"""find ship itinerary, cruise packages and destinations by ship name"""
it = travel.itnerary_search(ship_name)
results = ""
for i in it:
results += f" Cruise Package {i.Name} room prices: {'/n-'.join(i.Rooms)} schedule: {'/n-'.join(i.Schedule)}"
return results
@tool
def book_cruise(package_name:str, passenger_name:str, room: str )-> str:
"""book cruise using package name and passenger name and room """
print(f"Package: {package_name} passenger: {passenger_name} room: {room}")
# LLM defaults empty name to John Doe
if passenger_name == "John Doe":
return "In order to book a cruise I need to know your name."
else:
if room == '':
return "which room would you like to book"
return "Cruise has been booked, ref number is 343242"
TravelAgentTools.py 파일은 세 가지 도구를 정의합니다.
vacation_lookup
은 Azure Cosmos DB에 대해 벡터 검색을 수행합니다. 관련 여행 관련 재질을 검색하기 위해similarity_search
를 사용합니다.itinerary_lookup
은 지정된 크루즈 선박에 대한 크루즈 패키지 세부 정보 및 일정을 검색합니다.book_cruise
는 승객을 위한 크루즈 패키지를 예약했습니다.
LLM 프롬프트에 해당 지침을 포함했더라도 크루즈 패키지 예약을 위한 승객의 이름과 객실 번호를 확보하려면 구체적인 지침("크루즈를 예약하려면 예약하는 사람의 이름을 알아야 해.")이 필요할 수 있습니다.
AI 에이전트
에이전트의 기본 개념은 실행할 작업 시퀀스를 선택하기 위해 언어 모델을 사용하는 것입니다.
service/TravelAgent.py의 콘텐츠는 다음과 같습니다.
from .init import agent_with_chat_history
from model.prompt import PromptResponse
import time
from dotenv import load_dotenv
load_dotenv(override=False)
def agent_chat(input:str, session_id:str)->str:
start_time = time.time()
results=agent_with_chat_history.invoke(
{"input": input},
config={"configurable": {"session_id": session_id}},
)
return PromptResponse(text=results["output"],ResponseSeconds=(time.time() - start_time))
TravelAgent.py 파일은 agent_with_chat_history
및 해당 종속성(도구, 프롬프트 및 LLM)이 init.py 파일에서 초기화되고 구성되므로 간단합니다. 이 파일은 사용자로부터 받은 입력과 대화 메모리용 세션 ID를 사용하여 에이전트를 호출합니다. 이후에는 에이전트의 출력 및 응답 시간과 함께 PromptResponse
(모델/프롬프트)가 반환됩니다.
React 사용자 인터페이스와 AI 에이전트 통합
API를 통한 데이터 로딩 및 AI 에이전트의 접근성이 성공적으로 완료되었으므로 이제 여행 웹 사이트에 대한 웹 사용자 인터페이스(React 사용)를 구축하여 솔루션을 완료할 수 있습니다. React의 기능을 사용하면 AI 에이전트를 여행 사이트에 원활하게 통합하는 방법을 설명하는 데 도움이 됩니다. 이 통합은 문의 및 예약을 위한 대화식 여행 도우미를 통해 사용자 환경을 향상합니다.
React 환경 설정
React 인터페이스를 테스트하기 전에 Node.js와 종속성을 설치합니다.
web 디렉터리에서 다음 명령을 실행하여 프로젝트 종속성을 새로 설치합니다. 설치에는 다소 시간이 걸릴 수 있습니다.
npm ci
다음으로, 환경 변수를 쉽게 저장할 수 있도록 web 디렉터리 내에 .env라는 파일을 만듭니다. 새로 만들어진 .env 파일에 다음 세부 정보를 포함합니다.
REACT_APP_API_HOST=http://127.0.0.1:8000
이제 web 디렉터리에서 다음 명령을 실행하여 React 웹 사용자 인터페이스를 시작합니다.
npm start
이전 명령을 실행하면 React 웹 애플리케이션이 열립니다.
React 웹 인터페이스 살펴보기
GitHub 리포지토리의 웹 프로젝트는 AI 에이전트와의 사용자 인터페이스를 지원하는 간단한 애플리케이션입니다. 에이전트와 대화하는 데 필요한 기본 구성 요소는 TravelAgent.js 및 채팅Layout.js입니다. Main.js 파일은 중앙 모듈 또는 사용자 방문 페이지 역할을 합니다.
기본
주요 구성 요소는 애플리케이션의 중앙 관리자 역할을 합니다. 이는 라우팅을 위한 지정된 진입점 역할을 합니다. 렌더링 함수 내에서 기본 페이지 레이아웃을 묘사하는 JSX 코드를 생성합니다. 이 레이아웃에는 로고 및 링크와 같은 애플리케이션의 자리 표시자 요소, 여행사 구성 요소가 포함된 섹션, 애플리케이션 특성에 대한 샘플 고지 사항이 포함된 바닥글이 포함됩니다.
main.js의 콘텐츠는 다음과 같습니다.
import React, { Component } from 'react'
import { Stack, Link, Paper } from '@mui/material'
import TravelAgent from './TripPlanning/TravelAgent'
import './Main.css'
class Main extends Component {
constructor() {
super()
}
render() {
return (
<div className="Main">
<div className="Main-Header">
<Stack direction="row" spacing={5}>
<img src="/mainlogo.png" alt="Logo" height={'120px'} />
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Ships
</Link>
<Link
href="#"
sx={{ color: 'white', fontWeight: 'bold', fontSize: 18 }}
underline="hover"
>
Destinations
</Link>
</Stack>
</div>
<div className="Main-Body">
<div className="Main-Content">
<Paper elevation={3} sx={{p:1}} >
<Stack
direction="row"
justifyContent="space-evenly"
alignItems="center"
spacing={2}
>
<Link href="#">
<img
src={require('./images/destinations.png')} width={'400px'} />
</Link>
<TravelAgent ></TravelAgent>
<Link href="#">
<img
src={require('./images/ships.png')} width={'400px'} />
</Link>
</Stack>
</Paper>
</div>
</div>
<div className="Main-Footer">
<b>Disclaimer: Sample Application</b>
<br />
Please note that this sample application is provided for demonstration
purposes only and should not be used in production environments
without proper validation and testing.
</div>
</div>
)
}
}
export default Main
여행사
여행사 구성 요소의 목적은 사용자 입력을 캡처하고 응답을 표시하는 것입니다. 이는 주로 세션을 캡처하고 사용자 프롬프트를 FastAPI 서비스에 전달하여 백 엔드 AI 에이전트와의 통합을 관리하는 데 핵심적인 역할을 합니다. 결과 응답은 채팅 레이아웃 구성 요소를 통해 표시하기 위해 배열에 저장됩니다.
TripPlanning/TravelAgent.js의 콘텐츠는 다음과 같습니다.
import React, { useState, useEffect } from 'react'
import { Button, Box, Link, Stack, TextField } from '@mui/material'
import SendIcon from '@mui/icons-material/Send'
import { Dialog, DialogContent } from '@mui/material'
import ChatLayout from './ChatLayout'
import './TravelAgent.css'
export default function TravelAgent() {
const [open, setOpen] = React.useState(false)
const [session, setSession] = useState('')
const [chatPrompt, setChatPrompt] = useState(
'I want to take a relaxing vacation.',
)
const [message, setMessage] = useState([
{
message: 'Hello, how can I assist you today?',
direction: 'left',
bg: '#E7FAEC',
},
])
const handlePrompt = (prompt) => {
setChatPrompt('')
setMessage((message) => [
...message,
{ message: prompt, direction: 'right', bg: '#E7F4FA' },
])
console.log(session)
fetch(process.env.REACT_APP_API_HOST + '/agent/agent_chat', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({ input: prompt, session_id: session }),
})
.then((response) => response.json())
.then((res) => {
setMessage((message) => [
...message,
{ message: res.text, direction: 'left', bg: '#E7FAEC' },
])
})
}
const handleSession = () => {
fetch(process.env.REACT_APP_API_HOST + '/session/')
.then((response) => response.json())
.then((res) => {
setSession(res.session_id)
})
}
const handleClickOpen = () => {
setOpen(true)
}
const handleClose = (value) => {
setOpen(false)
}
useEffect(() => {
if (session === '') handleSession()
}, [])
return (
<Box>
<Dialog onClose={handleClose} open={open} maxWidth="md" fullWidth="true">
<DialogContent>
<Stack>
<Box sx={{ height: '500px' }}>
<div className="AgentArea">
<ChatLayout messages={message} />
</div>
</Box>
<Stack direction="row" spacing={0}>
<TextField
sx={{ width: '80%' }}
variant="outlined"
label="Message"
helperText="Chat with AI Travel Agent"
defaultValue="I want to take a relaxing vacation."
value={chatPrompt}
onChange={(event) => setChatPrompt(event.target.value)}
></TextField>
<Button
variant="contained"
endIcon={<SendIcon />}
sx={{ mb: 3, ml: 3, mt: 1 }}
onClick={(event) => handlePrompt(chatPrompt)}
>
Submit
</Button>
</Stack>
</Stack>
</DialogContent>
</Dialog>
<Link href="#" onClick={() => handleClickOpen()}>
<img src={require('.././images/planvoyage.png')} width={'400px'} />
</Link>
</Box>
)
}
손쉬운 여행 계획을 선택하여 여행 도우미를 엽니다.
채팅 레이아웃
채팅 레이아웃 구성 요소는 채팅 정렬을 감독합니다. 채팅 메시지를 체계적으로 처리하고 message
JSON 개체에 지정된 서식을 구현합니다.
TripPlanning/채팅Layout.py의 콘텐츠는 다음과 같습니다.
import React from 'react'
import { Box, Stack } from '@mui/material'
import parse from 'html-react-parser'
import './ChatLayout.css'
export default function ChatLayout(messages) {
return (
<Stack direction="column" spacing="1">
{messages.messages.map((obj, i = 0) => (
<div className="bubbleContainer" key={i}>
<Box
key={i++}
className="bubble"
sx={{ float: obj.direction, fontSize: '10pt', background: obj.bg }}
>
<div>{parse(obj.message)}</div>
</Box>
</div>
))}
</Stack>
)
}
사용자 프롬프트는 오른쪽에 파란색으로 표시됩니다. AI 여행사의 응답은 왼쪽에 녹색으로 표시됩니다. 다음 이미지에 표시된 것처럼 HTML 형식의 응답이 대화에서 설명됩니다.
AI 에이전트가 프로덕션에 들어갈 준비가 되면 의미 체계 캐싱을 사용하여 쿼리 성능을 80% 개선하고 LLM 유추 및 API 호출 비용을 줄일 수 있습니다. 의미 체계 캐싱을 구현하려면 Stochastic Coder 블로그의 이 게시물을 참조하세요.