JetBrains가 Rust Foundation과 함께 주최한 라이브 시연에 따르면 Rust로 구축된 인공지능 애플리케이션은 점차 초기 실험 단계에서 보다 실용적인 형태로 발전하고 있다. 첫 번째 세션에서는 오픈 소스 라이브러리인 Rig와 이를 사용해 대규모 언어 모델을 기반으로 하며 도구를 호출하고 애플리케이션 내부에서 작업을 수행할 수 있는 에이전트를 구축하는 방법에 초점을 맞췄다.
Developer Advocate인 Orhun Parmaksız는 Rig와 Ratatui를 사용해 구축한 소규모 코딩 에이전트를 시연했으며, 0xPlaygrounds에서 Rig를 주로 관리하는 Stephen Korzeniewski는 프로젝트의 내부 구조와 API를 뒷받침하는 설계 선택을 설명했다.
모델 제공업체를 위한 통합 인터페이스
Rig는 대규모 언어 모델 애플리케이션에서 흔히 발생하는 실질적인 문제를 해결한다. OpenAI, Anthropic, Gemini 및 기타 업체는 일부 서비스가 OpenAI 인터페이스와의 호환성을 제공한다고 밝히더라도 서로 다른 API를 제공한다. Rig는 애플리케이션의 여러 부분을 특정 제공업체의 인터페이스에 직접 연결하는 대신, 모델과 관련된 부분을 다시 작성하지 않고도 제공업체를 교체할 수 있는 통합 Rust 인터페이스를 제공한다.
이 라이브러리는 제공업체 클라이언트, 완성 모델, 에이전트 및 에이전트가 사용할 수 있는 도구를 비롯한 여러 핵심 구성 요소를 중심으로 애플리케이션을 구성한다. 에이전트는 단순한 모델 요청보다 상위 계층으로 작동하며, 입력 텍스트와 출력 텍스트를 주고받는 흐름을 넘어서는 작업을 수행하는 데 필요한 지침, 토큰 제한 및 기능을 추가한다.
에이전트의 지침은 Rig에서 preamble이라고 부르는 항목으로 전달된다. 이는 시스템 프롬프트 역할을 하며 각 요청의 시작 부분에 삽입된다. 모델 제공업체와의 네트워크 통신은 비동기 인터페이스를 통해 관리되며, 비동기 작업의 많은 세부 사항은 라이브러리 내부에 유지되므로 애플리케이션 코드는 필요한 설정과 동작에 집중할 수 있다.
도구를 통해 에이전트가 애플리케이션의 일부가 된다
Rig는 Rust의 Tool trait 인터페이스를 통해 도구를 정의한다. 도구 정의에는 도구의 이름, 입력·출력·오류 유형 및 호출될 때 실행되는 함수가 포함된다. 또한 정의에는 JSON Schema를 사용해 예상되는 인수가 설명되므로 모델은 자신이 제공할 수 있는 데이터에 대한 구조화된 설명을 얻는다.
에이전트에 도구를 등록하면 도구 호출을 지원하는 모델은 도구를 사용할 시점을 결정하고 그 결과를 응답에 통합할 수 있다. 함수는 계산을 수행하거나 데이터베이스를 조회하거나 정보를 검색하거나 다른 서비스에 연결할 수 있다. 도구는 호출 횟수나 캐시된 결과와 같은 상태를 보존하는 컨텍스트를 받을 수도 있다. 이 개념은 에이전트 자체에도 확장되며, 한 에이전트를 다른 에이전트의 도구로 제공해 두 에이전트 사이에서 작업을 위임할 수 있다.
실험적 시연에서 테스트 가능한 애플리케이션으로
Rat Code 프로젝트는 이러한 구성 요소를 Rig와 Ratatui를 사용해 터미널에서 작동하는 소규모 코딩 에이전트로 통합했다. main.rs 파일은 제공업체 클라이언트, 모델 및 에이전트를 초기화하며, 파일 읽기와 쓰기, 셸 명령 실행 기능은 별도로 정의한 뒤 Rig의 도구 인터페이스를 통해 에이전트에 등록한다.
이 애플리케이션은 또한 Rig의 스트리밍 인터페이스를 사용해 응답을 여러 묶음으로 처리하고 모델이 답변을 생성하는 동안 터미널 인터페이스를 업데이트한다. 시연에서는 훅 시스템, 도구 호출에서 복구하는 메커니즘 및 라이브러리가 제공하는 추상화의 설계 선택도 다뤘다. 전체 코드 시연은 녹화본의 27:28부터 시작한다.
RAG, 로컬 모델 및 테스트
Rig는 호스팅된 모델 제공업체에만 국한되지 않는다. 문서와 사용자 질의를 벡터 임베딩으로 변환한 뒤 의미적으로 가장 가까운 문서를 검색해 모델의 컨텍스트에 추가하는 검색 증강 생성 애플리케이션을 지원한다. 이 라이브러리는 데이터베이스와의 통합 및 벡터 저장소를 위한 추상화를 제공하며, 직접 지원되지 않는 데이터베이스를 사용할 때 벡터 저장소 인터페이스를 구현할 수도 있다.
또한 Ollama와 llama.cpp를 통해 로컬 모델을 실행하거나, rig-candle 통합을 사용해 Rust 애플리케이션 내부에서 직접 추론을 수행할 수 있다. 이 옵션을 사용하면 모델 가중치를 애플리케이션에 포함하고 WebAssembly를 통해 지원되는 모델을 실행할 수 있으며, 호스팅된 모델 인터페이스나 별도의 로컬 추론 서버에 의존하지 않아도 된다.
이러한 선택지는 모델과 데이터가 실행되는 위치에서 중요성을 갖지만, 동시에 통합 테스트라는 과제를 제기한다. Rig는 주로 기록 시스템에 의존한다. 실제 제공업체를 대상으로 테스트를 실행하고 HTTP 트래픽을 YAML 파일에 저장한 다음, 모의 서버가 지속적 통합 테스트에서 요청과 응답을 재생한다. 프로젝트에는 약 1,700개의 기록된 상호작용이 포함되어 있으며, 병합 요청이 생성될 때마다 몇 초 안에 이러한 상호작용을 다시 실행한다.
이 테스트는 소프트웨어 통합이 계속 작동하는지 확인하지만, 제공업체가 모델을 업데이트하면 변할 수 있는 모델 출력의 품질은 측정하지 않는다. 따라서 시연에서는 응답 품질에 의존하는 애플리케이션을 위한 별도의 방법으로 실제 모델을 대상으로 예약된 테스트를 언급했다.
편집자 관점: 개발자에게 중요한 점은 무엇인가?
Rig의 실질적인 가치는 단순히 새로운 제공업체를 추가하는 데 있지 않다. 모델 인터페이스의 세부 사항에서 애플리케이션 계층을 분리하는 동시에 도구, 검색 및 로컬 추론을 하나의 Rust 구조 안에 유지하는 데 있다. 이를 통해 제공업체나 실행 방식을 변경하는 비용을 줄일 수 있지만, 모델 간의 행동 차이를 없애지는 않으며 출력 품질 평가 문제를 그 자체로 해결하지도 않는다. 프로젝트의 테스트 메커니즘은 통신이 작동하는지 보장하는 것과 모델이 원하는 결과를 생성하는지 확인하는 것은 서로 다른 문제이며, 후자에는 실제 모델을 대상으로 하는 테스트와 독립적인 평가 기준이 필요하다는 점을 보여준다.