1-1. 환경변수 설정

from dotenv import load_dotenv
from datetime import datetime, timedelta
from openai import OpenAI
import os

load_dotenv(override=True)

apikey = os.getenv("OPENAI_API_KEY")
default_model = os.getenv("OPENAI_DEFAULT_MODEL")

client = OpenAI(api_key=apikey)

 

1-2. 툴셋 파일

tools = [
    {
    "type":"function",
    "function" :{
        "name":"get_weather",
        "description":"오늘의 날씨를 알려주는 함수",
        "parameters":{
            "type":"object",
            "properties":{
                "location":{
                    "type":"string",
                    "description":"날씨를 알고 싶은 지역"
                },
            },
            "required":["location"]
        }
        }
    },
    {
    "type":"function",
    "function" : {
        "name" : "get_time",
        "description" : "현재 시간을 알려주는 함수",
        "parameters" : {
            "type" : "object",
            "properties" : {},
            "required" : []
        }
    },
}
]

 

1-3. 함수 선언

def get_weather(location):
    '''
    날씨를 가져오는 함수
    '''

    weather_data = {
        "서울": "맑음, 기온 25도",
        "부산": "맑음, 기온 30도",
        "대구": "맑음, 기온 20도",
        "인천": "맑음, 기온 21도"
    }

    return weather_data.get(location, f"{location}지역의 날씨 정보를 찾을 수 없습니다.")

def get_time():
    '''
    시간을 가져오는 함수
    '''

    time_data = {
        "현재" : datetime.now().strftime('%Y-%m-%d %H:%M:%S')
    }
    return time_data
available_functions = {
    "get_weather" : get_weather,
    "get_time" : get_time    
}

 

1-4. 실행파일

import json

tool_calls = response.choices[0].message.tool_calls

if tool_calls:
    for tool_call in tool_calls:  # 모든 tool_call을 반복 처리
        func_name = tool_call.function.name
        # print(f"처리 중인 함수: {func_name}")

        # get_weather 처리
        if func_name == "get_weather":
            try:
                args = json.loads(tool_call.function.arguments)
                if func_name in available_functions:
                    result = available_functions[func_name](**args)
                    print(f"날씨 정보: {result}")
            except json.JSONDecodeError:
                print("인자 파싱 오류")

        # get_time 처리
        elif func_name == "get_time":
            if func_name in available_functions:
                result = available_functions[func_name]()  # 파라미터 없음
                print(f"현재 시각: {result['현재']}")

 

output

 

2-1. 그라디오 기본셋팅

import gradio as gr

def greet(name):
    return f"안녕하세요. {name}님! 만나서 반갑습니다."

demo = gr.Interface(fn=greet, inputs="text", outputs="text")
demo.launch(share=True)

2-2. 그라디오 슬라이더

import gradio as gr

def greet(name, is_morning, age):
    a = "아침" if is_morning else "저녁"
    age = age-10
    b = f"안녕하세요. {name}님! 좋은 {a} 입니다. {age}처럼 보입니다"
    return b, age

demo = gr.Interface(fn=greet, inputs=["text", "checkbox", gr.Slider(0, 100, 50)],
                    outputs=["text", "number"])
demo.launch(share=True)

2-3. 그라디오 탭 생성

import gradio as gr


tab1 = gr.Interface(lambda x : x[::-1],
                    inputs="text",
                    outputs="text",
                    title = 'reverse')
tab2 = gr.Interface(lambda x : x.upper(),
                    inputs="text",
                    outputs="text",
                    title = 'Uppercase')

demo = gr.TabbedInterface([tab1, tab2], ["뒤집기", "대문자"])
demo.launch(share=True)

 

2-4. 그라디오 챗봇 화면

import time
import random

def response(msg, history):
    result = random.choice(['안녕하세요', '반갑습니다','배가 고파요','집에 가고 싶어요'])
   
    # 초기 응답은 빈 문자열로 시작
    result_stream = ""
   
    for char in result:
        result_stream += char
        time.sleep(0.1)
        # 히스토리 마지막 요소를 업데이트하여 yield
        yield  history + [(msg, result_stream)], ""

with gr.Blocks() as demo:
    chatbot = gr.Chatbot()
    msg = gr.Textbox(placeholder="메시지를 입력하세요", label="메시지")
    btn2 = gr.Button("초기화")

    msg.submit(fn = response,
               inputs=[msg, chatbot],
               outputs=[chatbot, msg],
               )

demo.launch(share=True)

 

2-5. 챗봇 1차 version

