OpenAI 전사
OpenAI 전사 (Transcriptions)
Spring AI는 OpenAI의 Transcription 모델을 지원해요. 음성(오디오)을 텍스트로 변환하는 작업에 유용하죠. 이 글에서는 의존성 추가와 자동 설정, 전사 관련 프로퍼티, 런타임 옵션, 수동 구성, 그리고 diarized_json SDK 워크어라운드까지 다뤄볼게요.
출처: 문서
본문
Spring AI는 OpenAI’s Transcription model을 지원해요.
| __ | 2.0.0-M5 버전부터 Spring AI는 모든 OpenAI 모델을 위해 내부적으로 공식 openai-java SDK를 사용해요. 전환은 매끄러울 것으로 예상되며, OpenAI API 프로퍼티와 빌더의 기존 사용자에게는 호환성이 깨지는 변경이 없어요. 문제를 발견하면 Spring AI GitHub Issues로 알려주세요. |
|---|
Prerequisites
ChatGPT 모델에 접근하려면 OpenAI로 API 키를 만들어야 해요. OpenAI signup page에서 계정을 만들고 API Keys page에서 토큰을 생성하세요. Spring AI 프로젝트는 spring.ai.openai.api-key라는 구성 프로퍼티를 정의하는데, 여기에 openai.com에서 얻은 API Key 값을 설정해야 해요. 환경 변수를 내보내는 것도 이 구성 프로퍼티를 설정하는 한 가지 방법이에요:
Auto-configuration
| __ | Spring AI 자동 설정과 스타터 모듈 아티팩트 이름에 큰 변경이 있었어요. 자세한 내용은 upgrade notes를 참고해주세요. |
|---|
Spring AI는 OpenAI Transcription 클라이언트에 대한 Spring Boot 자동 설정을 제공해요. 활성화하려면 프로젝트의 Maven pom.xml 파일에 다음 의존성을 추가하세요:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-starter-model-openai</artifactId>
</dependency>
또는 Gradle build.gradle 빌드 파일에 추가할 수도 있어요:
dependencies {
implementation 'org.springframework.ai:spring-ai-starter-model-openai'
}
| __ | 빌드 파일에 Spring AI BOM을 추가하려면 Dependency Management 섹션을 참고해주세요. |
|---|
Transcription Properties
Connection Properties
프리픽스 spring.ai.openai는 OpenAI에 연결할 수 있게 해주는 프로퍼티 프리픽스예요.
| Property | Description | Default |
|---|---|---|
| spring.ai.openai.base-url | 연결할 URL | api.openai.com |
| spring.ai.openai.api-key | API 키 | - |
| spring.ai.openai.organization-id | 선택적으로 API 요청에 사용할 조직을 지정할 수 있어요. | - |
| spring.ai.openai.project-id | 선택적으로 API 요청에 사용할 프로젝트를 지정할 수 있어요. | - |
| spring.ai.openai.timeout | OpenAI 클라이언트의 요청 타임아웃. | 60 sec. |
| spring.ai.openai.max-retries | OpenAI 클라이언트의 최대 재시도 횟수. | 3 |
| spring.ai.openai.proxy | OpenAI 클라이언트의 프록시 설정. | - |
| spring.ai.openai.custom-headers | OpenAI 클라이언트 요청에 추가할 커스텀 HTTP 헤더. | empty |
| spring.ai.openai.connection-pool-metrics-enabled | 기저 OkHttp 클라이언트의 연결 풀 메트릭을 활성화할지 여부. | false |
| __ | 여러 조직에 속한 사용자(또는 레거시 사용자 API 키로 프로젝트에 접근하는 사용자)의 경우, 선택적으로 API 요청에 사용할 조직과 프로젝트를 지정할 수 있어요. 이 API 요청의 사용량은 지정된 조직과 프로젝트의 사용량으로 집계돼요. |
|---|
Configuration Properties
| __ | 오디오 전사 자동 설정의 활성화/비활성화는 이제 프리픽스 spring.ai.model.audio.transcription이 붙은 최상위 프로퍼티로 설정해요. 활성화하려면 spring.ai.model.audio.transcription=openai (기본값으로 활성화됨). 비활성화하려면 spring.ai.model.audio.transcription=none (또는 openai와 일치하지 않는 어떤 값). 이 변경은 여러 모델의 설정을 허용하기 위한 것이에요. |
|---|
프리픽스 spring.ai.openai.audio.transcription은 OpenAI 전사 모델의 재시도 메커니즘을 구성할 수 있게 해주는 프로퍼티 프리픽스예요.
| Property | Description | Default |
|---|---|---|
| spring.ai.model.audio.transcription | OpenAI Audio Transcription Model 활성화 | openai |
| spring.ai.openai.audio.transcription.base-url | 연결할 URL | api.openai.com |
| spring.ai.openai.audio.transcription.api-key | API 키 | - |
| spring.ai.openai.audio.transcription.organization-id | 선택적으로 API 요청에 사용할 조직을 지정할 수 있어요. | - |
| spring.ai.openai.audio.transcription.project-id | 선택적으로 API 요청에 사용할 프로젝트를 지정할 수 있어요. | - |
| spring.ai.openai.audio.transcription.model | 전사에 사용할 모델의 ID. 사용 가능한 모델: gpt-4o-transcribe (GPT-4o 기반 음성-텍스트), gpt-4o-mini-transcribe (GPT-4o mini 기반 음성-텍스트), gpt-4o-transcribe-diarize (화자 분리), 또는 whisper-1 (범용 음성 인식 모델, 기본값). |
whisper-1 |
| spring.ai.openai.audio.transcription.response-format | 전사 출력의 형식: json, text, srt, verbose_json, vtt, 또는 diarized_json (화자 레이블이 있는 세그먼트, gpt-4o-transcribe-diarize 필요). |
text |
| spring.ai.openai.audio.transcription.prompt | 모델의 스타일을 안내하거나 이전 오디오 세그먼트를 이어갈 선택적 텍스트. 프롬프트는 오디오 언어와 일치해야 해요. | |
| spring.ai.openai.audio.transcription.language | 입력 오디오의 언어. 입력 언어를 ISO-639-1 형식으로 제공하면 정확도와 지연 시간이 개선돼요. | |
| spring.ai.openai.audio.transcription.temperature | 샘플링 온도, 0에서 1 사이. 0.8 같은 높은 값은 출력을 더 무작위로 만들고, 0.2 같은 낮은 값은 더 집중적이고 결정적으로 만들죠. 0으로 설정하면 모델이 특정 임계값에 도달할 때까지 온도를 자동으로 높이기 위해 로그 확률을 사용해요. | 0 |
| spring.ai.openai.audio.transcription.timestamp-granularities | 이 전사를 위해 채울 타임스탬프 세분성. timestamp granularities를 사용하려면 response_format이 verbose_json이어야 해요. word 또는 segment 중 하나 또는 둘 다 지원돼요. 참고: 세그먼트 타임스탬프에는 추가 지연이 없지만, 단어 타임스탬프 생성은 추가 지연이 발생해요. |
segment |
| spring.ai.openai.audio.transcription.known-speaker-names | 화자 이름(최대 4개), known-speaker-references와 위치적으로 대응돼요. gpt-4o-transcribe-diarize에서만 사용돼요. |
|
| spring.ai.openai.audio.transcription.known-speaker-references | 알려진 화자의 오디오 샘플(data URL 형태, 예: data:audio/wav;base64,…), known-speaker-names와 위치적으로 대응돼요. gpt-4o-transcribe-diarize에서만 사용돼요. |
|
| spring.ai.openai.audio.transcription.chunking-strategy | 오디오가 어떻게 청킹되는지 제어해요. 이 프로퍼티로는 auto만 지원돼요. voice-activity-detection 조정은 프로그래밍 방식으로 OpenAiAudioTranscriptionOptions.Builder를 사용하세요. whisper-1에서는 지원되지 않아요. |
|
| spring.ai.openai.audio.transcription.diarized-json-workaround-enabled | diarized_json 응답을 잘못 분류하는 알려진 OpenAI Java SDK 버그(openai-java#802)를 우회할지 여부. diarized_json SDK Workaround 참고. |
true |
| __ | 공통 spring.ai.openai.base-url, spring.ai.openai.api-key, spring.ai.openai.organization-id, spring.ai.openai.project-id 프로퍼티를 재정의할 수 있어요. spring.ai.openai.audio.transcription.base-url, spring.ai.openai.audio.transcription.api-key, spring.ai.openai.audio.transcription.organization-id, spring.ai.openai.audio.transcription.project-id 프로퍼티가 설정되면 공통 프로퍼티보다 우선해요. 서로 다른 모델과 서로 다른 모델 엔드포인트에 서로 다른 OpenAI 계정을 사용하려 할 때 유용해요. |
|---|
| __ | spring.ai.openai.audio.transcription 프리픽스가 붙은 모든 프로퍼티는 런타임에 재정의할 수 있어요. |
|---|
Runtime Options
OpenAiAudioTranscriptionOptions 클래스는 전사 요청을 할 때 사용할 옵션을 제공해요. 시작 시 spring.ai.openai.audio.transcription으로 지정한 옵션이 사용되지만 런타임에 이를 재정의할 수 있어요.
예:
OpenAiAudioTranscriptionOptions transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
.language("en")
.prompt("Ask not this, but ask that")
.temperature(0f)
.responseFormat(AudioResponseFormat.VTT)
.build();
AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
AudioTranscriptionResponse response = openAiTranscriptionModel.call(transcriptionRequest);
Response Metadata
verbose_json과 diarized_json의 경우, response.getMetadata()는 전사된 텍스트에 더해 getDuration(), getLanguage(), getUsage(), getSegments(), getWords()를 노출하는 OpenAiAudioTranscriptionResponseMetadata예요. 다른 응답 형식에서는 이 값들이 null/empty예요.
diarized_json SDK Workaround
OpenAI Java SDK(4.42.0 기준)는 diarized_json 응답을 잘못 분류해서, 그대로 두면 원시 JSON 페이로드가 전사 텍스트로 드러나요(openai-java#802). Spring AI는 이를 감지해 깨끗한 텍스트, 화자 세그먼트, 사용량을 자동으로 복구해요. 이 형식에서는 API가 duration을 반환하지 않으므로 duration은 계속 사용할 수 없어요. 워크어라운드를 비활성화하려면 OpenAiAudioTranscriptionOptions.Builder#diarizedJsonWorkaroundEnabled(false) 또는 spring.ai.openai.audio.transcription.diarized-json-workaround-enabled=false를 사용하세요.
Manual Configuration
프로젝트의 Maven pom.xml 파일에 spring-ai-openai 의존성을 추가하세요:
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
</dependency>
또는 Gradle build.gradle 빌드 파일에 추가할 수도 있어요:
dependencies {
implementation 'org.springframework.ai:spring-ai-openai'
}
| __ | 빌드 파일에 Spring AI BOM을 추가하려면 Dependency Management 섹션을 참고해주세요. |
|---|
다음으로 OpenAiAudioTranscriptionModel을 만들어볼게요:
var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
.apiKey(System.getenv("OPENAI_API_KEY"))
.responseFormat(AudioResponseFormat.TEXT)
.temperature(0f)
.build();
var openAiAudioTranscriptionModel = OpenAiAudioTranscriptionModel.builder()
.options(transcriptionOptions)
.build();
var audioFile = new FileSystemResource("/path/to/your/resource/speech/jfk.flac");
AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, transcriptionOptions);
AudioTranscriptionResponse response = openAiAudioTranscriptionModel.call(transcriptionRequest);
Customizing the HTTP Client
Spring AI는 내부적으로 공식 openai-java SDK를 사용하며, SpringAiOpenAiHttpClient.Builder가 만든 커스텀 OkHttp 클라이언트로 HTTP 전송을 구성해요. 기저 OkHttpClient가 생성되기 전에 하나 이상의 OpenAiHttpClientBuilderCustomizer 빈을 노출해서 그 빌더를 가로챌 수 있어요. 각 커스터마이저는 모든 OpenAI 모델(chat, embedding, image, audio, moderation)이 사용하는 동일한 빌더를 받으므로, 커스터마이징이 균일하게 적용돼요.
@FunctionalInterface
public interface OpenAiHttpClientBuilderCustomizer {
void customize(SpringAiOpenAiHttpClient.Builder builder);
}
전형적인 사용 사례:
-
OkHttp
Interceptor인스턴스 등록 (인증, 전파 헤더, 커스텀 로깅); -
디스패처
ExecutorService교체 (예: 비동기 I/O를 가상 스레드로 라우팅); -
빌더가 노출하는 프록시, SSL, 호스트 이름 검증, 연결 풀 크기 구성.
커스터마이저가 여러 개 있으면 @Order / Ordered 순서로, Spring AI 기본값 이후에 적용되므로 사용자 코드가 우선해요.
OpenAi*Model.Builder를 통해 모델을 수동으로 연결할 때도 동일한 훅을 사용할 수 있어요:
var chatModel = OpenAiChatModel.builder()
.options(OpenAiChatOptions.builder().model("gpt-4o").build())
.httpClientBuilderCustomizer(myCustomizer)
.build();
Example Code
- OpenAiAudioTranscriptionModelIT.java 테스트는 라이브러리 사용법에 대한 일반적인 예제를 제공해요.