์๋ ํ์ธ์ dev_writer์ ๋๋ค.
์ด๋ฒ ์๊ฐ์๋ Spring AI ๊ณต์ ๋ฌธ์ ์ค ๋๋จธ์ง ๋ชจ๋ธ์ธ Embedding Models, Audio Models, Moderation Models์ ๋ํด ๋ฒ์ญํ ๋ด์ฉ์ ์ ๋ฌํด ๋๋ฆฌ๊ฒ ์ต๋๋ค.
Embedding Models
์๋ฒ ๋ฉ (Embedding)์ ํ ์คํธ, ์ด๋ฏธ์ง, ๋น๋์ค์ ๊ฐ์ ์ ๋ ฅ ๋ฐ์ดํฐ๋ฅผ ์์นํ๋ ๋ฒกํฐ ํํ๋ก ๋ณํํ์ฌ, ์ด๋ค ๊ฐ์ ๊ด๊ณ๋ฅผ ํฌ์ฐฉํ๋ ๋ฐฉ์์ ๋๋ค.
์๋ฒ ๋ฉ์ ํ ์คํธ, ์ด๋ฏธ์ง, ๋น๋์ค ๋ฑ์ ๋ถ๋์์์ ์ซ์์ ๋ฐฐ์ด (๋ฒกํฐ)๋ก ๋ณํํจ์ผ๋ก์จ ์๋ํฉ๋๋ค. ์ด ๋ฒกํฐ๋ ํด๋น ์ ๋ ฅ์ ์๋ฏธ๋ฅผ ํฌ์ฐฉํ๋๋ก ์ค๊ณ๋์ด ์์ผ๋ฉฐ, ์ด ๋ฒกํฐ ๋ฐฐ์ด์ ๊ธธ์ด๋ ๋ฒกํฐ์ ์ฐจ์ (dimensionality)์ด๋ผ๊ณ ํฉ๋๋ค.
๋ ํ ์คํธ์ ์๋ฒ ๋ฉ ๋ฒกํฐ ๊ฐ ์์น์ ๊ฑฐ๋ฆฌ๋ฅผ ๊ณ์ฐํจ์ผ๋ก์จ, ์ ํ๋ฆฌ์ผ์ด์ ์ ํด๋น ๊ฐ์ฒด ๊ฐ์ ์ ์ฌ๋ (similarity)๋ฅผ ํ๋จํ ์ ์์ต๋๋ค.
EmbeddingModel ์ธํฐํ์ด์ค๋ AI ๋ฐ ๋จธ์ ๋ฌ๋์์ ์๋ฒ ๋ฉ ๋ชจ๋ธ๊ณผ์ ํตํฉ์ ๊ฐ๋จํ๊ฒ ๋ง๋ค๊ธฐ ์ํด ์ค๊ณ๋์์ต๋๋ค. ์ด ์ธํฐํ์ด์ค์ ์ฃผ์ ๋ชฉ์ ์ ํ ์คํธ๋ฅผ ์์น ๋ฒกํฐ (์๋ฒ ๋ฉ)๋ก ๋ณํํ๋ ๊ฒ์ ๋๋ค. ์ด๋ฌํ ์๋ฒ ๋ฉ์ ์๋ฏธ ๋ถ์ (semantic analysis), ํ ์คํธ ๋ถ๋ฅ (text classification) ๋ฑ ๋ค์ํ ์์ ์ ํต์ฌ์ ์ผ๋ก ์ฌ์ฉ๋ฉ๋๋ค.
EmbeddingModel ์ธํฐํ์ด์ค์ ์ค๊ณ๋ ๋ค์ ๋ ๊ฐ์ง ์ฃผ์ ๋ชฉํ๋ฅผ ์ค์ฌ์ผ๋ก ์ด๋ฃจ์ด์ก์ต๋๋ค.
- ์ด์์ฑ (Portability): ์ด ์ธํฐํ์ด์ค๋ ๋ค์ํ ์๋ฒ ๋ฉ ๋ชจ๋ธ ๊ฐ์ ์์ฌ์ด ์ ํ์ ๊ฐ๋ฅํ๊ฒ ํ์ฌ, ์ต์ํ์ ์ฝ๋ ๋ณ๊ฒฝ๋ง์ผ๋ก๋ ๋ค๋ฅธ ์๋ฒ ๋ฉ ๊ธฐ๋ฒ์ด๋ ๋ชจ๋ธ๋ก ๊ต์ฒดํ ์ ์๋๋ก ์ง์ํฉ๋๋ค. ์ด๋ Spring ํ๋ ์์ํฌ์ ๋ชจ๋ํ ๋ฐ ํธํ์ฑ ์ฒ ํ๊ณผ๋ ์ ๋ถํฉํฉ๋๋ค.
- ๋จ์์ฑ (Simplicity): EmbeddingModel์ ํ ์คํธ๋ฅผ ์๋ฒ ๋ฉ์ผ๋ก ๋ณํํ๋ ๊ณผ์ ์ ๋จ์ํํฉ๋๋ค. embed(String text), embed(Document document)์ ๊ฐ์ ๊ฐ๋จํ ๋ฉ์๋๋ฅผ ์ ๊ณตํ์ฌ, ์์ ํ ์คํธ ๋ฐ์ดํฐ์ ์๋ฒ ๋ฉ ์๊ณ ๋ฆฌ์ฆ์ ์ง์ ๋ค๋ฃจ๋ ๋ณต์ก์ฑ์ ์ ๊ฑฐํฉ๋๋ค. ์ด๋ฌํ ์ค๊ณ๋ AI์ ์ต์ํ์ง ์์ ๊ฐ๋ฐ์๋ค๋ ์๋ฒ ๋ฉ ๊ธฐ๋ฅ์ ์ฝ๊ฒ ํ์ฉํ ์ ์๋๋ก ๋์ต๋๋ค.
API ๊ฐ์
์๋ฒ ๋ฉ ๋ชจ๋ธ API (Embedding Model API)๋ Spring AI ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ ์ผ๋ถ์ธ ๋ฒ์ฉ Spring AI ๋ชจ๋ธ API ์์ ๊ตฌ์ถ๋์ด ์์ต๋๋ค. ์ด๋ก ์ธํด EmbeddingModel ์ธํฐํ์ด์ค๋ Model ์ธํฐํ์ด์ค๋ฅผ ํ์ฅํ๋ฉฐ, AI ๋ชจ๋ธ๊ณผ ์ํธ์์ฉํ๊ธฐ ์ํ ํ์ค ๋ฉ์๋ ์งํฉ์ ์ ๊ณตํฉ๋๋ค.
EmbeddingRequest์ EmbeddingResponse ํด๋์ค๋ ๊ฐ๊ฐ ์ ๋ ฅ๊ณผ ์ถ๋ ฅ์ ์บก์ํํ๊ธฐ ์ํด ์ฌ์ฉ๋๋ฉฐ, ์ด๋ ModelRequest์ ModelResponse๋ฅผ ํ์ฅํ์ฌ ์ค๊ณ๋์์ต๋๋ค. ์ด๋ฅผ ํตํด ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ์์ฒญ/์๋ต ์ฒ๋ฆฌ๊ฐ ์ผ๊ด๋ ๋ฐฉ์์ผ๋ก ์ํ๋ฉ๋๋ค.
EmbeddingModel API๋ ์์ ๊ณ์ธต ์ปดํฌ๋ํธ์์ OpenAI, Titan, Azure OpenAI, Ollie ๋ฑ ๋ค์ํ ํน์ ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ๋ํ ๊ตฌํ์ ์ง์ํ๊ธฐ ์ํด ์ฌ์ฉ๋ฉ๋๋ค. ์ด ๊ตฌ์กฐ๋ ์ถ์ํ ๊ณ์ธต์ ํตํด ๋ชจ๋ธ ๊ฐ์ ํธํ์ฑ์ ๋ณด์ฅํ๋ฉด์, ๊ฐ๋ฐ์๊ฐ ํน์ ๋ฒค๋์ ์ข ์๋์ง ์๊ณ ์ ์ฐํ๊ฒ ๊ตฌํํ ์ ์๋๋ก ๋์ต๋๋ค.
๋ค์ ๋ค์ด์ด๊ทธ๋จ์ Embedding API๊ฐ Spring AI Model API ๋ฐ ๊ตฌ์ฒด์ ์ธ Embedding Models์ ์ด๋ป๊ฒ ์ฐ๊ณ๋์ด ์๋์ง๋ฅผ ์๊ฐ์ ์ผ๋ก ์ค๋ช ํฉ๋๋ค.
์ด ์น์ ์์๋ EmbeddingModel ์ธํฐํ์ด์ค ๋ฐ ๊ด๋ จ ํด๋์ค์ ๋ํ ๊ฐ์ด๋๋ฅผ ์ ๊ณตํฉ๋๋ค.
public interface EmbeddingModel extends Model<EmbeddingRequest, EmbeddingResponse> {
@Override
EmbeddingResponse call(EmbeddingRequest request);
/**
* ์ฃผ์ด์ง ๋ฌธ์์ ๋ด์ฉ์ ๋ฒกํฐ๋ก ์๋ฒ ๋ฉํฉ๋๋ค.
* @param document ์๋ฒ ๋ฉํ ๋ฌธ์
* @return ์๋ฒ ๋ฉ๋ ๋ฒกํฐ
*/
float[] embed(Document document);
/**
* ์ฃผ์ด์ง ํ
์คํธ๋ฅผ ๋ฒกํฐ๋ก ์๋ฒ ๋ฉํฉ๋๋ค.
* @param text ์๋ฒ ๋ฉํ ํ
์คํธ
* @return ์๋ฒ ๋ฉ๋ ๋ฒกํฐ
*/
default float[] embed(String text) {
Assert.notNull(text, "Text must not be null");
return this.embed(List.of(text)).iterator().next();
}
/**
* ํ
์คํธ ๋ชฉ๋ก์ ๋ฒกํฐ๋ก ์ผ๊ด ์๋ฒ ๋ฉํฉ๋๋ค.
* @param texts ์๋ฒ ๋ฉํ ํ
์คํธ ๋ชฉ๋ก
* @return ์๋ฒ ๋ฉ๋ ๋ฒกํฐ ๋ชฉ๋ก์ ๋ชฉ๋ก
*/
default List<float[]> embed(List<String> texts) {
Assert.notNull(texts, "Texts must not be null");
return this.call(new EmbeddingRequest(texts, EmbeddingOptions.EMPTY))
.getResults()
.stream()
.map(Embedding::getOutput)
.toList();
}
/**
* ํ
์คํธ ๋ชฉ๋ก์ ๋ฒกํฐ๋ก ์๋ฒ ๋ฉํ๊ณ {@link EmbeddingResponse}๋ฅผ ๋ฐํํฉ๋๋ค.
* @param texts ์๋ฒ ๋ฉํ ํ
์คํธ ๋ชฉ๋ก
* @return ์๋ฒ ๋ฉ ์๋ต
*/
default EmbeddingResponse embedForResponse(List<String> texts) {
Assert.notNull(texts, "Texts must not be null");
return this.call(new EmbeddingRequest(texts, EmbeddingOptions.EMPTY));
}
/**
* @return ์๋ฒ ๋ฉ๋ ๋ฒกํฐ์ ์ฐจ์ ์๋ฅผ ๋ฐํํฉ๋๋ค. ์ด๋ ์์ฑ ๋ชจ๋ธ๋ณ๋ก ๋ค๋ฆ
๋๋ค.
*/
default int dimensions() {
return embed("Test String").size();
}
}
embed ๋ฉ์๋๋ ํ ์คํธ๋ฅผ ์๋ฒ ๋ฉ์ผ๋ก ๋ณํํ๋ ๋ค์ํ ์ต์ ์ ์ ๊ณตํฉ๋๋ค. ๋จ์ผ ๋ฌธ์์ด, ๊ตฌ์กฐํ๋ Document ๊ฐ์ฒด, ๋๋ ํ ์คํธ์ ๋ฐฐ์น (batch)๋ฅผ ์ฒ๋ฆฌํ ์ ์์ต๋๋ค.
ํ ์คํธ๋ฅผ ์๋ฒ ๋ฉํ๊ธฐ ์ํ ์ฌ๋ฌ ๊ฐ์ ๋จ์ถ ๋ฉ์๋๊ฐ ์ ๊ณต๋๋ฉฐ, ๊ทธ์ค embed(String text) ๋ฉ์๋๋ ๋จ์ผ ๋ฌธ์์ด์ ์ ๋ ฅ๋ฐ์ ํด๋นํ๋ ์๋ฒ ๋ฉ ๋ฒกํฐ๋ฅผ ๋ฐํํฉ๋๋ค. ๋ชจ๋ ๋จ์ถ ๋ฉ์๋๋ ์๋ฒ ๋ฉ ๋ชจ๋ธ์ ํธ์ถํ๋ ๊ธฐ๋ณธ ๋ฉ์๋์ธ call ๋ฉ์๋๋ฅผ ์ค์ฌ์ผ๋ก ๊ตฌํ๋์ด ์์ต๋๋ค.
์๋ฒ ๋ฉ์ ์ผ๋ฐ์ ์ผ๋ก ๋ถ๋์์์ ์ซ์ (float)์ ๋ฆฌ์คํธ๋ก ๋ฐํ๋๋ฉฐ, ์ด๋ ์๋ฒ ๋ฉ์ ์์น ๋ฒกํฐ ํ์์ผ๋ก ํํํ ๊ฒ์ ๋๋ค. embedForResponse ๋ฉ์๋๋ ๋ณด๋ค ํฌ๊ด์ ์ธ ์ถ๋ ฅ์ ์ ๊ณตํ๋ฉฐ, ์๋ฒ ๋ฉ์ ๋ํ ์ถ๊ฐ ์ ๋ณด๊ฐ ํฌํจ๋ ์ ์์ต๋๋ค.
dimensions ๋ฉ์๋๋ ๊ฐ๋ฐ์๊ฐ ์๋ฒ ๋ฉ ๋ฒกํฐ์ ํฌ๊ธฐ๋ฅผ ๋น ๋ฅด๊ฒ ํ์ ํ ์ ์๋๋ก ๋์์ฃผ๋ ์ ์ฉํ ๋๊ตฌ์ ๋๋ค. ์ด๋ ์๋ฒ ๋ฉ ๊ณต๊ฐ์ ์ดํดํ๊ฑฐ๋ ํ์ ์ฒ๋ฆฌ ๋จ๊ณ์ ์์ด์ ์ค์ํ ์์์ ๋๋ค.
EmbeddingRequest
EmbeddingRequest๋ ModelRequest๋ฅผ ์์ํ ํด๋์ค๋ก, ํ ์คํธ ๊ฐ์ฒด์ ๋ฆฌ์คํธ์ ์ ํ์ ์ธ ์๋ฒ ๋ฉ ์์ฒญ ์ต์ ์ ์ ๋ ฅ์ผ๋ก ๋ฐ์ต๋๋ค. ์๋๋ ์์ฑ์ ๋ฐ ๊ธฐํ ์ ํธ๋ฆฌํฐ ๋ฉ์๋๋ฅผ ์ ์ธํ EmbeddingRequest ํด๋์ค์ ์ถ์ฝ ๋ฒ์ ์ ๋๋ค.
public class EmbeddingRequest implements ModelRequest<List<String>> {
private final List<String> inputs;
private final EmbeddingOptions options;
// ๋ค๋ฅธ ๋ฉ์๋๋ค์ ์๋ต
}
EmbeddingResponse
EmbeddingResponse ํด๋์ค์ ๊ตฌ์กฐ๋ ์๋์ ๊ฐ์ต๋๋ค.
public class EmbeddingResponse implements ModelResponse<Embedding> {
private List<Embedding> embeddings;
private EmbeddingResponseMetadata metadata = new EmbeddingResponseMetadata();
// ๋ค๋ฅธ ๋ฉ์๋๋ค์ ์๋ต
}
EmbeddingResponse ํด๋์ค๋ AI ๋ชจ๋ธ์ ์ถ๋ ฅ์ ๋ณด๊ดํ๋ฉฐ, ๊ฐ Embedding ์ธ์คํด์ค๋ ๋จ์ผ ํ ์คํธ ์ ๋ ฅ์ ๋ํ ๊ฒฐ๊ณผ ๋ฒกํฐ ๋ฐ์ดํฐ๋ฅผ ํฌํจํฉ๋๋ค.
๋ํ EmbeddingResponse ํด๋์ค๋ AI ๋ชจ๋ธ์ ์๋ต์ ๋ํ ๋ฉํ๋ฐ์ดํฐ์ธ EmbeddingResponseMetadata ๋ ํจ๊ป ํฌํจํฉ๋๋ค.
Embedding
Embedding์ ๋จ์ผ ์๋ฒ ๋ฉ ๋ฒกํฐ๋ฅผ ๋ํ๋ ๋๋ค.
public class Embedding implements ModelResult<float[]> {
private float[] embedding;
private Integer index;
private EmbeddingResultMetadata metadata;
// ๋ค๋ฅธ ๋ฉ์๋๋ค์ ์๋ต
}
์ด์ฉ ๊ฐ๋ฅํ ๊ตฌํ์ฒด
๋ด๋ถ์ ์ผ๋ก ๋ค์ํ EmbeddingModel ๊ตฌํ์ฒด๋ค์ ์๋ฒ ๋ฉ ์์ ์ ์ํํ๊ธฐ ์ํด ์๋ก ๋ค๋ฅธ ์ ์์ค ๋ผ์ด๋ธ๋ฌ๋ฆฌ ๋ฐ API๋ฅผ ์ฌ์ฉํฉ๋๋ค. ๋ค์์ ์ฌ์ฉ ๊ฐ๋ฅํ EmbeddingModel ๊ตฌํ์ฒด๋ค์ ์ผ๋ถ์ ๋๋ค.
- Spring AI OpenAI Embeddings
- Spring AI Azure OpenAI Embeddings
- Spring AI Ollamma Embeddings
- Spring AI Transformers (ONNX) Embeddings
- Spring AI PostgresML Embeddings
- Spring AI Bedrock Cohere Embeddings
- Spring AI Bedrock Titan Embeddings
- Spring AI VertexAI Embeddings
- Spring AI Mistral AI Embeddings
- Spring AI Oracle Cloud Infrastructure GenAI Embeddings
Audio Models (OpenAI)
์์ฑ-ํ ์คํธ ๋ณํ (Transcription, ์ ์ฌ) API
Spring AI๋ OpenAI์ ์์ฑ-ํ ์คํธ ๋ณํ API๋ฅผ ์ง์ํฉ๋๋ค. ํฅํ ์ถ๊ฐ์ ์ธ ์ ๊ณต์๊ฐ ๊ตฌํ๋๋ฉด, ๊ณตํต ์ธํฐํ์ด์ค์ธ AudioTranscriptionModel์ด ์ถ์ถ๋์ด ์ ์ฉ๋ ์์ ์ ๋๋ค.
OpenAI Transcriptions
Spring AI๋ OpenAI์ ์์ฑ-ํ ์คํธ ๋ณํ ๋ชจ๋ธ์ ์ง์ํฉ๋๋ค.
์ฌ์ ์ค๋น ์ฌํญ
ChatGPT ๋ชจ๋ธ์ ์ ๊ทผํ๋ ค๋ฉด OpenAI API ํค๋ฅผ ์์ฑํด์ผ ํฉ๋๋ค. OpenAI ํ์๊ฐ์ ํ์ด์ง์์ ๊ณ์ ์ ์์ฑํ๊ณ , API Keys ํ์ด์ง์์ ํ ํฐ (API Key)์ ์์ฑํ์ธ์. Spring AI ํ๋ก์ ํธ์์๋ spring.ai.openai.api-keys๋ผ๋ ๊ตฌ์ฑ ์์ฑ์ ์ฌ์ฉํ์ฌ ์ด API ํค ๊ฐ์ ์ค์ ํ๋๋ก ์ ์๋์ด ์์ต๋๋ค. ํ๊ฒฝ ๋ณ์ ๋ด๋ณด๋ด๊ธฐ๋ ํด๋น ๊ตฌ์ฑ ์์ฑ์ ์ค์ ํ๋ ํ ๊ฐ์ง ๋ฐฉ๋ฒ์ ๋๋ค.
์๋ ๊ตฌ์ฑ
์ฐธ๊ณ
Spring AI์ ์๋ ๊ตฌ์ฑ ๋ฐ ์คํํฐ ๋ชจ๋ ์ํฐํฉํธ ์ด๋ฆ์ด ๋ณ๊ฒฝ๋์์ต๋๋ค. ์ ๊ทธ๋ ์ด๋ ๋ ธํธ๋ฅผ ์ฐธ์กฐํ์ธ์.
Spring AI๋ OpenAI Transcription Client์ ๋ํ 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.openai๋ OpenAI์ ์ฐ๊ฒฐํ๊ธฐ ์ํ ๊ตฌ์ฑ ์์ฑ์ ์ ๋์ด๋ก ์ฌ์ฉ๋ฉ๋๋ค.
ํ๋กํผํฐ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
spring.ai.openai.base-url | OpenAI์ ์ฐ๊ฒฐํ URL | api.openai.com |
spring.ai.openai.api-key | OpenAI API ํค | |
spring.ai.openai.organization-id | API ์์ฒญ ์ ์ฌ์ฉํ ์กฐ์ง (์ ํ ์ฌํญ) | |
spring.ai.openai.project-id | API ์์ฒญ ์ ์ฌ์ฉํ ํ๋ก์ ํธ (์ ํ ์ฌํญ) |
ํ
์ฌ๋ฌ ์กฐ์ง์ ์์๋์ด ์๊ฑฐ๋, ๋ ๊ฑฐ์ ์ฌ์ฉ์ API ํค๋ฅผ ํตํด ํ๋ก์ ํธ์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ์๋ API ์์ฒญ ์ ์ฌ์ฉํ ์กฐ์ง ID์ ํ๋ก์ ํธ ID๋ฅผ ๋ช ์ํ ์ ์์ต๋๋ค. ์ด๋ ๊ฒ ์ค์ ํ๋ฉด, ํด๋น ์์ฒญ์ ์ง์ ๋ ์กฐ์ง ๋ฐ ํ๋ก์ ํธ์ ์ฌ์ฉ๋์ผ๋ก ์ง๊ณ๋ฉ๋๋ค.
๊ตฌ์ฑ ์์ฑ
์ฐธ๊ณ
์ค๋์ค ํธ๋์คํฌ๋ฆฝ์ ์๋ ๊ตฌ์ฑ์ ํ์ฑํ ๋ฐ ๋นํ์ฑํ๋ ์ด์ spring.ai.model.audio.transcription ์ ๋์ด๋ฅผ ๊ฐ๋ ์ต์์ ์์ฑ์ ํตํด ์ค์ ๋ฉ๋๋ค.
ํ์ฑํํ๋ ค๋ฉด: spring.ai.model.audio.transcription=openai (๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ์ฑํ๋จ)
๋นํ์ฑํํ๋ ค๋ฉด: spring.ai.model.audio.transcription=none (๋๋ openai์ ์ผ์นํ์ง ์๋ ์์์ ๊ฐ)
์ด ๋ณ๊ฒฝ์ ์ฌ๋ฌ ๋ชจ๋ธ์ ๋์์ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๊ธฐ ์ํด ๋์ ๋์์ต๋๋ค.
spring.ai.openai.audio.transcription ์ ๋์ด๋ OpenAI ์์ฑ-ํ ์คํธ ๋ณํ ๋ชจ๋ธ์ ์ฌ์๋ (retry) ๋ฉ์ปค๋์ฆ์ ๊ตฌ์ฑํ ๋ ์ฌ์ฉํ๋ ์ค์ ์ ๋์ด์ ๋๋ค.
ํ๋กํผํฐ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
spring.ai.model.audio.transcription | OpenAI ์ค๋์ค ํธ๋์คํฌ๋ฆฝ์ ๋ชจ๋ธ ํ์ฑํ ์ฌ๋ถ | openai |
spring.ai.openai.audio.transcription.base-url | ์ฐ๊ฒฐํ OpenAI API์ URL | api.openai.com |
spring.ai.openai.audio.transcription.api-key | OpenAI API ํค | |
spring.ai.openai.audio.transcription.organization-id | API ์์ฒญ ์ ์ฌ์ฉํ ์กฐ์ง (์ ํ ์ฌํญ) | |
spring.ai.openai.audio.transcription.project-id | API ์์ฒญ ์ ์ฌ์ฉํ ํ๋ก์ ํธ (์ ํ ์ฌํญ) | |
spring.ai.openai.audio.transcription.options.model | ์ฌ์ฉํ ๋ชจ๋ธ์ ID (ํ์ฌ๋ ์คํ์์ค Whisper V2 ๊ธฐ๋ฐ์ whisper-1๋ง ์ฌ์ฉ ๊ฐ๋ฅ) | whisper |
spring.ai.openai.audio.transcription.options.response-format | ์ถ๋ ฅ ํฌ๋งท (์ ํ ๊ฐ๋ฅ: json, text, srt, verbose_json, vtt) | json |
spring.ai.openai.audio.transcription.options.prompt | ๋ชจ๋ธ์ ์คํ์ผ์ ์ ๋ํ๊ฑฐ๋ ์ด์ ์ค๋์ค ๊ตฌ๊ฐ์ ์ด์ด๊ฐ๊ธฐ ์ํ ์ ํ์ ํ๋กฌํํธ (์ค๋์ค ์ธ์ด์ ์ผ์นํด์ผ ํจ) | |
spring.ai.openai.audio.transcription.options.language | ์ ๋ ฅ ์ค๋์ค์ ์ธ์ด (ISO-639-1 ํฌ๋งท ๊ถ์ฅ, ์ ํ๋ ๋ฐ ์๋ ํฅ์์ ๋์) | |
spring.ai.openai.audio.transcription.options.temperature | ์ํ๋ง ์จ๋ (0~1 ์ฌ์ด ๊ฐ. ๋์์๋ก ๋๋ค, ๋ฎ์์๋ก ๊ฒฐ์ ์ . 0์ผ ๊ฒฝ์ฐ ์๋ ์กฐ์ ๋จ) | 0 |
spring.ai.openai.audio.transcription.options.timestamp_granularities | ํ์์คํฌํ ์ธ๋ถํ ์์ค ์ง์ (response_format์ด verbose_json์ผ ๋๋ง ์ฌ์ฉ ๊ฐ๋ฅ). word, segment ์ค ํ๋ ๋๋ ๋ ๋ค ์ฌ์ฉ ๊ฐ๋ฅ. ์ฐธ๊ณ : segment๋ ์ถ๊ฐ ์ง์ฐ ์์, word๋ ์ง์ฐ ๋ฐ์ ๊ฐ๋ฅ | segment |
์ฐธ๊ณ
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, api-key, organization-id, project-id๋ก ๊ฐ๋ณ์ ์ผ๋ก ์ค๋ฒ๋ผ์ด๋(์ฌ์ ์)ํ ์ ์์ต๋๋ค. ์ด๋ฌํ ์ค์ ์ ์๋ก ๋ค๋ฅธ ๋ชจ๋ธ ๋๋ ์๋ํฌ์ธํธ์์ OpenAI ๊ณ์ ์ ๋ถ๋ฆฌํ์ฌ ์ฌ์ฉํ ๊ฒฝ์ฐ ์ ์ฉํฉ๋๋ค.
ํ
spring.ai.openai.transcription.options ์ ๋์ด๋ก ์์ํ๋ ๋ชจ๋ ์์ฑ์ ๋ฐํ์ ์ค์๋ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
๋ฐํ์ ์ต์
OpenAiAudioTranscriptionOptions ํด๋์ค๋ ์์ฑ-ํ ์คํธ ๋ณํ ์์ฒญ ์ ์ฌ์ฉํ ์ต์ ์ ์ ๊ณตํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์๋ spring.ai.openai.audio.transcription์ ์ง์ ๋ ์ค์ ๊ฐ์ด ์ฌ์ฉ๋์ง๋ง, ์ด ์ค์ ๋ค์ ๋ฐํ์ (runtime)์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
๋ค์์ ์์์ ๋๋ค.
OpenAiAudioApi.TranscriptResponseFormat responseFormat = OpenAiAudioApi.TranscriptResponseFormat.VTT;
OpenAiAudioTranscriptionOptions transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
.language("en")
.prompt("Ask not this, but ask that")
.temperature(0f)
.responseFormat(this.responseFormat)
.build();
AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(audioFile, this.transcriptionOptions);
AudioTranscriptionResponse response = openAiTranscriptionModel.call(this.transcriptionRequest);
์๋ ๊ตฌ์ฑ
spring-ai-openai ์ข ์์ฑ์ ํ๋ก์ ํธ์ Maven pom.xml์ ๋ฑ๋กํ์ธ์.
<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 openAiAudioApi = new OpenAiAudioApi(System.getenv("OPENAI_API_KEY"));
var openAiAudioTranscriptionModel = new OpenAiAudioTranscriptionModel(this.openAiAudioApi);
var transcriptionOptions = OpenAiAudioTranscriptionOptions.builder()
.responseFormat(TranscriptResponseFormat.TEXT)
.temperature(0f)
.build();
var audioFile = new FileSystemResource("/path/to/your/resource/speech/jfk.flac");
AudioTranscriptionPrompt transcriptionRequest = new AudioTranscriptionPrompt(this.audioFile, this.transcriptionOptions);
AudioTranscriptionResponse response = openAiTranscriptionModel.call(this.transcriptionRequest);
์์ ์ฝ๋
OpenAiTranscriptionModelIT.java ํ ์คํธ ํด๋์ค๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ผ๋ฐ์ ์ธ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค.
ํ ์คํธ-์์ฑ ๋ณํ (Text-to-Speech) API
Spring AI๋ OpenAI์ ์์ฑ ์์ฑ (Speech) API๋ฅผ ์ง์ํฉ๋๋ค. ์ถ๊ฐ์ ์ธ ์ ๊ณต์๊ฐ ๊ตฌํ๋๋ฉด, ๊ณตํต ์ธํฐํ์ด์ค์ธ SpeechModel ๋ฐ StreamingSpeechModel์ด ์ถ์ถ๋์ด ์ ์ฉ๋ ์์ ์ ๋๋ค.
๊ฐ์
Audio API๋ OpenAI์ TTS(Text-to-Speech) ๋ชจ๋ธ์ ๊ธฐ๋ฐ์ผ๋ก ํ๋ ์์ฑ ์๋ํฌ์ธํธ๋ฅผ ์ ๊ณตํ๋ฉฐ, ์ฌ์ฉ์๋ ๋ค์๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ์ด์ฉํ ์ ์์ต๋๋ค:
- ์์ฑ๋ ๋ธ๋ก๊ทธ ๊ฒ์๊ธ์ ์์ฑ์ผ๋ก ๋ญ๋
- ๋ค์ํ ์ธ์ด๋ก ์์ฑ ์ค๋์ค ์์ฑ
- ์คํธ๋ฆฌ๋ฐ์ ํตํ ์ค์๊ฐ ์์ฑ ์ถ๋ ฅ
์ฌ์ ์ค๋น ์ฌํญ
- OpenAI ๊ณ์ ์ ์์ฑํ๊ณ API ํค๋ฅผ ๋ฐ๊ธ๋ฐ์ผ์ธ์. ํ์๊ฐ์ ์ OpenAI์ ํ์๊ฐ์ ํ์ด์ง์์ ํ ์ ์์ผ๋ฉฐ, API ํค ํ์ด์ง์์ API ํค๋ฅผ ์์ฑํ ์ ์์ต๋๋ค.
- ํ๋ก์ ํธ์ ๋น๋ ํ์ผ์ spring-ai-openai ์์กด์ฑ์ ์ถ๊ฐํ์ธ์. ์์ธํ ๋ด์ฉ์ Dependency Management ์น์ ์ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
์๋ ๊ตฌ์ฑ
Spring AI์ ์๋ ๊ตฌ์ฑ (auto-configuration) ๋ฐ ์คํํฐ ๋ชจ๋์ artifact ์ด๋ฆ์ ์ค์ํ ๋ณ๊ฒฝ ์ฌํญ์ด ์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์ ๊ทธ๋ ์ด๋ ๋ ธํธ๋ฅผ ์ฐธ๊ณ ํ์๊ธฐ ๋ฐ๋๋๋ค.
Spring AI๋ OpenAI Text-to-Speech ํด๋ผ์ด์ธํธ๋ฅผ ์ํ 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'
}
ํ
Dependency Management ์น์ ์ ์ฐธ๊ณ ํ์ฌ Spring AI BOM์ ๋น๋ ํ์ผ์ ์ถ๊ฐํ์ธ์.
Speech ์์ฑ
์ฐ๊ฒฐ ์์ฑ (Connection Properties)
spring.ai.openai๋ OpenAI์ ์ฐ๊ฒฐํ ์ ์๋๋ก ํด์ฃผ๋ ์์ฑ ์ ๋์ด์ ๋๋ค.
์์ฑ๋ช | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
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 ์์ฒญ ์ ์ฌ์ฉํ ํ๋ก์ ํธ๋ฅผ ์ง์ ํ ์ ์์ |
ํ
์ฌ๋ฌ ์กฐ์ง์ ์ํด ์๊ฑฐ๋ ๋ ๊ฑฐ์ ์ฌ์ฉ์ API ํค๋ฅผ ํตํด ํ๋ก์ ํธ์ ์ ๊ทผํ๋ ์ฌ์ฉ์๋ผ๋ฉด, organization-id์ project-id๋ฅผ ๋ช ์ํจ์ผ๋ก์จ ์ด๋ค ์กฐ์ง ๋ฐ ํ๋ก์ ํธ๋ก ์ฌ์ฉ๋์ด ์ง๊ณ๋ ์ง๋ฅผ ์ง์ ํ ์ ์์ต๋๋ค.
๊ตฌ์ฑ ์์ฑ (Configuration Properties)
์ฃผ์
์ค๋์ค ์คํผ์น ์๋ ๊ตฌ์ฑ์ ํ์ฑํ/๋นํ์ฑํ๋ ์ด์ ์ต์์ ์์ฑ ์ ๋์ด spring.ai.model.audio.speech๋ฅผ ํตํด ์ค์ ํฉ๋๋ค.
ํ์ฑํํ๋ ค๋ฉด: spring.ai.model.audio.speech=openai (๊ธฐ๋ณธ๊ฐ์ผ๋ก ํ์ฑํ๋จ)
๋นํ์ฑํํ๋ ค๋ฉด: spring.ai.model.audio.speech=none (๋๋ openai์ ์ผ์นํ์ง ์๋ ์๋ฌด ๊ฐ)
์ด ๋ณ๊ฒฝ์ ์ฌ๋ฌ ๋ชจ๋ธ์ ๊ตฌ์ฑํ ์ ์๋๋ก ํ๊ธฐ ์ํ ๊ฒ์ ๋๋ค.
spring.ai.openai.audio.speech๋ OpenAI Text-to-Speech ํด๋ผ์ด์ธํธ๋ฅผ ๊ตฌ์ฑํ ์ ์๋๋ก ํด์ฃผ๋ ์์ฑ ์ ๋์ด์ ๋๋ค.
์์ฑ๋ช | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
spring.ai.model.audio.speech | Audio Speech ๋ชจ๋ธ ํ์ฑํ ์ฌ๋ถ ์ง์ | openai |
spring.ai.openai.audio.speech.base-url | ์ฐ๊ฒฐํ URL | api.openai.com |
spring.ai.openai.audio.speech.api-key | OpenAI API ํค | - |
spring.ai.openai.audio.speech.organization-id | (์ ํ) API ์์ฒญ ์ ์ฌ์ฉํ ์กฐ์ง์ ์ง์ ํ ์ ์์ | - |
spring.ai.openai.audio.speech.project-id | (์ ํ) API ์์ฒญ ์ ์ฌ์ฉํ ํ๋ก์ ํธ๋ฅผ ์ง์ ํ ์ ์์ | - |
spring.ai.openai.audio.speech.options.model | ์ค๋์ค ์์ฑ์ ์ํด ์ฌ์ฉํ ๋ชจ๋ธ์ ID ์ ๋๋ค. OpenAI์ TTS API์์๋ ์ฌ์ฉ ๊ฐ๋ฅํ ๋ชจ๋ธ ์ค ํ๋์ธ tts-1 ๋๋ tts-1-hd๋ฅผ ์ง์ ํด์ผ ํฉ๋๋ค. | tts-1 |
spring.ai.openai.audio.speech.options.voice | ์์ฑ ํฉ์ฑ์ ์ฌ์ฉํ ๋ชฉ์๋ฆฌ (voice)๋ฅผ ์ง์ ํฉ๋๋ค. OpenAI์ TTS API์์๋ ์ ํํ ๋ชจ๋ธ์ ๋ฐ๋ผ ์ฌ์ฉํ ์ ์๋ ๋ชฉ์๋ฆฌ ์ค ํ๋๋ฅผ ์ง์ ํด์ผ ํ๋ฉฐ, ์ฌ์ฉ ๊ฐ๋ฅํ ๊ฐ์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค: alloy, echo, fable, onyx, nova, shimmer | alloy |
spring.ai.openai.audio.speech.options.response-format | ์ค๋์ค ์ถ๋ ฅ ํ์์ ์ง์ ํฉ๋๋ค. ์ง์๋๋ ํ์์ ๋ค์๊ณผ ๊ฐ์ต๋๋ค: mp3, opus, aac, flac, wav, pcm | mp3 |
spring.ai.openai.audio.speech.options.speed | ์์ฑ ํฉ์ฑ์ ์๋๋ฅผ ์ค์ ํฉ๋๋ค. ํ์ฉ ๊ฐ๋ฅํ ๋ฒ์๋ 0.25 (๊ฐ์ฅ ๋๋ฆผ)๋ถํฐ 4.0 (๊ฐ์ฅ ๋น ๋ฆ) ๊น์ง์ ๋๋ค. | 1.0 |
๊ณตํต ์์ฑ์ธ spring.ai.openai.base-url, spring.ai.openai.api-key, spring.ai.openai.organization-id, spring.ai.openai.project-id๋ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
๋์ , ์๋์ ๊ฐ์ ์ค๋์ค ์คํผ์น ์ ์ฉ ์์ฑ์ ์ค์ ํ๋ฉด ํด๋น ๊ฐ์ด ๊ณตํต ์์ฑ๋ณด๋ค ์ฐ์ ์ ์ฉ๋ฉ๋๋ค.
- spring.ai.openai.audio.speech.base-url
- spring.ai.openai.audio.speech.api-key
- spring.ai.openai.audio.speech.orgnanization-id
- spring.ai.openai.audio.speech.project-id
์ด ๊ธฐ๋ฅ์ ๋ชจ๋ธ๋ณ๋ก ๋ค๋ฅธ OpenAI ๊ณ์ ์ด๋ ์๋ํฌ์ธํธ๋ฅผ ์ฌ์ฉํ๊ณ ์ ํ ๋ ์ ์ฉํฉ๋๋ค.
ํ: spring.ai.openai.image.options ์ ๋์ด๋ก ์์ํ๋ ๋ชจ๋ ์์ฑ์ ๋ฐํ์์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
๋ฐํ์ ์ต์
OpenAiAudioSpeechOptions ํด๋์ค๋ ํ ์คํธ๋ฅผ ์์ฑ์ผ๋ก ๋ณํํ ๋ ์ฌ์ฉํ ์ต์ ๋ค์ ์ ๊ณตํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์ด ์์๋ ๋๋ spring.ai.openai.audio.speech์ ์ ์๋ ์ค์ ์ด ์ ์ฉ๋์ง๋ง, ๋ฐํ์์์ ํด๋น ์ต์ ์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
์๋ฅผ ๋ค์ด:
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.model("tts-1")
.voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.speed(1.0f)
.build();
SpeechPrompt speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", speechOptions);
SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
์๋ ๊ตฌ์ฑ (Manual Configuration)
ํ๋ก์ ํธ์ spring-ai-openai ์์กด์ฑ์ ์ถ๊ฐํ์ธ์:
Maven pom.xml
<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 ์น์ ์ ์ฐธ๊ณ ํ์ธ์.
๋ค์ ๋จ๊ณ๋ก OpenAiAudioSpeechModel ๊ฐ์ฒด๋ฅผ ์์ฑํ์ฌ ์ฌ์ฉํฉ๋๋ค.
var openAiAudioApi = new OpenAiAudioApi()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi);
var speechOptions = OpenAiAudioSpeechOptions.builder()
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.speed(1.0f)
.model(OpenAiAudioApi.TtsModel.TTS_1.value)
.build();
var speechPrompt = new SpeechPrompt("Hello, this is a text-to-speech example.", speechOptions);
SpeechResponse response = openAiAudioSpeechModel.call(speechPrompt);
// ๋ฉํ๋ฐ์ดํฐ (์์ฒญ ์ ํ ์ ๋ณด)์ ์ ๊ทผํ๊ธฐ
OpenAiAudioSpeechResponseMetadata metadata = response.getMetadata();
byte[] responseAsBytes = response.getResult().getOutput();
์ค์๊ฐ ์ค๋์ค ์คํธ๋ฆฌ๋ฐ
Speech API๋ ์ฒญํฌ ์ ์ก ์ธ์ฝ๋ฉ (chunk transfer encoding)์ ์ฌ์ฉํ์ฌ ์ค์๊ฐ ์ค๋์ค ์คํธ๋ฆฌ๋ฐ์ ์ง์ํฉ๋๋ค.
์ด๋ ์ ์ฒด ์ค๋์ค ํ์ผ์ด ์์ ํ ์์ฑ๋์ด ์ ๊ทผ ๊ฐ๋ฅํด์ง๊ธฐ ์ ์ ์ฌ์ํ ์ ์์์ ์๋ฏธํฉ๋๋ค.
var openAiAudioApi = new OpenAiAudioApi()
.apiKey(System.getenv("OPENAI_API_KEY"))
.build();
var openAiAudioSpeechModel = new OpenAiAudioSpeechModel(openAiAudioApi);
OpenAiAudioSpeechOptions speechOptions = OpenAiAudioSpeechOptions.builder()
.voice(OpenAiAudioApi.SpeechRequest.Voice.ALLOY)
.speed(1.0f)
.responseFormat(OpenAiAudioApi.SpeechRequest.AudioResponseFormat.MP3)
.model(OpenAiAudioApi.TtsModel.TTS_1.value)
.build();
SpeechPrompt speechPrompt = new SpeechPrompt("Today is a wonderful day to build something people love!", speechOptions);
Flux<SpeechResponse> responseStream = openAiAudioSpeechModel.stream(speechPrompt);
์์ ์ฝ๋
OpenAiSpeechModelIT.java ํ ์คํธ๋ ํด๋น ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ ๋ํ ์ผ๋ฐ์ ์ธ ์์ ๋ฅผ ์ ๊ณตํฉ๋๋ค.
Moderation Models (OpenAI)
Spring AI๋ OpenAI์ Moderation ๋ชจ๋ธ์ ์ง์ํฉ๋๋ค. ์ด ๋ชจ๋ธ์ ํตํด ํ ์คํธ ๋ด์ ์ ์ฌ์ ์ผ๋ก ์ ํดํ๊ฑฐ๋ ๋ฏผ๊ฐํ ์ฝํ ์ธ ๋ฅผ ๊ฐ์งํ ์ ์์ต๋๋ค. ์์ธํ ์ ๋ณด๋ OpenAI์ Moderation ๋ชจ๋ธ ๊ด๋ จ ๊ฐ์ด๋๋ฅผ ์ฐธ์กฐํ์ธ์.
์ฌ์ ์ค๋น ์ฌํญ
- OpenAI ๊ณ์ ์ ์์ฑํ๊ณ API ํค๋ฅผ ๋ฐ๊ธ๋ฐ์ต๋๋ค. OpenAI ํ์๊ฐ์ ํ์ด์ง์์ ๊ณ์ ์ ์์ฑํ๊ณ , API Keys ํ์ด์ง์์ API ํค๋ฅผ ์์ฑํ์ธ์.
- ํ๋ก์ ํธ์ ๋น๋ ํ์ผ์ spring-ai-openai ์์กด์ฑ์ ์ถ๊ฐํฉ๋๋ค. ์์ธํ ๋ด์ฉ์ ์์กด์ฑ ๊ด๋ฆฌ (Dependency Management) ์น์ ์ ์ฐธ์กฐํ์ธ์.
์๋ ๊ตฌ์ฑ
์ฐธ๊ณ
Spring AI์ ์๋ ๊ตฌ์ฑ ๋ฐฉ์ ๋ฐ ์คํํฐ ๋ชจ๋์ ์ํฐํฉํธ ์ด๋ฆ์ ์ค์ํ ๋ณ๊ฒฝ์ด ์์์ต๋๋ค. ์์ธํ ๋ด์ฉ์ ์ ๊ทธ๋ ์ด๋ ๋ ธํธ๋ฅผ ์ฐธ์กฐํ์ธ์.
Spring AI๋ OpenAI์ Text-to-Speech ํด๋ผ์ด์ธํธ์ ๋ํด 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 ์น์ ์ ์ฐธ๊ณ ํ์ธ์.
Moderation ์์ฑ
์ฐ๊ฒฐ ์์ฑ
spring.ai.openai๋ OpenAI์ ์ฐ๊ฒฐํ๊ธฐ ์ํ ์ค์ ์ ํ๋กํผํฐ ์ ๋์ด์ ๋๋ค.
ํ๋กํผํฐ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
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 ์์ฒญ์ ์ฌ์ฉํ ํ๋ก์ ํธ ์ง์ (์ ํ ์ฌํญ) |
ํ
์ฌ๋ฌ ์กฐ์ง์ ์์๋ ์ฌ์ฉ์์ด๊ฑฐ๋ ๋ ๊ฑฐ์ ์ฌ์ฉ์ API ํค๋ฅผ ํตํด ํ๋ก์ ํธ์ ์ ๊ทผํ๋ ๊ฒฝ์ฐ, ์์ฒญ ์ ์ฌ์ฉํ ์กฐ์ง ๋ฐ ํ๋ก์ ํธ๋ฅผ ๋ช ์ํ ์ ์์ต๋๋ค. ์ด ๊ฒฝ์ฐ ํด๋น ์กฐ์ง๊ณผ ํ๋ก์ ํธ์ ์ฌ์ฉ๋์ด ๊ธฐ๋ก๋ฉ๋๋ค.
๊ตฌ์ฑ ์์ฑ
์ฐธ๊ณ
์๋ฒ ๋ฉ ์๋ ๊ตฌ์ฑ์ ํ์ฑํ ์ฌ๋ถ๋ ์ด์ spring.ai.model.embedding ์ ๋์ด๋ฅผ ๊ฐ์ง ์ต์์ ํ๋กํผํฐ๋ก ์ค์ ํฉ๋๋ค.
ํ์ฑํ: spring.ai.model.moderation=openai (๊ธฐ๋ณธ๊ฐ)
๋นํ์ฑํ: spring.ai.model.moderation=none (๋๋ openai์ ์ผ์นํ์ง ์๋ ๊ฐ)
์ด ๋ณ๊ฒฝ์ ์ฌ๋ฌ ๋ชจ๋ธ์ ๊ตฌ์ฑ์ ์ง์ํ๊ธฐ ์ํจ์ ๋๋ค.
OpenAI์ Moderation ๋ชจ๋ธ์ ๊ตฌ์ฑํ ๋๋ ์ ๋์ด spring.ai.openai.moderation์ ์ฌ์ฉํฉ๋๋ค.
ํ๋กํผํฐ | ์ค๋ช | ๊ธฐ๋ณธ๊ฐ |
spring.ai.model.moderation | Moderation ๋ชจ๋ธ ํ์ฑํ ์ฌ๋ถ | openai |
spring.ai.openai.moderation.base-url | ์ฐ๊ฒฐํ URL | api.openai.com |
spring.ai.openai.moderation.api-key | API ํค | |
spring.ai.openai.moderation.organization-id | ์กฐ์ง ID (์ ํ ์ฌํญ) | |
spring.ai.openai.moderation.project-id | ํ๋ก์ ํธ ID (์ ํ ์ฌํญ) | |
spring.ai.openai.moderation.options.model | ์ฌ์ฉํ Moderation ๋ชจ๋ธ ID | text-moderation-latest |
์ฐธ๊ณ
๊ณตํต ์์ฑ (spring.ai.openai.base-url, api-key, organization-id, project-id)๋ณด๋ค Moderation ์ ์ฉ ์์ฑ (spring.ai.openai.moderation.*)์ด ์ฐ์ ์ ์ฉ๋ฉ๋๋ค. ์๋ก ๋ค๋ฅธ ๋ชจ๋ธ ๋๋ OpenAI ๊ณ์ ์ ์ฌ์ฉํ๊ณ ์ ํ ๋ ์ ์ฉํฉ๋๋ค.
ํ
spring.ai.openai.moderation.options.* ์ ๋์ด๋ก ์์ํ๋ ๋ชจ๋ ์์ฑ์ ๋ฐํ์์ ์ฌ์ ์ํ ์ ์์ต๋๋ค.
๋ฐํ์ ์ต์
OpenAiModerationOptions ํด๋์ค๋ Moderation ์์ฒญ ์ ์ฌ์ฉํ ์ต์ ์ ์ ์ํฉ๋๋ค. ์ ํ๋ฆฌ์ผ์ด์ ์์ ์์๋ spring.ai.openai.moderation์ ์ ์๋ ๊ฐ์ด ์ ์ฉ๋์ง๋ง, ์๋์ ๊ฐ์ด ๋ฐํ์์์ ์ฌ์ ์ํ ์๋ ์์ต๋๋ค.
OpenAiModerationOptions moderationOptions = OpenAiModerationOptions.builder()
.model("text-moderation-latest")
.build();
ModerationPrompt moderationPrompt = new ModerationPrompt("Text to be moderated", this.moderationOptions);
ModerationResponse response = openAiModerationModel.call(this.moderationPrompt);
// ๊ฒฐ๊ณผ ์ ๊ทผ
Moderation moderation = moderationResponse.getResult().getOutput();
// ์ผ๋ฐ ์ ๋ณด ์ถ๋ ฅ
System.out.println("Moderation ID: " + moderation.getId());
System.out.println("Model used: " + moderation.getModel());
// ๊ฒฐ๊ณผ ๋ฆฌ์คํธ (๋ณดํต ํ๋์ง๋ง ๋ฆฌ์คํธ ํํ)
for (ModerationResult result : moderation.getResults()) {
System.out.println("\nModeration Result:");
System.out.println("Flagged: " + result.isFlagged());
// ์นดํ
๊ณ ๋ฆฌ ์ ๊ทผ
Categories categories = result.getCategories();
System.out.println("\nCategories:");
System.out.println("Sexual: " + categories.isSexual());
System.out.println("Hate: " + categories.isHate());
System.out.println("Harassment: " + categories.isHarassment());
System.out.println("Self-Harm: " + categories.isSelfHarm());
System.out.println("Sexual/Minors: " + categories.isSexualMinors());
System.out.println("Hate/Threatening: " + categories.isHateThreatening());
System.out.println("Violence/Graphic: " + categories.isViolenceGraphic());
System.out.println("Self-Harm/Intent: " + categories.isSelfHarmIntent());
System.out.println("Self-Harm/Instructions: " + categories.isSelfHarmInstructions());
System.out.println("Harassment/Threatening: " + categories.isHarassmentThreatening());
System.out.println("Violence: " + categories.isViolence());
// ์นดํ
๊ณ ๋ฆฌ ์ ์ ์ ๊ทผ
CategoryScores scores = result.getCategoryScores();
System.out.println("\nCategory Scores:");
System.out.println("Sexual: " + scores.getSexual());
System.out.println("Hate: " + scores.getHate());
System.out.println("Harassment: " + scores.getHarassment());
System.out.println("Self-Harm: " + scores.getSelfHarm());
System.out.println("Sexual/Minors: " + scores.getSexualMinors());
System.out.println("Hate/Threatening: " + scores.getHateThreatening());
System.out.println("Violence/Graphic: " + scores.getViolenceGraphic());
System.out.println("Self-Harm/Intent: " + scores.getSelfHarmIntent());
System.out.println("Self-Harm/Instructions: " + scores.getSelfHarmInstructions());
System.out.println("Harassment/Threatening: " + scores.getHarassmentThreatening());
System.out.println("Violence: " + scores.getViolence());
}
์๋ ๊ตฌ์ฑ
Maven pom.xml ๋๋ Gradle build.gradle ํ์ผ์ sprint-ai-openai ์์กด์ฑ์ ์ถ๊ฐํ์ธ์.
<dependency>
<groupId>org.springframework.ai</groupId>
<artifactId>spring-ai-openai</artifactId>
</dependency>
dependencies {
implementation 'org.springframework.ai:spring-ai-openai'
}
ํ
Spring AI BOM์ build ํ์ผ์ ์ถ๊ฐํ๋ ๋ฐฉ๋ฒ์ Dependency Management ์น์ ์ ์ฐธ์กฐํ์ธ์.
๋ค์์ผ๋ก OpenAiModerationModel์ ์์ฑํฉ๋๋ค.
OpenAiModerationApi openAiModerationApi = new OpenAiModerationApi(System.getenv("OPENAI_API_KEY"));
OpenAiModerationModel openAiModerationModel = new OpenAiModerationModel(this.openAiModerationApi);
OpenAiModerationOptions moderationOptions = OpenAiModerationOptions.builder()
.model("text-moderation-latest")
.build();
ModerationPrompt moderationPrompt = new ModerationPrompt("Text to be moderated", this.moderationOptions);
ModerationResponse response = this.openAiModerationModel.call(this.moderationPrompt);
์์ ์ฝ๋
OpenAiModerationModelIT ํ ์คํธ ํด๋์ค๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ๋ฅผ ์ฌ์ฉํ๋ ์ผ๋ฐ์ ์ธ ์์๋ฅผ ์ ๊ณตํฉ๋๋ค. ๋ ์์ธํ ์ฌ์ฉ๋ฒ์ ํด๋น ํ ์คํธ๋ฅผ ์ฐธ๊ณ ํ ์ ์์ต๋๋ค.
Reference
'๐ ๊ณต์ ๋ฌธ์ ๋ฒ์ญ > Spring AI (2025 Renewal)' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[Spring AI 2025 Renewal #7] Tool Calling (4) | 2025.05.25 |
---|---|
[Spring AI 2025 Renewal #6] Chat Memory (0) | 2025.05.17 |
[Spring AI 2025 Renewal #4] Chat Models & Image Models (1) | 2025.04.12 |
[Spring AI 2025 Renewal #3] Advisors API (0) | 2025.04.06 |
[Spring AI 2025 Renewal #2] Chat Client API (0) | 2025.04.04 |