Education*
Devops
Architecture
F/B End
B.Chain
Basic
Others
CLOSE
Search For:
Search
BY TAGS
linux
HTTP
golang
flutter
java
fintech
개발환경
kubernetes
network
Docker
devops
database
tutorial
cli
분산시스템
www
블록체인
AWS
system admin
bigdata
보안
금융
msa
mysql
redis
Linux command
dns
javascript
CICD
VPC
FILESYSTEM
S3
NGINX
TCP/IP
ZOOKEEPER
NOSQL
IAC
CLOUD
TERRAFORM
logging
IT용어
Kafka
docker-compose
Dart
Vertex Gemini 기반 AI 에이전트 개발 06. LLM Native Application 개발
Recommanded
Free
YOUTUBE Lecture:
<% selectedImage[1] %>
yundream
2025-04-01
2025-04-01
61
[◀️ 첫 번째 LLM 애플리케이션 개발](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-005) [📑 목차](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-001) ## LLM Native Application **LLM Native Application(이하 LLM 애플리케이션)** 은 대규모 언어 모델을 중심으로 두고 설계된 애플리케이션을 의미한다. 단순히 LLM을 도구로 사용하는 것에서 더 나아가서 애플리케이션 아키텍처, UX/UI, 비즈니스 로직의 핵심을 LLM으로 구현한다. LLM 애플리케이션의 주요 특징은 아래와 같다. ✅ LLM 중심 아키텍처 * LLM의 기능에 의존하기 때문에 문서 요약 및 분석, 질의 응답, 창작, 코드 생성, 대화에 특화된다. * 프롬프트 엔지니어링과 **RAG(Retrieval-Agumented Generation)** 기술이 핵심 구성 요소다. ✅ 사용자 경험 * **자연어 인터페이스(Natural Language Interface)** 를 통해 사용자와 상호작용한다. 음성으로 확대될 수도 있다. * 전통적인 메뉴 기반 UI 대신 대화형 챗봇이나 AI 비서 형태로 구현된다. ✅ 데이터 중심 * 기업의 데이터를 LLM과 결합하여 맞춤형 응답을 제공한다. * **벡터 데이터베이스(Vector Database)** 를 사용해 의미 기반으로 검색 정확도를 높인다. ✅ 멀티모달 * 텍스트 뿐만 아니라 이미지, 오디오, 동영상 등 다양한 데이터를 처리 할 수 있다. LLM 애플리케이션의 핵심 구성 요소는 아래와 같다. * LLM Core: Vectex Gemini, OpenAI GPT, Meta Llama 등의 언어 모델. * API 및 오케스트레이션: LLM 애플리케이션은 자연어를 다루는 애플리케이션이다. 따라서 사용자의 의도를 파악하고 이를 기반으로 LLM으로 부터 다양한 기능들을 끄집어 내야 한다. 개발자는 LangChain, LlamaIndex, Vertex AI Agent Builder 등 다양한 툴을 이용하여 오케스트레이션 할 수 있다.  ## Streamlit를 이용한 ChatBot 개발 [첫 번째 LLM 애플리케이션 개발](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-005) 포스트에서 python을 이용하여 간단한 LLM 애플리케이션을 만들었지만, LLM API를 연동하는 수준에 지나지 않았다. 이제 실제 **ChatBot** 처럼 보이는 애플리케이션을 개발해 보자. ##### Streamlit Vertex AI Gemini 는 사용자의 **Input**을 받아서 **Output** 을 리턴하는 "간단한" API를 제공한다. 이 API를 가지고 그럴듯한 애플리케이션을 만드는 것은 개발자의 역할이다. 그럴듯한 (웹 기반)챗봇 애플리케이션을 만들려면, 서버뿐만 아니라 Chat을 주고 받을 수 있는 UI를 만들어야 하는데, 많은 시간이 걸린다. 완전한 챗봇 애플리케이션을 만들기 위해서는 React.js, Vue.js, 등의 프레임워크를 이용해야 겠는데 여기에서는 **Streamlit**을 이용해서 빠르게 구현해보도록 하겠다. **Streamlit**는 빠르게 웹 애플리케이션을 개발 할 수 있도록 도와주는 **오픈소스 프레임워크**다. Python을 이용해서 간단하게 웹 애플리케이션을 구축 할 수 있는데, 차트 등을 쉽게 구현할 수 있어서 데이터 분석가와 머신러닝 엔지니어가 많이 사용하고 있다. ### 코드 python 가상 환경을 만든다. ``` mkdir streamlit-demo-app cd streamlit-demo-app virtuenenv venv ``` 패키지를 설치한다. ``` pip install streamlit pip install genai pip install dotenv ``` ```python import os from google import genai from google.genai import types import streamlit as st from dotenv import load_dotenv load_dotenv() client = genai.Client( vertexai=True, project=os.getenv("PROJECT_ID"), location=os.getenv("LOCATION"), ) def generate(client, user_input, st: st): model = "gemini-2.0-flash-001" contents = [ types.Content( role="user", parts=[ types.Part.from_text(text=user_input) ] ) ] full_response="" response_placeholder = st.empty() for chunk in client.models.generate_content_stream( model = model, contents = contents, ): if chunk.text: full_response += chunk.text response_placeholder.markdown(full_response + "...") response_placeholder.markdown(full_response) st.title("Vertex AI Gemini 데모 애플리케이션") user_input = st.text_input("ChatBot과 대화를 해보세요:", key="user_input") if user_input: try: generate(client=client, user_input=user_input, st=st) except Exception as e: st.write(f"Error: {e}") ``` .env 에서 관리하는 환경변수는 아래와 같다. ``` PROJECT_ID=my-llm-app-xxxxxxx LOCATION=us-central1 ``` * PROJECT_ID: GCP Project ID * LOCATION: Gemini를 호출할 지역 이제 코드의 주요한 부분을 분석해보자. ```python client = genai.Client( vertexai=True, project=os.getenv("PROJECT_ID"), location=os.getenv("LOCATION"), ) ``` 이 코드는 Vertex AI Gemini 모델을 사용하기 위해서 클라이언트 객체를 초기화하는 부분이다. * vertexai=True: Vertex AI를 사용하여 Gemini 모델에 접근한다는 것을 명시한다. * project & location: .env 의 환경변수를 읽어서 프로젝트 아이디와 지역을 설정했다. ```python def generate(client, user_input, st: st): model = "gemini-2.0-flash-001" contents = [ types.Content( role="user", parts=[ types.Part.from_text(text=user_input) ] ) ] ``` * model: gemini-2.0-flash-001 모델을 사용하기로 했다. * contents: Gemini 모델에 전달할 컨텐츠(contents)을 정의한다. Gemini 모델은 이미지, 영상을 포함해서 여러 컨텐츠를 함께 처리할 수 있기 때문에 리스트 형태로 전달한다. * role="user": 컨텐츠의 역할을 "user"로 설정했다. 이는 사용자의 입력이라는 것을 모델에 알려준다. 이외에도 "model", "function" 롤이 있다. * model: 모델의 응답을 나타낸다. * function: 모델은 외부 API 등을 활용하여 다양한 작업을 수행 할 수 있다. 예를 들어 날씨 정보, 지역 정보 혹은 특정 웹사이트의 내용을 검색하는 등의 작업을 수행 할 수 있다. ```python full_response="" response_placeholder = st.empty() for chunk in client.models.generate_content_stream( model = model, contents = contents, ): if chunk.text: full_response += chunk.text response_placeholder.markdown(full_response + "...") response_placeholder.markdown(full_response) ``` LLM은 스트리밍 방식으로 콘텐츠를 전달하는데, 이를 통해서 대화하는 느낌으로 애플리케이션과 상호작용 할 수 있다. 이를 위해서 chunk 단위로 컨텐츠를 전달하는데, for 문에서 이를 처리하고 있다. ```python st.title("Vertex AI Gemini 데모 애플리케이션") user_input = st.text_input("ChatBot과 대화를 해보세요:", key="user_input") if user_input: try: generate(client=client, user_input=user_input, st=st) except Exception as e: st.write(f"Error: {e}") ``` * st.title: 타이틀을 설정한다. * st.txt_input: 텍스트 입력 창을 생성한다. * if user_input: 텍스트를 입력하고 엔터키를 누르면, generate 함수를 호출하여 Gemini와 대화를 시작한다. ##### 코드 실행 이 코드는 로컬 PC에서 실행되는데, 이를 위해서는 **Service Account** 를 생성하고 credentials 를 발급받아서 Vertex AI에 대한 권한을 확인해야 한다. 자세한 내용은[첫 번째 LLM 애플리케이션 개발](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-005) 문서를 참고하기 바란다. 코드를 실행해보자. ``` $ streamlit run app.py You can now view your Streamlit app in your browser. Local URL: http://localhost:8501 Network URL: http://192.168.35.177:8501 ``` 아래와 같이 웹 브라우저를 이용해서 테스트 할 수 있다.  ## Google Search Grounding 우리가 만든 앱을 이용해서 오늘이 몇 일인지 물어보자. 참고로 테스트를 하는 지금은 2025년 2월 22일이다. **Input** 오늘은 몇 일 인가요 ? **Output** 오늘(2024년 5월 16일)은 2024년 5월 16일 입니다. ---- 전혀 엉뚱한 답을 하고 있다. 이유는 LLM은 특정 시점까지 학습한 데이터만을 가지고 응답을 만들기 때문이다. 따라서 최신 정보에 대해서는 답을 할 수 없게 된다. Gemini는 이 문제를 **Search Grounding** 이라는 기능으로 해결하고 있다. **Grounding** 는 접지라는 뜻인데, 구글 검색 데이터를 기반으로 응답을 만드는 것이다. Grounding의 이점은 아래와 같다. * 모델이 사실과 다른 컨텐츠를 생성하는 **할루시네이션** 을 줄인다. * 문서에 대한 출처,인용을 제공하여 생성된 콘텐츠의 신뢰성을 향상시킨다. * 데이터 소스에 대한 모델 응답을 고정한다. 🚧 LLM에서 외부의 데이터를 기반으로 응답을 만들어 내는 것은 일반적으로 **RAG(Retrieval-Augmented Generation)** 라고 한다. 이런 점에서 Grounding은 사실상 RAG의 상품(혹은 기능)명 이라고 볼 수 있다. RAG는 다음 장에서 자세히 다룰 것이다. Grounding의 프로세스는 아래와 같다.  1. LLM Application에서 Message를 전송한다. 2. Vertex Gemini는 Google Search를 이용하여 인터넷 상에서 정보를 수집한다. 3. 수집된 정보를 요약하여 응답한다. 이때 출처와 추천 검색어도 함께 전송하여 신뢰성을 향상 시킨다. Grounding 을 이용해서 응답을 생성하도록 코드를 수정했다. ```python import os from google import genai from google.genai import types import streamlit as st from dotenv import load_dotenv load_dotenv() client = genai.Client( vertexai=True, project=os.getenv("PROJECT_ID"), location=os.getenv("LOCATION"), ) def generate(client, user_input, st: st): model = "gemini-2.0-flash-001" contents = [ types.Content( role="user", parts=[ types.Part.from_text(text=user_input) ] ) ] # Google Search Tool 추가 tools = [ types.Tool(google_search=types.GoogleSearch()) ] generate_content_content = types.GenerateContentConfig( temperature=0.5, top_p=0.95, max_output_tokens=8192, tools = tools, ) full_response = "" response_placeholder = st.empty() for chunk in client.models.generate_content_stream( model=model, contents=contents, config = generate_content_content, ): if chunk.text: full_response += chunk.text response_placeholder.markdown(full_response + "...") if chunk.candidates[0].content.parts[0].function_call: function_call = chunk.candidates[0].content.parts[0].function_call if function_call.name == "google_search": query = function_call.args["query"] # 검색 결과 처리 (실제 검색 API 호출은 필요에 따라 구현) search_results = f"Google Search 결과: {query} (검색 결과는 실제 구현에 따라 달라집니다.)" contents.append(types.Content(role="function", parts=[types.Part.from_text(text=search_results)])) generate(client, user_input, st) return response_placeholder.markdown(full_response) st.title("Vertex AI Gemini 데모 애플리케이션") user_input = st.text_input("ChatBot과 대화를 해보세요:", key="user_input") if user_input: try: generate(client=client, user_input=user_input, st=st) except Exception as e: st.write(f"Error: {e}") ``` Grounding을 적용하고 다시 테스트를 진행했다. **Input** 서울의 날씨를 알려주세요. **Output** 현재 서울의 날씨는 1°C입니다. 이번 주 서울의 날씨 예보는 다음과 같습니다. - 내일 (2월 23일): 0°C - 2월 24일 (월): 2°C - 2월 25일 (화): 6°C - 2월 26일 (수): 5°C - 2월 27일 (목): 9°C - 2월 28일 (금): 정보 없음 - 3월 1일 (토): 정보 없음 ---- 현재 시간을 기준으로 응답하는 것을 확인 할 수 있다. ### Function Calling LLM은 두뇌의 역할을 한다. 두뇌로 계획을 세운 다음 어떤 일을 하기 위해서는 "도구(Tool)"이 필요하다. Gemini의 Function Calling 기능은 쉽게 말해서 "**인공지능 비서가 필요할 때 도구를 불러다 쓸 수 있도록**" 해주는 기능이다. * 사용자의 요청을 이해하고, 어떤 툴이 필요한지 판단 * 어떤 툴이 필요한지 판다했다면, 툴을 실행해서 결과를 가져오고 사용자에게 필요한 답변을 제공 Function Calling은 아래와 같은 작업을 하는데 사용 할 수 있다. * "오늘 날씨 어때"라고 물으면 날쌔 앱을 실행하여 정보를 알려준다. * "부산에 호텔을 예약해줘"라고 요청하면 호텔 예약 사이트를 통해 예약을 진행한다. 아래는 Function Calling 예제다. 이 코드는 2개의 Function 을 가지고 있다. 1. get_current_weather_function: 특정 지역의 날씨를 가져온다. 2. get_stock_price_function: 특정 종목의 주가를 가져온다. ```python import os from google import genai from google.genai import types import streamlit as st from dotenv import load_dotenv load_dotenv() os.environ["GOOGLE_APPLICATION_CREDENTIALS"] = "./my-llm-app-448312-761e8905d65a.json" # 함수 정의 get_current_weather_function = { "name": "get_current_weather", "description": "특정 지역의 날씨 정보를 가져옵니다.", "parameters": { "type": "object", "properties": { "location": { "type": "string", "description": "날씨 정보를 알고 싶은 지역", } }, "required": ["location"], }, } get_stock_price_function = { "name": "get_stock_price", "description": "특정 주식의 현재 가격 정보를 가져옵니다.", "parameters": { "type": "object", "properties": { "stock_symbol": { "type": "string", "description": "주식 종목 코드 (예: AAPL, GOOG, TSLA, 005930.KS)", }, }, "required": ["stock_symbol"], }, } client = genai.Client( vertexai=True, project=os.getenv("PROJECT_ID"), location=os.getenv("LOCATION"), ) tools = types.Tool(function_declarations=[get_current_weather_function, get_stock_price_function]) config = types.GenerateContentConfig(tools=[tools]) def generate(client, user_input, config, st: st): model = "gemini-2.0-flash-001" contents = [ types.Content( role="user", parts=[ types.Part.from_text(text=user_input) ] ), ] response_placeholder = st.empty() response=client.models.generate_content( model=model, contents=contents, config=config, ) try: if response.candidates[0].content.parts[0].function_call: function_call = response.candidates[0].content.parts[0].function_call print(f"Function Name: {function_call.name}") print(f"Arguments: {function_call.args}") response_placeholder.markdown(f""" Fuction 을 호출했습니다. * Function Name: {function_call.name} * Arguments: {function_call.args}""") return else: response_placeholder.markdown("No function call found in the response.") return except Exception as e: print(f">> Error: {e}") response_placeholder.markdown(response.text) st.title("Vertex AI Gemini 데모 애플리케이션") user_input = st.text_input("ChatBot과 대화를 해보세요:", key="user_input") if user_input: try: input_text = user_input prompt = f""" {input_text} """ generate(client=client, user_input=prompt, config=config, st=st) except Exception as e: st.write(f"Error: {e}") ``` 코드를 실행해보자. ``` streamlit run functioncalling.py ``` 일상적인 대화는 LLM이 직접 답을 할 것이다. **Input** 리눅스 운영체제에 대해서 2 문단정도로 간단히 요약해주세요. **Output** 리눅스는 유닉스 계열의 오픈소스 운영체제입니다. 미니멀한 커널을 기반으로 다양한 기능을 모듈 형태로 추가하여 사용할 수 있으며, 이러한 모듈성 덕분에 임베디드 시스템부터 슈퍼컴퓨터까지 다양한 환경에서 사용됩니다. 또한 소스 코드가 공개되어 있어 누구나 수정 및 배포가 가능하고, 다양한 커뮤니티의 활발한 참여로 지속적인 발전이 이루어지고 있습니다. 사용자의 요구에 따라 시스템을 자유롭게 구성할 수 있는 유연성도 장점입니다. 리눅스는 마이크로소프트 윈도우나 macOS와 같이 상업적인 운영체제와는 달리, 무료로 사용할 수 있고, 개방적인 개발 방식으로 인해 커스터마이징이 용이합니다. 덕분에 서버 운영, 웹 개발, 데이터 분석 등 다양한 분야에서 널리 사용되고 있으며, 안드로이드 운영체제의 기반으로도 사용되는 등 그 영향력이 매우 큽니다. 꾸준한 업데이트를 통해 보안성과 안정성이 향상되고 있으며, 다양한 하드웨어를 지원하는 것도 특징입니다. 그러나 날씨나 주식에 관련된 질문을 하게 되면, 각 함수들이 호출된다. **Input** 서울 날씨 알려주세요. **Output** Fuction 을 호출했습니다. - Function Name: get_current_weather - Arguments: {'location': '서울'} **Input** 삼성 주가 알려주세요. **Output** Fuction 을 호출했습니다. - Function Name: get_stock_price - Arguments: {'stock_symbol': '005930.KS'} ## Function Calling을 외부 API와 연동하기 **Function Calling** 은 그 자체가 실제 어떤 작업을 하지는 않는다. "어떤 작업을 해야 할 지를 알아내는" 작업을 한다. 위의 코드는 1. 서울의 날씨를 궁금해 하는 구나 2. 삼성 주가를 궁금해 하는 구나 하는 의도를 파악하고 "서울", "삼성의 주식코드(005930.KS)"를 가져오는 것 까지가 역할이다. 따라서 실제 Weather API, Stock API와 연동하는 함수를 개발해야 한다. 아래는 예제코드다. 여기에서는 실제 구현을 다루지는 않을 것이다. ```python # 지역(location)의 날자를 가져오는 함수 def get_current_weather(location: str): try: response = requests.get(f"https://today.weather.com/api/weather?location={location}") # 주식 정보 API를 호출해서 주식 정보를 가져온다. def get_stock_price(stock_symbol: str): try: response = requests.get(f"https://stock.com/api/price?stock_symbol={stock_symbol}") ``` ## LangChain은 사용하지 않을 건가요 ? 아직 LLM 애플리케이션 개발에 뛰어들지 않았더라도 **LangChain**에 대해서 들어봤을 것이다. LangChain은 LLM을 활용하여 다양한 애플리케이션을 개발 할 수 있도록 도와주는 프레임워크다. 랭체인은 프롬프트관리, 체인, 에이전트 메모리, 문서 등 다양한 기능을 제공하며 이를 통해서 보다 쉽게 LLM 애플리케이션을 개발 할 수 있도록 지원하고 있다. LLM 기반 애플리케이션을 개발하겠다고 하면 항상 소개하는 것이 **LangChain** 이며, LangChaing 으로 시작하는 경우가 많다. 🚧 하지만 이 블로그 시리즈에서는 LangChain을 다루지 않을 것이다. 이 시리즈는 LLM 애플리케이션 개발이 목적이지 LangChain을 학습하는 것은 목적이 아니기 때문이다. 원리만 알고 있다면 LangChain을 이용해서 개발하든지, 기본적인 Gemini API(혹은 OpenAI API)를 이용해서 개발하던지 그건 중요하지 않다. ### 정리 LLM(Large Language Model) Native Application은 대규모 언어 모델을 중심으로 설계된 애플리케이션으로 텍스트, 코드, 오디오, 이미지, 비디오 등 다양한 데이터를 처리 할 수 있으며, 자연어 인터페이스를 통해서 사용자와 상호작용 할 수 있다. 여기에서는 Vertex AI Gemini 모델을 살펴보고, **streamlit** 을 이용해서 실제 ChatBot과 유사한 애플리케이션을 만드는 과정을 살펴봤다. 또한 Googl Search Grounding 기능을 이용해서 특정 시점까지 학습한 데이터만을 가지고 응답하는 한계를 극복하는 방법, Function Calling을 이용해서 사용자의 요청을 이해하고 필요한 도구를 호출하는 기능도 살펴봤다. 다음 글에서는 텍스트 외에 이미지, 동영상, 오디오 등 Gemini의 **멀티모달** 기능에 대해서 살펴볼 계획이다. [◀️ 첫 번째 LLM 애플리케이션 개발](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-005) [📑 목차](https://www.joinc.co.kr/w/LLM-NATIVE-APP-DEVELOP-001)
Recent Posts
Vertex Gemini 기반 AI 에이전트 개발 06. LLM Native Application 개발
최신 경량 LLM Gemma 3 테스트
MLOps with Joinc - Kubeflow 설치
Vertex Gemini 기반 AI 에이전트 개발 05. 첫 번째 LLM 애플리케이션 개발
LLama-3.2-Vision 테스트
Vertex Gemini 기반 AI 에이전트 개발 04. 프롬프트 엔지니어링
Vertex Gemini 기반 AI 에이전트 개발 03. Vertex AI Gemini 둘러보기
Vertex Gemini 기반 AI 에이전트 개발 02. 생성 AI에 대해서
Vertex Gemini 기반 AI 에이전트 개발 01. 소개
Vertex Gemini 기반 AI 에이전트 개발-소개
Archive Posts
Tags
LLM
vertex gemini 기반 AI Agent 개발
Copyrights © -
Joinc
, All Rights Reserved.
Inherited From -
Yundream
Rebranded By -
Joonphil
Recent Posts
Archive Posts
Tags