{"id":11428,"date":"2025-12-10T22:28:55","date_gmt":"2025-12-10T13:28:55","guid":{"rendered":"https:\/\/www.stechstar.com\/user\/wordpress\/?p=11428"},"modified":"2026-08-27T18:33:54","modified_gmt":"2026-08-27T09:33:54","slug":"%ec%9d%b8%ea%b3%b5%ec%a7%80%eb%8a%a5-%ea%b0%9c%eb%b0%9c%ec%9e%90-spring-ai%eb%a1%9c-llm-%ec%97%b0%ea%b2%b0%ed%95%98%ea%b8%b0feat-ollama","status":"publish","type":"post","link":"https:\/\/www.stechstar.com\/user\/wordpress\/%ec%9d%b8%ea%b3%b5%ec%a7%80%eb%8a%a5-%ea%b0%9c%eb%b0%9c%ec%9e%90-spring-ai%eb%a1%9c-llm-%ec%97%b0%ea%b2%b0%ed%95%98%ea%b8%b0feat-ollama\/","title":{"rendered":"[\uc778\uacf5\uc9c0\ub2a5 \uac1c\ubc1c\uc790] Spring AI\ub85c LLM \uc5f0\uacb0\ud558\uae30(Feat: ollama)"},"content":{"rendered":"<h1>[\uc778\uacf5\uc9c0\ub2a5 \uac1c\ubc1c\uc790] Spring AI\ub85c LLM \uc5f0\uacb0\ud558\uae30(Feat: ollama)<\/h1>\n<h2>\ub4e4\uc5b4\uac00\uba74\uc11c<\/h2>\n<p>\uc62c\ud574 \ucd08 LLM\uc5d0 \uad00\uc2ec\uc774 \uc0dd\uaca8 \uc774\uac83\uc800\uac83 \ucc3e\uc544\ubcf4\ub2e4\uac00 Spring AI\ub97c \uc54c\uac8c \ub418\uc5c8\uace0, \ucd5c\uadfc \uc815\uc2dd \ubc84\uc804\uc778&nbsp;<code>1.0.0<\/code>\uc774 \ucd9c\uc2dc\ub418\uba74\uc11c \ubcf8\uaca9\uc801\uc73c\ub85c \uacf5\ubd80\ud558\uac8c \ub418\uc5c8\uc2b5\ub2c8\ub2e4.<br \/>\n\uc81c\uac00 \ub290\ub07c\uae30\uc5d0 Spring AI\ub294 LLM \uc5f0\uacb0\uc744 \ub9e4\uc6b0 \uc27d\uac8c \ub3c4\uc640\uc8fc\uba70, \ub2e4\uc74c\uacfc \uac19\uc740 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4:<\/p>\n<ul>\n<li>\ud504\ub86c\ud504\ud2b8 \uc804\ucc98\ub9ac\/\ud6c4\ucc98\ub9ac\ub97c \uc704\ud55c&nbsp;Advisor<\/li>\n<li>JSON \u2192 DTO \uad6c\uc870\ud654 \ucd9c\ub825 \uc9c0\uc6d0<\/li>\n<li>LLM\uc774 \uba54\uc11c\ub4dc\ub97c \uc9c1\uc811 \ud638\ucd9c\ud558\ub294&nbsp;Function Calling<\/li>\n<li>RAG, MCP, \uba40\ud2f0\ubaa8\ub2ec \ub4f1 \ub2e4\uc591\ud55c \uace0\uae09 \uae30\ub2a5 \uc9c0\uc6d0<\/li>\n<\/ul>\n<p>\ub355\ubd84\uc5d0 \uc774\uc81c\ub294 Python \uae30\ubc18 \ub3c4\uad6c\uac00 \uc544\ub2c8\ub354\ub77c\ub3c4, Java \ud658\uacbd\uc5d0\uc11c\ub3c4 LLM\uc744 \ud6a8\uacfc\uc801\uc73c\ub85c \ud65c\uc6a9\ud560 \uc218 \uc788\uac8c \ub418\uc5c8\uc2b5\ub2c8\ub2e4.<br \/>\n\uc774 \ube14\ub85c\uadf8 \uc2dc\ub9ac\uc988\ub294 \ucd1d 3\ud3b8\uc73c\ub85c \uad6c\uc131\ub420 \uc608\uc815\uc774\uba70, \uac01 \uc8fc\uc81c\ub294 \ub2e4\uc74c\uacfc \uac19\uc2b5\ub2c8\ub2e4:<\/p>\n<ol>\n<li>Spring AI\ub85c LLM \uc5f0\uacb0\ud558\uace0 \uad6c\uc870\ud654\ub41c \ucd9c\ub825\ud558\uae30<\/li>\n<li><a href=\"https:\/\/zero-human.tistory.com\/11\" data-cke-saved-href=\"https:\/\/zero-human.tistory.com\/11\">Advisor\ub85c LLM\uc5d0 \ucd94\uac00 \uc815\ubcf4 \uc81c\uacf5 \ubc0f \uc751\ub2f5 \uac00\uacf5\ud558\uae30 (feat. RAG)<\/a><\/li>\n<li><a href=\"https:\/\/zero-human.tistory.com\/12\" data-cke-saved-href=\"https:\/\/zero-human.tistory.com\/12\">Function Calling\uc73c\ub85c LLM\uc5d0\uac8c \uba54\uc11c\ub4dc \uc81c\uacf5\ud558\uae30 (feat. AI Agent)<\/a><br \/>\n\uc774\ubc88 \ud3ec\uc2a4\ud305\uc740 \uadf8 \uccab \ubc88\uc9f8 \uc8fc\uc81c\uc778&nbsp;\u201cSpring AI\ub85c LLM \uc5f0\uacb0\ud558\uace0 \uad6c\uc870\ud654\ub41c \ucd9c\ub825\ud558\uae30\u201d\uc785\ub2c8\ub2e4.<\/li>\n<\/ol>\n<hr>\n<h2>\uae30\ubcf8\uc801\uc778 \uc124\uc815\ubc95<\/h2>\n<p>Spring AI\ub294 \ub2e4\uc591\ud55c LLM \uc81c\uacf5\uc790(OpenAI, Azure, Ollama \ub4f1)\uc640 \uc5f0\ub3d9\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br \/>\n\uc800\ub294 \uc774 \ud3ec\uc2a4\ud305\uc5d0\uc11c&nbsp;\ub85c\uceec\uc5d0\uc11c \uc2e4\ud589 \uac00\ub2a5\ud55c \uc624\ud508\uc18c\uc2a4 \ud50c\ub7ab\ud3fc\uc778 Ollama\ub97c \uae30\uc900\uc73c\ub85c \uc124\uba85\ud558\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<ul>\n<li>\ucc38\uace0: Spring AI\ub294 Java 17 \uc774\uc0c1\ubd80\ud130 \uc9c0\uc6d0\ub429\ub2c8\ub2e4.<\/li>\n<\/ul>\n<p>Ollama\ub294 \ub2e4\uc591\ud55c \uc624\ud508\uc18c\uc2a4 LLM\uc744 PC\uc5d0 \uc9c1\uc811 \ub2e4\uc6b4\ub85c\ub4dc\ud558\uc5ec \uc2e4\ud589\ud560 \uc218 \uc788\ub294 \ud50c\ub7ab\ud3fc\uc785\ub2c8\ub2e4.<br \/>\n\ub530\ub77c\uc11c \uc678\ubd80\ub85c \uc720\ucd9c\ub418\uba74 \uc548 \ub418\ub294&nbsp;\uac1c\uc778\uc815\ubcf4\ub098 \ub300\uc678\ube44 \ubb38\uc11c\ub97c \ucc98\ub9ac\ud560 \ub54c \uc801\ud569\ud55c \uc120\ud0dd\uc774 \ub420 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"hljs xml\"> - \uc758\uc874\uc131 \ucd94\uac00 (Maven \uae30\uc900)\n<span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">dependency<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>org.springframework.ai<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">groupId<\/span>&gt;<\/span>\n    <span class=\"hljs-tag\">&lt;<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>spring-ai-starter-model-ollama<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">artifactId<\/span>&gt;<\/span>\n<span class=\"hljs-tag\">&lt;\/<span class=\"hljs-name\">dependency<\/span>&gt;<\/span><\/code><\/pre>\n<pre><code class=\"hljs csharp\"> - \uc124\uc815 \ud30c\uc77c \uae30\ubcf8\uc801\uc778 \uc124\uc815\n <span class=\"hljs-meta\"># Ollama \uc11c\ubc84 \uc8fc\uc18c<\/span>\nspring.ai.ollama.<span class=\"hljs-keyword\">base<\/span>-url=http:<span class=\"hljs-comment\">\/\/localhost:11434 <\/span>\n<span class=\"hljs-meta\"># \ubaa8\ub378 \ub2e4\uc6b4\ub85c\ub4dc \uc804\ub7b5(always, when_missing, never)<\/span>\nspring.ai.ollama.<span class=\"hljs-keyword\">init<\/span>.pull-model-strategy=when_missing\n<span class=\"hljs-meta\"># \uae30\ubcf8 \uc14b\ud305 llm\ubaa8\ub378<\/span>\nspring.ai.ollama.chat.model= qwen3:<span class=\"hljs-number\">1.7b<\/span> \n<span class=\"hljs-meta\"># \ucc3d\uc758\uc131 \uc870\uc808: \ub192\uc744\uc218\ub85d \uc790\uc720\ub85c\uc6b4 \uc751\ub2f5<\/span>\nspring.ai.ollama.chat.temperature= <span class=\"hljs-number\">0.8<\/span>\n<span class=\"hljs-meta\"># \ucd5c\ub300 \uc751\ub2f5 \ud1a0\ud070 \uc218<\/span>\nspring.ai.ollama.chat.max-tokens= <span class=\"hljs-number\">1024<\/span>\n<span class=\"hljs-meta\"># Embedding \ubaa8\ub378<\/span>\nspring.ai.ollama.embedding.model=bona\/bge-m3-korean<\/code><\/pre>\n<p>\ucd94\uac00\uc801\uc778 \uc124\uc815\uc5d0 \ub300\ud574\uc11c\ub294 url\uc5d0\uc11c \ud655\uc778 \uac00\ub2a5\ud569\ub2c8\ub2e4.<br \/>\n<a href=\"https:\/\/docs.spring.io\/spring-ai\/reference\/api\/chat\/ollama-chat.html#_chat_properties\" data-cke-saved-href=\"https:\/\/docs.spring.io\/spring-ai\/reference\/api\/chat\/ollama-chat.html#_chat_properties\">https:\/\/docs.spring.io\/spring-ai\/reference\/api\/chat\/ollama-chat.html#_chat_properties<\/a><\/p>\n<hr>\n<h2>\uc608\uc81c \ucf54\ub4dc<\/h2>\n<p>Spring AI\uc5d0\uc11c\ub294 LLM\uc758 \uc751\ub2f5\uc744 \ub450 \uac00\uc9c0 \ubc29\uc2dd\uc73c\ub85c \ubc1b\uc744 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<ol>\n<li>\ub2e8\uc77c \ucd9c\ub825 \ubc29\uc2dd: \ud55c \ubc88\uc5d0 \uc804\uccb4 \uc751\ub2f5\uc744 \ubc1b\uc544 \ucc98\ub9ac<\/li>\n<li>\uc2a4\ud2b8\ub9ac\ubc0d \ucd9c\ub825 \ubc29\uc2dd (Flux): LLM \uc751\ub2f5\uc744 \uc2e4\uc2dc\uac04\uc73c\ub85c \uc870\uac01 \ub2e8\uc704\ub85c \ubc1b\uae30<br \/>\n\uc608\uc81c\ub97c \ud1b5\ud574 \ub450 \ubc29\uc2dd\uc758 \uc0ac\uc6a9\ubc95\uacfc, JSON \uad6c\uc870\ud654\ub41c \ucd9c\ub825 \ubc29\uc2dd\uae4c\uc9c0 \ud568\uaed8 \uc0b4\ud3b4\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/li>\n<\/ol>\n<hr>\n<h3>???? ChatModel\uacfc ChatClient\uc758 \ucc28\uc774<\/h3>\n<p>Spring AI\uc5d0\ub294&nbsp;<code>ChatModel<\/code>\uacfc&nbsp;<code>ChatClient<\/code>\ub77c\ub294 \ub450 \uac1c\uc758 \uc8fc\uc694 \uad6c\uc131 \uc694\uc18c\uac00 \uc788\uc2b5\ub2c8\ub2e4.<\/p>\n<ul>\n<li>ChatModel: LLM\uacfc\uc758 \uc800\uc218\uc900 \ud1b5\uc2e0 \uc5ed\ud560\uc744 \ud569\ub2c8\ub2e4.<\/li>\n<li>ChatClient: ChatModel\uc744 \ub798\ud551\ud55c \uc0c1\uc704 \ub808\ubca8 API\ub85c, \ud504\ub86c\ud504\ud2b8 \uad6c\uc131, \uc751\ub2f5 \ucc98\ub9ac, Advisor, RAG \ub4f1 \ub2e4\uc591\ud55c \ud655\uc7a5 \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4.<\/li>\n<\/ul>\n<hr>\n<h3>\ub2e8\uc77c \ucd9c\ub825 \ubc29\uc2dd<\/h3>\n<pre><code class=\"hljs typescript\"><span class=\"hljs-meta\">@AllArgsConstructor<\/span>\n<span class=\"hljs-meta\">@RestController<\/span>\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ModelClient<\/span> <\/span>{\n\n    <span class=\"hljs-comment\">\/\/ Spring\uc774 OllamaChatModel \uad6c\ud604\uccb4 \uc790\ub3d9 \uc8fc\uc785<\/span>\n    <span class=\"hljs-keyword\">private<\/span> final ChatModel chatModel;\n\n    <span class=\"hljs-meta\">@GetMapping<\/span>(<span class=\"hljs-string\">\"\/v1\/model-client\"<\/span>)\n    <span class=\"hljs-keyword\">public<\/span> ChatResponse <span class=\"hljs-function\"><span class=\"hljs-title\">modelClientV1<\/span>(<span class=\"hljs-params\"><span class=\"hljs-meta\">@RequestParam<\/span>(<span class=\"hljs-string\">\"text\"<\/span>) <span class=\"hljs-built_in\">String<\/span> text<\/span>)<\/span> {\n\n        <span class=\"hljs-comment\">\/\/ \uc2dc\uc2a4\ud15c \uba54\uc2dc\uc9c0\ub294 LLM\uc774 \ubc18\ub4dc\uc2dc \uc9c0\ucf1c\uc57c \ud560 \uc9c0\uce68<\/span>\n        <span class=\"hljs-comment\">\/\/ \uc720\uc800 \uba54\uc2dc\uc9c0\ub294 \uc0ac\uc6a9\uc790\uc758 \uc785\ub825<\/span>\n        Prompt prompt = <span class=\"hljs-keyword\">new<\/span> Prompt(\n                List.of(\n                        <span class=\"hljs-keyword\">new<\/span> SystemMessage(<span class=\"hljs-string\">\"\ub108\ub294 \uce5c\uc808\ud55c AI \ube44\uc11c\uc57c. \uc808\ub300 \ucd94\ub860 \uacfc\uc815\uc744 \ubcf4\uc5ec\uc8fc\uc9c0 \ub9d0\uace0 \uc694\uc57d\ub9cc \uc751\ub2f5\ud574.\"<\/span>),\n                        <span class=\"hljs-keyword\">new<\/span> UserMessage(text)\n                ));\n\n        <span class=\"hljs-keyword\">return<\/span> ChatClient.create(chatModel)\n                .prompt(prompt)\n                .call()\n                .content(); <span class=\"hljs-comment\">\/\/ \uc804\uccb4 \uc751\ub2f5\uc744 \ud55c \ubc88\uc5d0 \ubc18\ud658<\/span>\n    }\n}<\/code><\/pre>\n<hr>\n<h3>\uc2a4\ud2b8\ub9ac\ubc0d \ucd9c\ub825 \ubc29\uc2dd (Flux)<\/h3>\n<p>\uc2a4\ud2b8\ub9ac\ubc0d \ubc29\uc2dd\uc740 \ucc44\ud305\ucc98\ub7fc \uc2e4\uc2dc\uac04\uc73c\ub85c \uc751\ub2f5\uc774 \ud544\uc694\ud55c UI\uc5d0 \uc801\ud569\ud569\ub2c8\ub2e4.<\/p>\n<pre><code class=\"hljs typescript\"><span class=\"hljs-meta\">@AllArgsConstructor<\/span>\n<span class=\"hljs-meta\">@RestController<\/span>\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ModelClient<\/span> <\/span>{\n\n  <span class=\"hljs-keyword\">private<\/span> final ChatModel chatModel;\n\n  <span class=\"hljs-meta\">@GetMapping<\/span>(value = <span class=\"hljs-string\">\"\/v2\/model-client\"<\/span>, produces = <span class=\"hljs-string\">\"text\/plain;charset=UTF-8\"<\/span>)\n  <span class=\"hljs-keyword\">public<\/span> Flux&lt;<span class=\"hljs-built_in\">String<\/span>&gt; <span class=\"hljs-function\"><span class=\"hljs-title\">getModelClientV2<\/span>(<span class=\"hljs-params\"><span class=\"hljs-meta\">@RequestParam<\/span>(<span class=\"hljs-string\">\"text\"<\/span>) <span class=\"hljs-built_in\">String<\/span> text<\/span>)<\/span> {\n\n      <span class=\"hljs-comment\">\/\/ \uc2dc\uc2a4\ud15c \uba54\uc2dc\uc9c0\ub294 LLM\uc774 \ubc18\ub4dc\uc2dc \uc9c0\ucf1c\uc57c \ud560 \uc9c0\uce68<\/span>\n      <span class=\"hljs-comment\">\/\/ \uc720\uc800 \uba54\uc2dc\uc9c0\ub294 \uc0ac\uc6a9\uc790\uc758 \uc785\ub825<\/span>\n      Prompt prompt = <span class=\"hljs-keyword\">new<\/span> Prompt(\n              List.of(\n                      <span class=\"hljs-keyword\">new<\/span> SystemMessage(<span class=\"hljs-string\">\"\ub108\ub294 \uce5c\uc808\ud55c AI \ube44\uc11c\uc57c\"<\/span>),\n                      <span class=\"hljs-keyword\">new<\/span> UserMessage(text)\n              ));\n\n      <span class=\"hljs-keyword\">return<\/span> ChatClient.create(<span class=\"hljs-built_in\">this<\/span>.chatModel)\n              .prompt(prompt)\n              .stream() <span class=\"hljs-comment\">\/\/ \uc2a4\ud2b8\ub9ac\ubc0d \uc751\ub2f5 \uc2dc\uc791<\/span>\n              .content(); <span class=\"hljs-comment\">\/\/ Flux&lt;String&gt;\uc73c\ub85c \uc2e4\uc2dc\uac04 \uc870\uac01 \uc751\ub2f5 \uc218\uc2e0<\/span>\n    }\n}<\/code><\/pre>\n<hr>\n<h3>\uad6c\uc870\ud654\ub41c \ucd9c\ub825 \ubc1b\uae30 (JSON \u2192 DTO)<\/h3>\n<p>\ub0b4\ubd80\uc801\uc73c\ub85c\ub294 LLM\uc5d0\uac8c &#8220;\uc774\ub7f0 \uad6c\uc870\ub85c \uc751\ub2f5\ud574\uc918&#8221;\ub77c\uace0 \uba85\uc2dc\ud55c \ud6c4 \uacb0\uacfc\ub97c DTO\uc5d0 \ubc14\uc778\ub529\ud569\ub2c8\ub2e4.<br \/>\n\ud558\uc9c0\ub9cc LLM\uc774 \ud574\ub2f9 \ud615\uc2dd\ub300\ub85c \uc815\ud655\ud558\uac8c \uc751\ub2f5\ud558\uc9c0 \uc54a\uc73c\uba74 \ud30c\uc2f1 \uc5d0\ub7ec\uac00 \ubc1c\uc0dd\ud560 \uc218 \uc788\uc2b5\ub2c8\ub2e4.<br \/>\n\uc548\uc815\uc131\uc744 \ub192\uc774\uae30 \uc704\ud574 \uc2dc\uc2a4\ud15c \uba54\uc2dc\uc9c0\uc5d0 \ud615\uc2dd\uc744 \ubc18\ubcf5\uc801\uc73c\ub85c \uba85\ud655\ud788 \uba85\uc2dc\ud558\uac70\ub098, \uad6c\uc870 \uc720\ub3c4 \ud504\ub86c\ud504\ud2b8 \uc608\uc81c\ub97c \ud568\uaed8 \uc81c\uacf5\ud558\ub294 \uac83\uc774 \uc88b\uc2b5\ub2c8\ub2e4.<\/p>\n<pre><code class=\"hljs php\">@AllArgsConstructor\n@RestController\n<span class=\"hljs-keyword\">public<\/span> <span class=\"hljs-class\"><span class=\"hljs-keyword\">class<\/span> <span class=\"hljs-title\">ModelClient<\/span> <\/span>{\n\n    <span class=\"hljs-keyword\">private<\/span> <span class=\"hljs-keyword\">final<\/span> ChatModel chatModel;\n\n    @GetMapping(<span class=\"hljs-string\">\"\/v3\/model-client\"<\/span>)\n    <span class=\"hljs-keyword\">public<\/span> ActorFilms modelClientV3(@RequestParam(<span class=\"hljs-string\">\"text\"<\/span>) <span class=\"hljs-keyword\">String<\/span> text) {\n\n        <span class=\"hljs-comment\">\/\/ \uc0ac\uc6a9\uc790 \uc785\ub825\uc744 \uc774\uc6a9\ud574 \ud504\ub86c\ud504\ud2b8 \ud15c\ud50c\ub9bf \uad6c\uc131<\/span>\n        <span class=\"hljs-keyword\">String<\/span> template = <span class=\"hljs-string\">\"\"<\/span><span class=\"hljs-string\">\"\n            Generate the filmography of 5 movies for {actor}.\n        \"<\/span><span class=\"hljs-string\">\"\"<\/span>;\n\n        Prompt prompt = <span class=\"hljs-keyword\">new<\/span> Prompt(\n                <span class=\"hljs-keyword\">List<\/span>.of(\n                        <span class=\"hljs-keyword\">new<\/span> SystemMessage(<span class=\"hljs-string\">\"\ub108\ub294 \uce5c\uc808\ud55c AI \ube44\uc11c\uc57c. \uc808\ub300 \ucd94\ub860 \uacfc\uc815\uc744 \ubcf4\uc5ec\uc8fc\uc9c0 \ub9d0\uace0 \uc694\uc57d\ub9cc \uc751\ub2f5\ud574.\"<\/span>),\n                        <span class=\"hljs-keyword\">new<\/span> UserMessage(<span class=\"hljs-keyword\">new<\/span> PromptTemplate(template).render(Map.of(<span class=\"hljs-string\">\"actor\"<\/span>, text)))\n                ));\n\n        ChatModel gemma = OllamaChatModel.builder()\n                .ollamaApi(OllamaApi.builder().build())\n                .defaultOptions(\n                        OllamaOptions.builder()\n                                .model(<span class=\"hljs-string\">\"gemma3n:e4b\"<\/span>)\n                                .temperature(<span class=\"hljs-number\">0.4<\/span>)\n                                .build())\n                .build();\n\n        <span class=\"hljs-keyword\">return<\/span> ChatClient.create(gemma)\n                .prompt(prompt)\n                .call()\n                .entity(ActorFilms.<span class=\"hljs-keyword\">class<\/span>); <span class=\"hljs-comment\">\/\/ \uacb0\uacfc\ub97c DTO\ub85c \uad6c\uc870\ud654<\/span>\n    }\n\n    record ActorFilms(<span class=\"hljs-keyword\">String<\/span> actor, <span class=\"hljs-keyword\">List<\/span>&lt;<span class=\"hljs-keyword\">String<\/span>&gt; movies) {}\n}\n\n\ud504\ub86c\ud504\ud2b8 \uc694\uccad \uc608\uc2dc (\ub0b4\ubd80 \ub3d9\uc791 \ud655\uc778\uc6a9)\nSpring AI\uac00 \uad6c\uc870\ud654 \ucd9c\ub825\uc744 \uc704\ud574 \ub0b4\ubd80\uc801\uc73c\ub85c LLM\uc5d0\uac8c \ub2e4\uc74c\uacfc \uac19\uc774 \uc694\uccad\uc744 \uad6c\uc131\ud569\ub2c8\ub2e4.\n\nrequest: ChatClientRequest[\n- \uc800\ud76c\uac00 \uc785\ub825\ud55c \uba85\ub839 \ud504\ub86c\ud504\ud2b8 \uc785\ub825\uc785\ub2c8\ub2e4.\nprompt=Prompt{\n    messages=[SystemMessage{textContent=<span class=\"hljs-string\">'\ub108\ub294 \uce5c\uc808\ud55c AI \ube44\uc11c\uc57c. \uc808\ub300 \ucd94\ub860\uacfc\uc815\uc744 \ubcf4\uc5ec\uc8fc\uc9c0 \ub9d0\uace0 \uc694\uc57d\ub9cc \uc751\ub2f5\ud574'<\/span>, messageType=SYSTEM, metadata={messageType=SYSTEM}}, \n    UserMessage{content=<span class=\"hljs-string\">'Generate the filmography of 5 movies for \ud558\uc815\uc6b0.'<\/span>, properties={messageType=USER}, messageType=USER}], modelOptions=org.springframework.ai.ollama.api.OllamaOptions@<span class=\"hljs-number\">48e29<\/span>a2c}, \n\n- \uc5ec\uae30\uc5d0 \ud574\ub2f9 DTO \uac1d\uccb4\uc758 \uc815\uc758\uac00 \ub4e4\uc5b4\uac11\ub2c8\ub2e4.\ncontext={spring.ai.chat.client.output.format=Your response should be in JSON format.\n<span class=\"hljs-keyword\">Do<\/span> not <span class=\"hljs-keyword\">include<\/span> any explanations, only provide a RFC8259 compliant JSON response following this format without deviation.\n<span class=\"hljs-keyword\">Do<\/span> not <span class=\"hljs-keyword\">include<\/span> markdown code blocks in your response.\nRemove the ```json markdown <span class=\"hljs-keyword\">from<\/span> the output.\nHere is the JSON Schema instance your output must adhere to:\n```{\n  <span class=\"hljs-string\">\"<span class=\"hljs-subst\">$schema<\/span>\"<\/span> : <span class=\"hljs-string\">\"https:\/\/json-schema.org\/draft\/2020-12\/schema\"<\/span>,\n  <span class=\"hljs-string\">\"type\"<\/span> : <span class=\"hljs-string\">\"object\"<\/span>,\n  <span class=\"hljs-string\">\"properties\"<\/span> : {\n    <span class=\"hljs-string\">\"actor\"<\/span> : {\n      <span class=\"hljs-string\">\"type\"<\/span> : <span class=\"hljs-string\">\"string\"<\/span>\n    },\n    <span class=\"hljs-string\">\"movies\"<\/span> : {\n      <span class=\"hljs-string\">\"type\"<\/span> : <span class=\"hljs-string\">\"array\"<\/span>,\n      <span class=\"hljs-string\">\"items\"<\/span> : {\n        <span class=\"hljs-string\">\"type\"<\/span> : <span class=\"hljs-string\">\"string\"<\/span>\n      }\n    }\n  },\n  <span class=\"hljs-string\">\"additionalProperties\"<\/span> : <span class=\"hljs-literal\">false<\/span>\n}```\n}]<\/code><\/pre>\n<hr>\n<h2>\ub9c8\uce58\uba70<\/h2>\n<p>AI\ub97c \uc2e4\uc81c \ud504\ub85c\uc81d\ud2b8\uc5d0 \ub3c4\uc785\ud558\ub294 \uac83\uc740 \uc5b4\ub835\uace0 \ubcf5\uc7a1\ud560 \uac83 \uac19\ub2e4\ub294 \ub9c9\uc5f0\ud55c \uc0dd\uac01\uc774 \uc788\uc5c8\uc9c0\ub9cc,<br \/>\nSpring AI\ub97c \ud1b5\ud574 Java \ud658\uacbd\uc5d0\uc11c\ub3c4 LLM\uc744 \uc190\uc27d\uac8c \uc5f0\uacb0\ud558\uace0 \ud65c\uc6a9\ud560 \uc218 \uc788\ub2e4\ub294 \uac00\ub2a5\uc131\uc744 \ud655\uc778\ud560 \uc218 \uc788\uc5c8\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\ubb3c\ub860 \uc131\ub2a5, \uc18d\ub3c4, \ud504\ub86c\ud504\ud2b8 \uc124\uacc4, \uc801\uc808\ud55c \ubaa8\ub378 \uc120\ud0dd \ub4f1 \uc2e4\ubb34\uc5d0\uc11c \uace0\ub824\ud560 \uc694\uc18c\ub4e4\uc740 \ub9ce\uc9c0\ub9cc,<br \/>\n\uc774\ubc88 \uc2e4\uc2b5\uc744 \ud1b5\ud574 LLM\uc744 \uc2e4\uc81c \uc11c\ube44\uc2a4\uc5d0 \uc801\uc6a9\ud558\ub294 \ucd9c\ubc1c\uc810\uc744 \uc7a1\uc744 \uc218 \uc788\uc5c8\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\ub2e4\uc74c \ud3ec\uc2a4\ud305\uc5d0\uc11c\ub294&nbsp;Advisor \uae30\ub2a5\uc744 \ud65c\uc6a9\ud574 LLM \uc751\ub2f5\uc744 \uac00\uacf5\ud558\uace0,<br \/>\n\uac04\ub2e8\ud55c&nbsp;RAG(Retrieval-Augmented Generation)&nbsp;\uae30\ub2a5\uc744 \uad6c\ud604\ud574\ubcf4\uaca0\uc2b5\ub2c8\ub2e4.<\/p>\n<p>\uc774 \uae30\ub2a5\uc740 Logging, \ud06c\ub864\ub9c1\ub41c \ubb38\uc11c, RDBMS \uc815\ubcf4 \ub4f1 \ub2e4\uc591\ud55c \uc678\ubd80 \uc9c0\uc2dd \uc18c\uc2a4\ub97c LLM\uacfc \uc5f0\uacb0\ud574<br \/>\n\ub354 \uc815\ud655\ud558\uace0 \uc2e0\ub8b0\ub3c4 \ub192\uc740 \uc751\ub2f5\uc744 \uc0dd\uc131\ud558\ub3c4\ub85d \ub3c4\uc640\uc8fc\ub294 \ubc29\uc2dd\uc785\ub2c8\ub2e4.<\/p>\n<p>\ud574\ub2f9 \uc608\uc2dc\ub294 github\uc5d0 \uc788\uc2b5\ub2c8\ub2e4.<br \/>\nurl:&nbsp;<a href=\"https:\/\/github.com\/Zero-Human\/springAi\" data-cke-saved-href=\"https:\/\/github.com\/Zero-Human\/springAi\">https:\/\/github.com\/Zero-Human\/springAi<\/a><\/p>\n<p>\ucc38\uace0\uc790\ub8cc<\/p>\n<ul>\n<li><a href=\"https:\/\/docs.spring.io\/spring-ai\/reference\/index.html\" data-cke-saved-href=\"https:\/\/docs.spring.io\/spring-ai\/reference\/index.html\">Spring AI \uacf5\uc2dd \ubb38\uc11c<\/a><\/li>\n<\/ul>\n<p>[\ucd9c\ucc98]&nbsp;https:\/\/zero-human.tistory.com\/9<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_11428\" class=\"pvc_stats all  \" data-element-id=\"11428\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/www.stechstar.com\/user\/wordpress\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"excerpt":{"rendered":"<p>[\uc778\uacf5\uc9c0\ub2a5 \uac1c\ubc1c\uc790] Spring AI\ub85c LLM \uc5f0\uacb0\ud558\uae30(Feat: ollama) \ub4e4\uc5b4\uac00\uba74\uc11c \uc62c\ud574 \ucd08 LLM\uc5d0 \uad00\uc2ec\uc774 \uc0dd\uaca8 \uc774\uac83\uc800\uac83 \ucc3e\uc544\ubcf4\ub2e4\uac00 Spring AI\ub97c \uc54c\uac8c \ub418\uc5c8\uace0, \ucd5c\uadfc \uc815\uc2dd \ubc84\uc804\uc778&nbsp;1.0.0\uc774 \ucd9c\uc2dc\ub418\uba74\uc11c \ubcf8\uaca9\uc801\uc73c\ub85c \uacf5\ubd80\ud558\uac8c \ub418\uc5c8\uc2b5\ub2c8\ub2e4. \uc81c\uac00 \ub290\ub07c\uae30\uc5d0 Spring AI\ub294 LLM \uc5f0\uacb0\uc744 \ub9e4\uc6b0 \uc27d\uac8c \ub3c4\uc640\uc8fc\uba70, \ub2e4\uc74c\uacfc \uac19\uc740 \ub2e4\uc591\ud55c \uae30\ub2a5\uc744 \uc81c\uacf5\ud569\ub2c8\ub2e4: \ud504\ub86c\ud504\ud2b8 \uc804\ucc98\ub9ac\/\ud6c4\ucc98\ub9ac\ub97c \uc704\ud55c&nbsp;Advisor JSON \u2192 DTO \uad6c\uc870\ud654 \ucd9c\ub825 \uc9c0\uc6d0 LLM\uc774 \uba54\uc11c\ub4dc\ub97c \uc9c1\uc811 \ud638\ucd9c\ud558\ub294&nbsp;Function Calling RAG, [&hellip;]<\/p>\n<div class=\"pvc_clear\"><\/div>\n<p id=\"pvc_stats_11428\" class=\"pvc_stats all  \" data-element-id=\"11428\" style=\"\"><i class=\"pvc-stats-icon medium\" aria-hidden=\"true\"><svg aria-hidden=\"true\" focusable=\"false\" data-prefix=\"far\" data-icon=\"chart-bar\" role=\"img\" xmlns=\"http:\/\/www.w3.org\/2000\/svg\" viewBox=\"0 0 512 512\" class=\"svg-inline--fa fa-chart-bar fa-w-16 fa-2x\"><path fill=\"currentColor\" d=\"M396.8 352h22.4c6.4 0 12.8-6.4 12.8-12.8V108.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v230.4c0 6.4 6.4 12.8 12.8 12.8zm-192 0h22.4c6.4 0 12.8-6.4 12.8-12.8V140.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v198.4c0 6.4 6.4 12.8 12.8 12.8zm96 0h22.4c6.4 0 12.8-6.4 12.8-12.8V204.8c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v134.4c0 6.4 6.4 12.8 12.8 12.8zM496 400H48V80c0-8.84-7.16-16-16-16H16C7.16 64 0 71.16 0 80v336c0 17.67 14.33 32 32 32h464c8.84 0 16-7.16 16-16v-16c0-8.84-7.16-16-16-16zm-387.2-48h22.4c6.4 0 12.8-6.4 12.8-12.8v-70.4c0-6.4-6.4-12.8-12.8-12.8h-22.4c-6.4 0-12.8 6.4-12.8 12.8v70.4c0 6.4 6.4 12.8 12.8 12.8z\" class=\"\"><\/path><\/svg><\/i> <img loading=\"lazy\" decoding=\"async\" width=\"16\" height=\"16\" alt=\"Loading\" src=\"https:\/\/www.stechstar.com\/user\/wordpress\/wp-content\/plugins\/page-views-count\/ajax-loader-2x.gif\" border=0 \/><\/p>\n<div class=\"pvc_clear\"><\/div>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"ngg_post_thumbnail":0,"footnotes":""},"categories":[21,24,20],"tags":[],"class_list":["post-11428","post","type-post","status-publish","format-standard","hentry","category-21","category-24","category-20"],"a3_pvc":{"activated":true,"total_views":16,"today_views":0},"_links":{"self":[{"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/posts\/11428","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/comments?post=11428"}],"version-history":[{"count":4,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/posts\/11428\/revisions"}],"predecessor-version":[{"id":12006,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/posts\/11428\/revisions\/12006"}],"wp:attachment":[{"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/media?parent=11428"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/categories?post=11428"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.stechstar.com\/user\/wordpress\/wp-json\/wp\/v2\/tags?post=11428"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}