본문 바로가기
Programming 개발은 구글로/기타 정보

[WEB+AI] 13일차 Chatbot + Python

by 40대직장인 2024. 10. 30.

Chatbot

 

강사: 이숙번님

 

🟦 Chatbot을 활용하여 주식 종목 정보 확인

  - FinanceDataReader 라이브러리를 사용하여 '삼성전자(005930)' 종목 주식 조회

import FinanceDataReader as fdr

# 005930 종목 2023년 주식 조회
df = fdr.DataReader('005930', '2023')
df.head()

 

  - 함수 설명 기입

tools = [
    {
        "type": "function",
        "function": {
            "name": "DataReader",
            "description": "주식 코드와 기간으로 해당 기간 동안의 시작가, 종가, 최저가, 거래량 등의 일별 주식 변동 데이터를 반환하는 함수",
            "parameters": {
                "type": "object",
                "properties": {
                    "symbol": {
                        "type": "string",
                        "description": "주식의 코드"
                    },
                    "start": {
                        "type": "string",
                        "description": "조회할 주식 기간의 시작 날짜. 포맷은 YYYY, YYYY-MM, YYYY-MM-DD"
                    },
                    "end": {
                        "type": "string",
                        "description": "조회할 주식 기간의 종료 날짜. 포맷은 YYYY, YYYY-MM, YYYY-MM-DD"
                    },
                        "end": {
                        "type": "string",
                        "description": "The second number to add"
                    }
                },
                "required": ["symbol"],
                "additionalProperties": False,
            }
        }
    }
]

 

 

  - openai 설치

!pip install openai

 

  - open AI import 및 key 설정

from openai import OpenAI

client = OpenAI(api_key = key) # openai 키 입력

 

 

  - GPT 모델을 통해 데이터를 불러옴

result = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "주식 전문가. 주식 데이터를 보고 상황을 분석하는 챗봇"},
        {"role": "user", "content": "고려 아연 2024년 10월 주가를 확인해서 주식 상황을 요약하고 흐름을 분석해줘"}
    ],
    tools=tools,
)

 

 

  - GPT가 뽑아낸 입력 Parameter를 가지고 함수 호출 -> 함수 결과 생성

import json

tool_call = result.choices[0].message.tool_calls[0]

name = tool_call.function.name
argumnets = json.loads(tool_call.function.arguments)

print(name)
print(argumnets)

df = fdr.DataReader(argumnets['symbol'], argumnets['start'], argumnets['end'])

# to_csv() 함수는 콤마를 기준으로 csv파일로 변환
df.to_csv('output.csv') # 파일 저장
df.to_csv() # 문자열로 출력하는 방법

 

 

  - function_call_result 라는 JSON 메시지를 생성하여 주식 데이터를 분석하는 챗봇에게 전달

function_call_result_message = {
    "role": "tool",
    "content": json.dumps({
        "symbol": argumnets['symbol'],
        "start": argumnets['start'],
        "end": argumnets['end'],
        "result": df.to_csv() # 주식 데이터 DataFrame(df)를 CSV 형식으로 변환한 문자열                          
    }),
    "tool_call_id": result.choices[0].message.tool_calls[0].id
}

response = client.chat.completions.create(
    model="gpt-4o",
    messages=[
        {"role": "system", "content": "주식 전문가. 주식 데이터를 보고 상황을 분석하는 챗봇"},
        {"role": "user", "content": "고려 아연 2024년 10월 주가를 확인해서 주식 상황을 요약하고 흐름을 분석해줘."},
        result.choices[0].message,
        function_call_result_message # tool 호출 결과 메시지를 포함하여 주가데이터를 csv로 챗봇에게 전달
    ]
)

print(response.choices[0].message.content)

 

 

  - gradio  ChatInterface 사용

import random
import gradio as gr

def random_chat(meassage, histroy):
    return random.choice(["Yes", "No"])

# gr.ChatInterface는 Gradio 라이브러리 인터페이스로 random_chat 함수를 통해 
# 사용자와 챗봇 간의 대화기능을 제공함
app = gr.ChatInterface(random_chat)