from dotenv import load_dotenv
from datetime import datetime
import os
import gradio as gr
from openai import OpenAI

# 환경 변수 로딩
load_dotenv(override=True)

apikey = os.getenv("OPENAI_API_KEY")
default_model = os.getenv("OPENAI_DEFAULT_MODEL")

client3 = OpenAI(api_key=apikey)

SAVE_PATH = "chat_history.json"

# 대화 불러오기 함수
def load_history():
    if os.path.exists(SAVE_PATH):
        with open(SAVE_PATH, "r", encoding="utf-8") as f:
            return json.load(f)
    return []

# 대화 저장 함수
def save_history(history):
    with open(SAVE_PATH, "w", encoding="utf-8") as f:
        json.dump(history, f, ensure_ascii=False, indent=2)
    return "✅ 대화가 저장되었습니다!"

# 응답 함수
def response(msg, history):
    if history is None:
        history = load_history()

    messages = [{"role": "system", "content": "너는 지금 금융 전문가 AI야. 보고서 형식으로 깔끔하게 대답해줘."}]
   
    # Gradio가 전달한 history를 직접 사용
    messages += history.copy()
    messages.append({"role": "user", "content": msg})

    result = client3.chat.completions.create(
        model=default_model,
        messages=messages,
        stream=True,
        max_tokens=500,
    )

    reply = ""
    for chunk in result:
        delta = chunk.choices[0].delta.content
        if delta:
            reply += delta
            time.sleep(0.1)
            # 실시간으로 답변 생성하면서 반환
            yield history + [{"role": "user", "content": msg},
                             {"role": "assistant", "content": reply}
                             ], ""

    # 마지막에 저장
    history.append({"role": "user", "content": msg})
    history.append({"role": "assistant", "content": reply})
    save_history(history)

with gr.Blocks() as demo:
    chatbot = gr.Chatbot(label="AI 챗봇", type="messages")  # 반드시 type='messages'
    msg = gr.Textbox(placeholder="메시지를 입력하세요.", label="메시지")
    btn2 = gr.Button("초기화")

    msg.submit(response, inputs=[msg, chatbot], outputs=[chatbot, msg])

    save_btn = gr.Button("💾 저장")
    load_btn = gr.Button("📂 불러오기")
    clear_btn = gr.Button("🧹 초기화")
    status = gr.Markdown("")  # ⬅️ 알림 메시지 출력용 컴포넌트

    save_btn.click(fn=save_history, inputs=[chatbot], outputs=[status])
    load_btn.click(fn=load_history, inputs=[], outputs=[chatbot])
    clear_btn.click(lambda:[], inputs=None, outputs=chatbot)

demo.launch(share=True)

 

3-1. Lang chain : 기본 셋팅

from dotenv import load_dotenv
from datetime import datetime
import os
 
import gradio as gr
from openai import OpenAI
 
from langchain_openai import ChatOpenAI
from langchain_core.messages import AIMessage, SystemMessage, HumanMessage

# 환경 변수 로딩
load_dotenv(override=True)

apikey = os.getenv("OPENAI_API_KEY")
default_model = os.getenv("OPENAI_DEFAULT_MODEL")
default_model2 = os.getenv("OPENAI_DEFAULT_MODEL_4")
 
llm = ChatOpenAI(api_key=apikey, model=default_model)
llm
 
messages1 = [("system", "당신은 서울의 음식과 문화 전문가입니다."),
            ("human", "서울을 대표하는 음식을 맛볼 수 있는 레스토랑 5개를 추천해주세요")]
 
messages2 = [[("system", "당신은 서울의 음식 전문가입니다."),
            ("human", "서울 신도림역쪽 주변의 블루리본 맛집을 5군데 추천해주세요")],
            [("system", "당신은 서울의 문화 전문가입니다."),
                        ("human", "서울의 문화 데이트 코스 5군데를 짜주세요.")]]
 
response = llm.stream(messages1)
# response = llm.batch(messages)

for chunk in response:
    print(chunk.content, end='')
chat = ChatOpenAI(api_key=apikey, model=default_model, temperature=0.9)
sys = SystemMessage(content="당신은 음악을 추천해주는 전문 AI입니다.")
user = HumanMessage(content="2000년대 팝송 5곡을 추천해줘.")

msg = chat([sys, user])
print(msg.content)

 

3-2. lang-chain 병렬처리

import asyncio
import time

async def invoke_async(llm, messages):
    response = await llm.ainvoke(messages)
    print(response.content)

async def invoke_parallel(llm, messages):
    tasks = [invoke_async(llm, messages) for _ in range(10)]
    await asyncio.gather(*tasks)
 
