Straico Has Great Models But No Streaming, So I Built a Proxy

개요

Straico API에서 지원하지 않는 스트리밍 응답 및 함수 호출 기능을 보완하기 위해 OpenCode와 Straico API 사이에 위치하는 프록시를 구축했습니다.

주요 내용

* 프록시 아키텍처: Express 서버, 스트리밍 시뮬레이션, 도구 주입 및 파싱, 로깅, 모델 제한 관리, 대화 요약 기능을 포함합니다. BaseProvider 추상 클래스와 StraicoProvider, ProviderFactory를 활용하여 다른 제공자(OpenAI, Anthropic) 추가를 염두에 둔 설계를 적용했습니다.
* 스트리밍 시뮬레이션: Straico의 일괄 응답을 SSE(Server-Sent Events) 청크로 분할하여 스트리밍처럼 보이게 합니다. 'none' 모드는 전체 응답을 한 번에 전송하며, 'smart' 모드는 줄 바꿈, 공백, 마크다운 구분자 등을 고려하여 안전한 경계에서 분할합니다.
* 함수 호출 (프롬프트 주입): Straico API에 함수 호출 기능이 없어, 시스템 프롬프트에 도구 정의를 주입하고 AI 응답에서 도구 호출을 파싱하는 방식으로 구현했습니다. OpenAI Native JSON, Minimax XML, Claude XML, 텍스트 형식 등 다양한 모델의 출력 형식을 처리하기 위해 네 가지 파서를 사용합니다.
* 대화 요약: 긴 대화 세션 시 모델의 컨텍스트 제한을 초과하지 않도록, 일정 임계값 이상이 되면 최근 메시지를 제외한 이전 대화를 요약하여 하나의 메시지로 대체합니다. 요약에는 Straico의 smart_llm_selector를 사용하여 비용 효율적인 모델을 선택합니다.
* 모델 제한 및 검증: Straico API에서 모델별 컨텍스트 제한(word_limit) 및 최대 출력 토큰(max_output) 정보를 가져와 캐싱합니다. 프록시는 이를 활용하여 요청이 모델의 컨텍스트 제한을 초과하지 않는지 검증하고, /v1/models 엔드포인트를 통해 사용 가능한 모델 목록을 노출합니다.
* 인증: required, optional, disabled, external 네 가지 인증 모드를 지원하며, API 키 비교 시 crypto.timingSafeEqual을 사용하여 타이밍 공격을 방지합니다.
* 재시도 및 정상 종료: BaseProvider에서 API 호출 시 지수 백오프를 적용한 재시도 로직을 구현하여 429, 5xx 오류 및 네트워크 오류에 대응합니다. Docker의 SIGTERM 신호 수신 시 새로운 요청을 중단하고 활성 요청이 완료될 때까지 기다리는 정상 종료 기능을 제공합니다.
* Docker 설정: Node.js 18 Alpine 기반 이미지를 사용하며, Entrypoint 스크립트를 통해 OpenCode 구성 동기화 후 서버를 시작합니다. .env 파일 및 OpenCode 설정 파일을 위한 볼륨 마운트를 구성합니다.
* Straico API 특이사항: Straico의 'tool' 역할 미지원 문제를 'user' 역할과 [Tool Result]: 접두사를 사용해 해결하고, 메시지 콘텐츠 형식을 단순 문자열로 정규화합니다. 대규모 도구 출력은 TOOL_RESULT_MAX_LENGTH 환경 변수로 잘라냅니다.

시사점

이 프록시는 Straico API의 제약을 극복하고 OpenCode와 같은 에이전트형 코딩 도구가 보다 효율적이고 안정적으로 작동할 수 있도록 하는 실질적인 솔루션을 제공합니다. 또한, 다른 LLM 제공자를 통합할 수 있는 확장 가능한 아키텍처를 제시하며, LLM API 연동 시 발생할 수 있는 다양한 기술적 문제에 대한 해결 방안을 보여줍니다.

원문 읽기 →
원문을 불러오는 중...

댓글

GitHub Discussions