app.launch(share=True, debug=True)

 

 

import random
import gradio as gr

def random_chat(message, history):
    response = client.chat.completions.create(
    	model="gpt-4o",
        messages=[
            {"role": "system", "content": "여동생같은 챗봇. 반말을 한다."},
            {"role": "user", "content": message},
        ]
	)
    return response.choices[0].message.content
    
app = gr.ChatInterface(random_chat)

app.launch(share=True, debug=True)

 

 

history = [ 
    ['안녕', '안녕'],
    ['행복했어?', '좋았어']
]
    
# messages를 리스트로 정의
messages = [{"role": "system", "content": "여동생같은 챗봇. 반말을 한다."}]

# for 루프는 history 리스트를 순회하면서 각 대화 쌍을 messages에 추가함.
for user, assistant in history:
    messages.append({"role": "user", "content": user}) 
    messages.append({"role": "assistant", "content": assistant})

 

  - history에 기록된 대화를 messages 리스트에 추가하여 system, user, assistant 간의 대화 히스토리를 저장함.

 

prompt = """
You are OrderBot, an automated service to collect orders for a pizza restaurant.
You first greet the customer, then collects the order, and then asks if it's a pickup or delivery.
You wait to collect the entire order, then summarize it and check for a final time if the customer wants to add anything else.
If it's a delivery, you ask for an address. Finally you collect the payment.
Make sure to clarify all options, extras and sizes to uniquely identify the item from the menu.
You respond in a short, very conversational friendly style.

The menu includes
    pepperoni pizza  12.95, 10.00, 7.00
    cheese pizza   10.95, 9.25, 6.50
    eggplant pizza   11.95, 9.75, 6.75
    fries 4.50, 3.50
    greek salad 7.25
Toppings:
    extra cheese 2.00,
    mushrooms 1.50
    sausage 3.00
    canadian bacon 3.50
    AI sauce 1.50
    peppers 1.00
Drinks:
    coke 3.00, 2.00, 1.00
    sprite 3.00, 2.00, 1.00
    bottled water 5.00
"""

# prompt에는 아래의 설명이 포함되어 있음
# 고객에게 인사하기, 주문 항목과 수령 방법(픽업 또는 배달) 확인, 주문 요약 및 확인
# 배달인 경우 주소 요청하기, 최종 결재 정보를 수집하기

def random_chat(message, history):
    system_prompt = "여동생같은 챗봇. 반말을 한다." 
    messages = [{"role": "system", "content": system_prompt}] 
    for user, assistant in history:
        messages.append({"role": "user", "content": user}) 
        messages.append({"role": "assistant", "content": assistant})  
    messages.append({"role": "user", "content": message})

    response = client.chat.completions.create(
    	model="gpt-4o",
        messages=messages
	)
    return response.choices[0].message.content

app = gr.ChatInterface(random_chat)

app.launch(share=True, debug=True)

 


참고 자료:

chatbot 공식문서: https://www.gradio.app/docs/chatbot

chatInterface 공식 문서: https://www.gradio.app/docs/chatinterface


 


Python

 

1. Python 강의

 

  - 리스트(List)

nums = [1, 2, 3, 4, 5, 6, 7, 8, 9]

 

  - slice 사용

print(nums[:3])
print(nums[3:6])
print(nums[6:])
print(nums[-3:])

 

  - for loop(list(nums)에 있는 값을 가져와서 출력)

for n in nums:
    print(n)

 

for i in range(5):
    print("a")
    
# range는 객체 자체로는 리스트가 아니지만, list()로 감싸면 리스트로 변환할 수 있습니다.

 

 

※ range는 Python에서 일정한 간격의 정수 시퀀스를 생성하는 함수

range([start], stop, [step])

# start: 시퀀스의 시작 값 (생략 시 기본값은 0)
# stop: 시퀀스의 끝 값 (이 값은 포함되지 않음)
# step: 증가 또는 감소 간격 (생략 시 기본값은 1)

 

 

- 멀티 Assign

이름, 지역, 이메일 = "이숙번", "통영", "abc@gmail.com",
print(f"to:{이메일}\n: {이름}님 안녕하세요. {지역}에는 요즘 날씨가 어떠신가요?")

 