print("Async")
start = time.perf_counter()
await invoke_parallel(llm, messages)
end = time.perf_counter()
print(f"Elapsed time: {end - start:.2f} seconds")

 

3-3. lang-chain for문으로 여러 메시지 보내기(대답은 이전 질문을 기억해서 답변하도록)

from langchain.schema import AIMessage, SystemMessage, HumanMessage
from langchain_openai import ChatOpenAI

chat = ChatOpenAI(api_key=apikey, model=default_model, temperature=0.9)

messages = [('system', '당신은 여행 전문가로 고객의 여행 일정에 도움을 줍니다.')]

msg = ["부산 여행에서 딱 한 곳만 가봐야 한다면 어떤 곳인지 추천해주세요.",
            '부산역에서 그 곳에 가는 교통편을 알려주세요.',
            '그 근처에서 먹을만한 음식점을 추천해주세요.']

for i in msg:
    messages.append(HumanMessage(content=f"'user', {i}"))
    response = llm.invoke(messages)
    messages.append(response)
    print(response.content)

 

3-4. lang-chain 에서 history를 기억함. 어떻게 사용할까?

from langchain.memory import chat_message_histories
from langchain.memory.chat_message_histories import ChatMessageHistory

history = ChatMessageHistory()

history.add_message(SystemMessage(content='당신은 여행 전문가로 고객이ㅡ 여행 일정에 도움을 줍니다.'))


msg = ["부산 여행에서 딱 한 곳만 가봐야 한다면 어떤 곳인지 추천해주세요.",
            '부산역에서 그 곳에 가는 교통편을 알려주세요.',
            '그 근처에서 먹을만한 음식점을 추천해주세요.']

for i in msg:
    history.add_user_message(i)
    response = llm.invoke(history.messages)
    history.add_ai_message(response.content)

 

3-5. 최근 대화 n개만 저장하도록!

from langchain.memory import ConversationBufferWindowMemory

#같은 메모리인데 최근 대화 k개를 가지고 있는 메모리
memory = ConversationBufferWindowMemory(memory_key="chat_history",
                                        return_messages=True,
                                        k=3) #최근 k개의 대화만 저장
memory.clear()
memory.save_context({'human':'안녕하세요 챗봇님'},
                    {'bot':'안녕하세요! 반가워요, 호칭을 어떻게 하는게 좋을까요?'}) #context의 시작은 항상 사용자
memory.save_context({'human':'나는 홍길동입니다'},
                    {'bot':'네, 홍길동님 만나서 반갑습니다'})
memory.save_context({'human':'경복궁을 가고 싶은데 어떻게 가면 되는지 알려주세요'},
                    {'bot':'물론이죠. 경복궁은 지하철을 타고 가면 편리합니다'})
memory.save_context({'human':'몇 호선을 타고 가야하는지 아니?'},
                    {'bot':'3호선을 타고 가세요'})  

result = memory.load_memory_variables({})
for msg in result['chat_history']:
    print(type(msg), msg.content)

 

3-6. 대화에서 요약된 내용만 출력하세요.

from langchain.memory import ConversationSummaryBufferMemory    

memory = ConversationSummaryBufferMemory(llm=llm,
                                        return_messages=True,
                                        max_token_limit=50)
memory.clear()
memory.save_context({'human':'안녕하세요 챗봇님'},
                    {'bot':'안녕하세요! 반가워요, 호칭을 어떻게 하는게 좋을까요?'}) #context의 시작은 항상 사용자
memory.save_context({'human':'나는 홍길동입니다'},
                    {'bot':'네, 홍길동님 만나서 반갑습니다'})
memory.save_context({'human':'경복궁을 가고 싶은데 어떻게 가면 되는지 알려주세요'},
                    {'bot':'물론이죠. 경복궁은 지하철을 타고 가면 편리합니다'})
memory.save_context({'human':'몇 호선을 타고 가야하는지 아니?'},
                    {'bot':'3호선을 타고 가세요'})  

result= memory.load_memory_variables({})
print(result)  # 요약된 대화 내용 출력

 

3-7. 대답을 하는데에 걸리는 시간, 비용, 토큰 수를 출력하고싶어.

from langchain.callbacks import get_openai_callback

with get_openai_callback() as callback:
    message = [HumanMessage(content="서울 광장시장에서 가장 맛있는 길거리 음식은 무엇인가요?")]
    response = llm.invoke(message)
    print(response.content)
    print(callback)
    print(callback.total_tokens)