
우리가 멀티 에이전트 플로우(Multi-Agent Flow)를 LangGraph Cloud에 배포한 방법
요약
GPT Researcher 프로젝트 팀이 LangGraph Cloud를 활용하여 멀티 에이전트 워크플로우를 배포하고, 이를 NextJS 기반의 새로운 프론트엔드와 연결하는 과정을 설명합니다. LangGraph Cloud를 통해 LangGraph의 복잡한 에이전트 협업 구조를 API 서버 형태로 추상화하여 효율적으로 관리할 수 있음을 강조합니다.
핵심 포인트
- GPT Researcher는 RAG 방식에서 LangGraph를 활용한 멀티 에이전트 방식으로 진화했습니다.
- LangGraph Cloud는 LangGraph의 기능을 API 엔드포인트로 추상화하여 Python 서버를 쉽게 배포할 수 있게 돕습니다.
- LangGraph Cloud를 사용하면 작업 트리거 및 그래프 편집을 위한 API를 자동으로 제공받을 수 있습니다.
- NextJS로 구축된 최신 클라이언트를 통해 GPT Researcher의 조사 경험을 개선했습니다.
참고: 이 글은 Fiverr의 Tech Lead인 Elisha Kramer가 작성한 게스트 블로그 포스트입니다. 그는 또한 Assaf Elovic이 이끄는 주요 gpt-researcher GitHub 프로젝트의 주요 기여자 중 한 명입니다.
새로운 LangGraph Cloud 기능을 실험한 후, 우리는 너무나 흥분되어 이에 대해 글을 쓰지 않을 수 없었습니다. 아래에서는 우리가 어떻게 LangGraph Cloud Host를 배포하고 GPT Researcher 프론트엔드(NextJS)에서 이를 쿼리했는지 보여드리겠습니다.
GPT Researcher란 무엇인가요?
GPT Researcher는 다양한 작업에 대해 포괄적인 온라인 조사를 수행하도록 설계된 오픈 소스 자율 에이전트(autonomous agent)입니다. 이 오픈 소스는 지난 1년 동안 13,000개 이상의 스타(stars)와 4,000명 이상의 개발자 커뮤니티를 확보하며 인기가 높아졌습니다.
GPT Researcher는 시간이 흐르면서 진화해 왔으며, 성공적인 RAG(Retrieval-Augmented Generation) 구현으로 시작하여 현재는 인기 있는 LangGraph 프레임워크를 사용하는 멀티 에이전트(multi-agents) 방식을 사용하고 있습니다.
하지만 여전히 빠진 조각이 있었습니다. GPT Researcher는 아직 업계 표준 수준의 프론트엔드 애플리케이션을 갖추지 못했으며, 여전히 단순한 HTML과 CSS로 구축되어 있었습니다. 우리는 최적의 조사 경험을 제공하도록 설계된, NextJS로 구축된 최신 클라이언트를 소개하게 되어 기쁩니다! 여기에서 데모를 확인해 보세요.
LangGraph는 이 그림에서 어떤 역할을 하나요?
문제를 통해 추론할 수 있는 문맥 인식(context-aware) AI 에이전트를 구축하기 시작하면서, 우리는 LangChain 라이브러리와 LangGraph를 발견했습니다.
구체적으로, 우리는 LangGraph의 개념에 매료되었습니다. 즉, AI 에이전트가 다른 에이전트와 협력하고, 각자의 독특한 관점을 제시하며, 서로의 작업을 검토할 수 있는 복잡한 멀티 에이전트 플로우(multi-agent flows)를 구축할 수 있게 해주는 프레임워크입니다.
LangGraph는 그 용도에 매우 적합하다는 것이 밝혀졌습니다! 그리고 우리의 새로운 프론트엔드를 GPT Researcher의 클라우드 기반 버전과 쉽게 연결할 수 있다는 능력은 믿기지 않을 정도로 좋게 들렸습니다.
LangGraph Cloud란 무엇인가요?
LangGraph Cloud Host의 이면에 있는 개념은 GraphQL API 서버의 개념과 매우 유사합니다.
A GraphQL API 서버는:
- 데이터베이스에 대한 액세스를 추상화하는 데 도움을 줄 수 있습니다.
- 서버 언어의 모든 라이브러리를 활용할 수 있습니다.
마찬가지로, LangGraph API 서버는 다음과 같은 역할을 수행할 수 있습니다:
- LangGraph에 대한 액세스를 추상화 (Abstract away) 합니다.
- LangGraph 내에서 사용되는 모든 pip 패키지를 활용 (Leverage) 할 수 있습니다.
본질적으로, 여러분은 LangGraph가 내장된 Python 서버를 배포하는 것입니다. 그리고 이 과정에서 여러 가지 기능들을 무료로 얻게 됩니다. 여기에는 쉬운 작업 트리거(job-triggering) 및 그래프 편집(graph edits)을 가능하게 하기 위해 LangGraph Cloud 호스트에 자동으로 노출되는 API 엔드포인트(API endpoints)들이 포함됩니다.
우리는 무엇을 배포했나요?
저희의 경우, 작업의 대부분은 GPT-Researcher의 창립자인 Assaf가 LangGraph를 활용하여 멀티 에이전트 워크플로우(multi-agent workflow)를 구축했을 때 이루어졌습니다. (이 모험에 대해 더 자세히 알고 싶다면 이전 포스트인 'How to Build the Ultimate AI Automation with Multi-Agent Collaboration'을 읽어보세요.)
해당 멀티 에이전트 플로우(multi-agent flow)가 LangGraph로 구축된 이후, 이는 향후의 쉬운 성과를 위한 발판이 되었습니다. 몇 주 후, Harrison(LangChain의 CEO)이 개입하여 우리가 Assaf가 미리 구축한 LangGraph를 쉽게 배포할 수 있도록 풀 리퀘스트(pull request)를 생성했습니다: 여기 GPT Researcher PR이 있습니다.
이 PR의 묘미는 우리의 GPT-Researcher LangGraph를 API 호출(API Call)을 통해 쉽게 배포, 편집 및 사용자 정의 파라미터(custom parameters)로 트리거할 수 있게 만들었다는 점입니다. 와우! 개발 환경에서 확장 가능한 프로덕션 준비 완료 서비스(production-ready service)로 전환하는 데 단 4개의 파일만 변경되었습니다!
LangGraph API 서버 쿼리하기 (Querying the LangGraph API Server)
앞선 두 단계의 단순함을 완전히 이해하는 데 시간이 좀 걸렸습니다. 멀티 에이전트 LLM 워크플로우를 트리거하는 것이 그렇게 쉬울 리가 없는데... 그렇지 않을까요?
알고 보니, 정말 쉬웠습니다.
Assaf와 Harrison의 코드를 기반으로, 저희가 해야 했던 일은 다음과 같습니다.
1단계: Harrison의 배포 튜토리얼 시청하기
2단계: LangSmith GUI의 “Deployments” 탭을 통해 커스텀 LangGraph 배포하기.
저희의 경우, GPT Researcher 프로젝트의 포크(fork) 버전을 선택하고 GPT Researcher의 multi_agents 디렉토리 내에 있는 langgraph.json 설정 파일(아래 참조)을 지정했습니다.
3단계: LangGraph Cloud 배포에 환경 변수(environment variables) 추가하기.
다음 사항들이면 충분할 것입니다:
위 스크린샷에서 LangGraph Cloud가 저를 위해 "Tracing Project"를 자동으로 생성한다는 점에 주목하십시오.
이는 우리가 MVP 멀티 에이전트 플로우 (multi-agents flow)에서 얻었던 것과 동일한 LangSmith 트레이싱 (tracing) 이점을 얻을 수 있음을 의미합니다. 실제 모습은 다음과 같습니다:
그리고 여러분이 얻게 되는 것은 다음과 같은 강력한 도구입니다:
- 사용자가 백엔드 데이터 흐름 (data flow)을 시각화하고 검사할 수 있도록 지원
- 품질 보증 (Quality assurance) 디버깅 - 즉, 우리 AI 플로우 (AI flows)의 입력 또는 출력을 어디에서 개선할 수 있는지 확인
단계 4: 새로 배포된 LangGraph에 쿼리(Query)하기.
다음은 React 코드 샘플입니다:
import { getHost } from '../../helpers/getHost';
import { Client } from "@langchain/langgraph-sdk";
import { task } from '../../config/task';
export async function startLanggraphResearch(newQuestion, report_source) {
// 새로운 질문으로 태스크 쿼리 업데이트
task.task.query = newQuestion;
task.task.source = report_source;
const host = getHost({purpose: 'langgraph-gui'});
const client = new Client({apiUrl: host});
// 모든 어시스턴트(assistants) 목록 가져오기
const assistants = await client.assistants.search({
metadata: null,
offset: 0,
limit: 10,
});
const agent = assistants[0];
// 새로운 스레드(thread) 시작
const thread = await client.threads.create();
// 스트리밍 실행(streaming run) 시작
const input = task;
const streamResponse = client.runs.stream(
thread["thread_id"],
agent["assistant_id"],
{
input,
},
);
return {streamResponse, host, thread_id: thread["thread_id"]};
}
파일 상단에서 임포트(import)된 task 객체는 우리의 API 요청 (API Request) 객체라고 생각할 수 있습니다. 이는 Assaf의 LangGraph에서 활용된 task.json 파일과 사실상 동일합니다.
getHost 함수는 localhost:8123 (langgraph-cli 서비스를 위한 것)을 반환하거나, 우리가 배포한 LangGraph Cloud 서버의 도메인을 반환합니다.
그게 전부입니다. 위의 코드를 통해 LangGraph 서버에서 실행(run)을 트리거할 수 있으며, 이는 LangSmith 사용자 인터페이스(User Interface)에서 완전히 관찰 가능합니다! 다음은 우리의 멀티 에이전트 플로우(multi-agent flow)가 작동하는 동안 사용자에게 각 작업별 LangGraph 상태(State)를 표시하는 위 코드의 연속 부분입니다:
const langsmithGuiLink =https://smith.langchain.com/studio/thread/${thread_id}?baseUrl=${host}`;`
let previousChunk = null;
for await (const chunk of streamResponse) {
console.log(chunk);
if (chunk.data.report != null && chunk.data.report != "Full report content here") {
setOrderedData((prevOrder) => [...prevOrder, { ...chunk.data, output: chunk.data.report, type: 'report' }]);
setLoading(false);
} else if (previousChunk) {
const differences = findDifferences(previousChunk, chunk);
setOrderedData((prevOrder) => [...prevOrder, { type: 'differences', content: 'differences', output: JSON.stringify(differences) }]);
}
previousChunk = chunk;
}
}
이전 코드 스니펫에서 우리가 client.runs.stream 메서드를 활용했다는 점에 주목하십시오.
이는 LangGraph API 서버가 업데이트를 청크(chunk) 단위로 우리에게 다시 전달한다는 것을 의미합니다. 이러한 청크에는 현재 실행 중인 작업(Job)의 업데이트된 상태나, 배포된 LangGraph 서버의 Python 스크립트에서 발생한 사용자 정의 에러(custom errors)가 포함될 수 있습니다.
우리의 경우, 사용자에게 LangGraph API 작업의 맞춤형 실시간 중계(play-by-play)를 보여주고 싶었기 때문에, 두 JavaScript 객체 간의 차이점을 계산하는 역할을 하는 findDifferences 함수를 추가했습니다.
그래프(Graph)가 보고서를 완성하면 해당 보고서가 사용자에게 표시됩니다.
그래프에서 실시간으로 필드 수정(field edits)이 발생하면, 그래프의 해당 차이점들이 사용자에게 표시됩니다.
요약
이 블로그 포스트에서는 React 및 LangGraph Cloud를 통해 우리의 LangGraph 멀티 에이전트 플로우(multi-agent flows)를 트리거하는 방법을 보여줍니다. 이러한 플로우는 인간의 추론(human reasoning)을 모방하므로 상당히 복잡합니다. 하지만 위에서 살펴본 단계별 안내(walkthrough)에서 입증되었듯이, 우아한 API가 프로세스를 단순화하여 모든 것이 수월하게 제자리를 찾도록 만들어 줍니다.
AI 자동 생성 콘텐츠
본 콘텐츠는 LangChain Blog의 원문을 AI가 자동으로 요약·번역·분석한 것입니다. 원 저작권은 원저작자에게 있으며, 정확한 내용은 반드시 원문을 확인해 주세요.
원문 바로가기