LiteLLM SDK + FastAPI + Hypercorn 중계 예제 구현 계획 (보관용)¶
이 문서는 relay 예제를 구현하기 전에 작성한 계획 기록입니다. 현재
main에는relay/예제가 이미 구현되어 있으며, 최신 사용법은docs/ko/relay-example.md를 따릅니다.
목표¶
이 저장소에 세 번째 예제를 추가합니다.
clients/python/— LiteLLM Proxy를 직접 호출하는 Python 예제clients/java/— LiteLLM Proxy를 직접 호출하는 Java 예제relay/— LiteLLM Python SDK를 감싼 FastAPI + Hypercorn 중계 예제
세 번째 예제의 핵심은, Java가 upstream LiteLLM Proxy를 직접 때리는 대신, tool calling처럼 구조화된 계약으로 relay를 호출하도록 만드는 것입니다.
즉, relay의 외부 계약은 단순 input 문자열이 아니라 다음과 같은 구조를 가집니다.
tool_nameresearch_questioncontextconstraintsdeliverable_formatbackgroundstream
relay 내부에서만 이 구조를 LiteLLM SDK 요청 형식으로 번역합니다.
현재 저장소 실제 상태 기준 정리¶
- 현재
main에는 직접 호출용 Python/Java 예제가 이미 존재합니다. - 두 예제 모두
chat/completions,responses,background: true를 지원합니다. - 문서 작성 시점 snapshot에서는 open issue 0, open PR 0, milestone 0, project item 0 이었습니다.
- 문서 작성 시점 snapshot에서 최근 CI는 성공 상태였습니다.
- 이 계획 문서가 작성되던 시점에는
relay/예제가 아직 구현되어 있지 않았습니다.
따라서 현재 repository에서 가장 먼저 닫아야 할 canonical task는:
세 번째 relay 예제를 위한 repository-local 구현 계획을 만들고, 저장소 구조/검증/계약을 명확히 고정하는 것
입니다.
아키텍처 개요¶
전체 흐름은 다음과 같습니다.
Azure OpenAI o3-deep-research
→ LiteLLM Proxy (Azure Landing Zone)
→ LiteLLM Python SDK + FastAPI + Hypercorn relay
→ Java caller
중요한 점은 다음과 같습니다.
- relay는 다시 LiteLLM Proxy를 HTTP로 그대로 재노출하는 서버가 아닙니다.
- relay는 LiteLLM Python SDK를 wrapping 합니다.
- Java는 relay에 구조화된 tool invocation 요청을 보냅니다.
- relay만 upstream LiteLLM 호출 형식을 압니다.
즉,
- Java ↔ relay 사이: 도메인 지향 / tool-calling-like contract
- relay ↔ LiteLLM SDK 사이: SDK/HTTP 세부 구현
으로 분리합니다.
최종적으로 추가될 디렉터리와 파일¶
새로 생길 상위 예제¶
relay/
relay 내부 주요 파일¶
relay/pyproject.tomlrelay/README.mdrelay/src/litellm_relay/__init__.pyrelay/src/litellm_relay/config.pyrelay/src/litellm_relay/contracts.pyrelay/src/litellm_relay/upstream.pyrelay/src/litellm_relay/service.pyrelay/src/litellm_relay/app.pyrelay/src/litellm_relay/__main__.py
relay 테스트 파일¶
relay/tests/test_config.pyrelay/tests/test_contracts.pyrelay/tests/test_upstream.pyrelay/tests/test_app.pyrelay/tests/test_lifecycle.py
기존 예제에서 수정될 가능성이 높은 파일¶
clients/java/src/main/java/example/litellm/Main.javaclients/java/src/main/java/example/litellm/relay/RelayClient.javaclients/java/src/test/java/example/litellm/RelayClientTest.javaclients/java/README.md
저장소 공통 문서/CI 수정 대상¶
.github/workflows/ci.ymlREADME.mdARCHITECTURE.mdAGENTS.mddocs/engineering/acceptance-criteria.mddocs/engineering/harness-engineering.mddocs/ko/manual.mddocs/workflow/one-day-delivery-plan.md
공개 API 계약 초안¶
relay는 REST 자원 스타일로 설계합니다.
1) Tool invocation 생성¶
POST /api/v1/tool-invocations
요청 예시:
{
"tool_name": "deep_research",
"arguments": {
"research_question": "Azure OpenAI o3-deep-research relay 구조를 설명해줘",
"context": ["Azure Landing Zone", "LiteLLM Proxy"],
"constraints": ["markdown 형식", "보안 가정 포함"],
"deliverable_format": "markdown_brief",
"require_citations": true,
"background": true,
"stream": false
}
}
2) Invocation 상태 조회¶
GET /api/v1/tool-invocations/{invocation_id}
3) 완료까지 대기¶
GET /api/v1/tool-invocations/{invocation_id}/wait
4) 이벤트 스트림 구독¶
GET /api/v1/tool-invocations/{invocation_id}/events
이렇게 하면 Java 입장에서는:
- "deep_research라는 도구를 호출한다"
- "그 도구에 구조화된 arguments를 넘긴다"
라는 모델로 이해할 수 있고, relay 내부에서만 LiteLLM SDK 요청으로 바뀝니다.
단계별 구현 계획¶
1단계: relay scaffold + 설정 로딩¶
목표:
relay/패키지 생성- Hypercorn 진입점 생성
- 기존 저장소 정책과 같은 설정 방식 적용
설정 키:
LITELLM_BASE_URLLITELLM_API_KEYLITELLM_MODEL(기본o3-deep-research)RELAY_HOST(기본127.0.0.1)RELAY_PORT(기본8080)RELAY_TIMEOUT_SECONDS(기본30)
정책:
- 실제 환경변수 우선
~/.envfallback 허용- 프로젝트 로컬
.env자동 로드 금지
테스트:
relay/tests/test_config.py
2단계: tool-calling-like contract 정의¶
목표:
- relay 외부 계약을 도메인 지향적으로 고정
핵심 모델 예시:
class DeepResearchArguments(BaseModel):
research_question: str
context: list[str] = []
constraints: list[str] = []
deliverable_format: Literal[
"markdown_brief",
"markdown_report",
"json_outline",
]
require_citations: bool = True
background: bool = False
stream: bool = False
class ToolInvocationRequest(BaseModel):
tool_name: Literal["deep_research"]
arguments: DeepResearchArguments
테스트:
relay/tests/test_contracts.py
3단계: LiteLLM SDK adapter 추가¶
목표:
- relay 내부에서만 LiteLLM SDK 호출 세부 구현 보유
핵심 역할:
- structured arguments → LiteLLM SDK 호출 payload 변환
- foreground responses 호출
- background responses 제출
- response id 조회
- polling
- stream 처리
중요한 원칙:
- relay 외부에는 raw
input파라미터를 공개하지 않음 - relay 내부에서만 LiteLLM SDK가 요구하는 형식으로 변환
테스트:
relay/tests/test_upstream.py
4단계: FastAPI 엔드포인트 구현¶
목표:
- Java가 relay를 일반 HTTP API처럼 호출 가능하게 만들기
동작 규칙:
- foreground 호출 → 최종 텍스트 결과 반환
- background 호출 → invocation id + upstream response id + 상태 메타데이터 반환
- wait 호출 → polling 후 최종 텍스트 반환
- events 호출 → SSE 이벤트 스트림 반환
테스트:
relay/tests/test_app.py
5단계: lifecycle (조회 / polling / stream) 구현¶
목표:
- background와 stream을 실제로 usable한 형태로 닫기
포함 범위:
- upstream
response_id조회 - timeout 포함 polling
- 텍스트 중심 SSE relay
간소화 원칙:
- 1차 버전에서는 텍스트 delta만 relay
- 복잡한 전체 event taxonomy는 과도하게 확장하지 않음
- 메타데이터는 보존
- 로그/에러에서 비밀값 노출 금지
테스트:
relay/tests/test_lifecycle.py
6단계: Java relay caller 추가¶
목표:
- Java가 직접 LiteLLM Proxy를 호출하는 모드와
- relay를 호출하는 모드를 둘 다 가지게 하기
추가 파일:
clients/java/src/main/java/example/litellm/relay/RelayClient.javaclients/java/src/test/java/example/litellm/RelayClientTest.java
수정 파일:
clients/java/src/main/java/example/litellm/Main.java
예상 역할:
- structured JSON 작성
- relay POST 호출
- background/wait/events 흐름 지원
테스트:
mvn -Dtest=RelayClientTest test
7단계: 문서와 CI 갱신¶
목표:
- relay 예제가 저장소의 정식 세 번째 예제로 반영되도록 canonical docs와 CI를 갱신
필수 수정 항목:
.github/workflows/ci.yml에 relay 테스트 추가README.md에 세 번째 예제 설명 추가ARCHITECTURE.md에 relay 구조 반영AGENTS.md에 relay setup/test 명령 추가docs/engineering/acceptance-criteria.md에 relay 검증 기준 추가docs/engineering/harness-engineering.md에 relay harness 설명 추가docs/ko/manual.md에 relay 사용법 추가
검증 명령¶
relay 테스트¶
기존 Python 예제 테스트¶
기존 Java 예제 테스트¶
relay 실행 확인¶
relay 직접 호출 확인 예시¶
curl -X POST http://127.0.0.1:8080/api/v1/tool-invocations \
-H "Content-Type: application/json" \
-d '{
"tool_name": "deep_research",
"arguments": {
"research_question": "relay architecture를 요약해줘",
"deliverable_format": "markdown_brief",
"background": false,
"stream": false
}
}'
Java → relay 호출 검증¶
relay caller가 구현되면 다음 형태의 검증을 수행합니다.
cd clients/java
mvn -q exec:java -Dexec.mainClass=example.litellm.Main -Dexec.args="--target relay relay architecture를 설명해줘"
위험 요소와 가정¶
- upstream LiteLLM Proxy의
responses,background,stream지원 수준은 Azure OpenAI 배치 구성에 따라 차이가 있을 수 있습니다. - relay는 외부에
input을 숨기지만, 내부적으로는 여전히 LiteLLM SDK 요청 형식으로 번역해야 합니다. - stream은 1차 버전에서 텍스트 delta 중심으로 제한하는 것이 적절합니다.
- Hypercorn은 이 relay 예제의 기본 ASGI 서버로 채택합니다.
- 이 예제는 production orchestration 플랫폼이 아니라, 구조와 중계 패턴을 보여주는 예제여야 합니다.
완료 기준¶
이 relay 계획이 실제 구현으로 닫혔다고 판단하려면 최소한 다음이 충족되어야 합니다.
- direct Python 예제 green
- direct Java 예제 green
- relay 테스트 green
- relay CI 포함
- relay 문서화 완료
- Java → relay structured contract 확인
- background / polling / stream 경로 검증 완료
- 관련 PR/CI/문서 상태가 모두 닫힌 상태
즉, 단순히 설계 문서만 있는 상태가 아니라, 실제 코드 + 테스트 + CI + 문서 + 런타임 검증까지 모두 닫혀야 완료입니다.
✅ 구현 완료 (2026-03-19)
위 완료 기준이 모두 충족되었습니다.
relay/예제는 현재main브랜치에 구현·테스트·CI·문서화까지 완전히 통합된 상태입니다. 최신 사용법과 API 계약은docs/ko/relay-example.md와docs/ko/manual.md를 참고하세요.