users = [
    ["이숙번", "통영", "abc@gmail.com",],
    ["이고잉", "서울", "abc@gmail.com",],
]

for user in users:
    print(f"to:{user[2]}\n: {user[0]}님 안녕하세요. {user[1]}에는 요즘 날씨가 어떠신가요?")

for 이름, 지역, 이메일 in users:
    print(f"to:{이메일}\n,{이름}님 안녕하세요. {지역}에는 요즘 날씨가 어떠신가요?")

 

  - 로또 번호 생성기

import random

# 1. for문
lotto = []
for i in range(6):
    n = random.randint(1, 46)
    if n not in lotto:
        lotto.append(n) 

# 2. while문
while len(lotto) < 6:

# 3. list 활용
numbers = list(range(1, 47))
random.shuffle(numbers)
lotto = numbers[:6]

# 4. random sample 사용
numbers = list(range(1, 47))
lotto = random.sample(numbers, k=6)
print(lotto)

# 중복 허용 
random.choices(numbers, k=6)    
# 중복 없이 
random.sample(numbers, k=6)

 

users = ['이고잉', '이숙번']

name = user[0]

for name in users:
    numbers = list(range(1, 47))
    lotto = random.sample(numbers, k=6)

    message = f"""
        {name}님의 로또 번호는 {lotto}입니다.
        """
    with open(f"{name}.txt", "w", encoding="utf-8") as f:
        f.write(message)

# 파일 오픈해서 내용 저장 및 종료
f = open(f"(name).txt", "w")
f.write(message)        
f.close()

 


with 문은 Python에서 **컨텍스트 매니저(Context Manager)**를 사용하기 위해 제공되는 구문입니다.

with <context_manager> as <variable>:

 * 주요 용도

  • 파일 작업: 파일을 열고 작업한 후 자동으로 파일을 닫아줍니다.
  • 데이터베이스 연결: 데이터베이스에 연결하고, 작업이 끝나면 자동으로 연결을 닫습니다.
  • 락(lock) 관리: 여러 스레드가 하나의 자원에 접근할 때 락을 걸고 자동으로 해제합니다.

 

with 문을 사용하면 파일이나 데이터베이스 연결처럼 자원 관리가 필요한 작업을 더 안전하고 간결하게 수행할 수 있습니다.

 

with 문을 벗어나면 자동으로 자원이 해제되므로 파일을 닫거나 예외 처리를 직접 할 필요가 줄어듭니다.


 

  - 리스트 컴프리헨션(Comprehension)

  : 컴프리헨션은 Python에서 리스트, 딕셔너리, 집합 등을 간단하고 직관적으로 생성할 수 있도록 해주는 표현식입니다.

 

리스트 컴프리헨션
[expression for item in iterable if condition]

# 예제
even_numbers = [x for x in range(1, 11) if x % 2 == 0]
-----------------------------------------------------------

# 딕셔너리 컴픠리헨션
{key_expression: value_expression for item in iterable if condition}

# 예제
squares = {x: x**2 for x in range(1, 6)}
-----------------------------------------------------------

# 집합 컴프리헨션
{expression for item in iterable if condition}

# 예제
unique_chars = {char.lower() for char in "Hello World"}
-----------------------------------------------------------

# 제너레이터 컴프리헨션
(expression for item in iterable if condition)

# 예제
squares_gen = (x**2 for x in range(1, 11))
# 필요할 때 next()로 값을 하나씩 꺼냄
print(next(squares_gen))  # 1
print(next(squares_gen))  # 4

 

numbers = list(range(10))

numbers2 =[]
for n in numbers:
    if n % 2 == 1:
        numbers2.append(n ** 2)

# 변환
numbers = [n ** 2 for n in numbers if n % 2 == 1]

 

 

※ 사용하는 Tool: Colab, OpenAI


출처: AI Hub 교육과정 - WEB+AI (위 내용이 문제가 된다면 댓글에 남겨주세요. 바로 삭제조치하도록 하겠습니다.)

 

 

댓글