Develop Note

W5500-EVB-Pico를 활용한 ChatGPT 기반 Slack 뉴스 봇 만들기 (Slack project V2) 본문

개발 (Ko)

W5500-EVB-Pico를 활용한 ChatGPT 기반 Slack 뉴스 봇 만들기 (Slack project V2)

Chalsu 2023. 8. 9. 10:34

Overview

이것은 이전 프로젝트의 두 번째 버전이다. 지난 프로젝트에서 W5100S-EVB-Pico, Slack, ChatGPT API를 연동해서 특정 메시지를 보내는 내용을 진행했었다.

이전 버전에서는 requests를 사용해서 요청-응답 위주로 사용했다면, 이번에는 센서 데이터와 추가 서비스 API를 사용하여 더 실용적이고 풍부한 메시지를 만들어 보려고 했다.

또한 이번에는 W5500-EVB-Pico를 사용하고, Picobricks 라는 개발 키트를 추가로 사용했다.

Component

Hardware

  • W5500-EVB-Pico
  • Picobricks

Platform

  • Slack
  • NewsAPI
  • OpenAI Chat API

개발환경

  • Thonny (Micropython)

 

슬랙과 OpenAI API를 사용하기 위해 설정하는 내용은 이전 프로젝트에서 진행했기 때문에 따로 작성하지 않는다. 픨요하다면 기존 프로젝트에서 관련 내용을 찾을 수 있다.

한글 버전은 아래 링크에서 볼 수 있다.
ChatGPT API를 사용하여 유용한 이메일 자동 전송하기 (with W5100S-EVB-Pico, Micropython)
W5100S-EVB-Pico에서 ChatGPT와 Slack API를 활용한 영어공부 Bot 만들기

Picobricks

Picobricks는 모듈화된 구성 요소를 사용하여 쉽게 프로젝트를 구축할 수 있게 돕는 오픈 소스 플랫폼이다.

브레드보드를 사용해 점퍼를 연결하는 수고 없이, 보드를 꽂기만 하면 정해진 Pin을 제어해서 쉽게 센서들을 사용할 수 있어 편리하다. Grove 케이블을 사용하여 별도 모듈을 연결할 수도 있다.

이번에는 간단하게 온습도 센서와 조도 센서만 사용했다.

자세한 내용은 링크에서 찾아볼 수 있다.

이번에는 간단하게 온습도 센서와 조도 센서만 사용했다.

Process

펌웨어

펌웨어는 Micropython에서 제공하는 W5500-EVB-Pico 공식 펌웨어를 사용했다. 사용한 버전은 아래와 같다. 현재 기준으로 최신 버전이다.

https://micropython.org/download/W5500_EVB_PICO/

 

MicroPython - Python for microcontrollers

MicroPython is a lean and efficient implementation of the Python 3 programming language that includes a small subset of the Python standard library and is optimised to run on microcontrollers and in constrained environments.

micropython.org

Sensor

DHT11 Test

picobricks에서 제공하는 라이브러리 사용 시 동작이 되다 안되다 하는데, 안될 때 아래와 같은 에러가 난다.

검색해보니 같은 문제를 겪은 사람들이 많은 듯 했다.

Picobricks와 관련된 문제가 아니라 센서 자체의 사용 문제인 듯 하다. 검색 끝에 Micropython 펌웨어의 최근 릴리즈에서 드라이버를 포함하고 있다는 것을 알았다.

다음과 같이 import 해서 간단하게 사용할 수 있다.

import dht
import machine
import utime

dht11 = dht.DHT11(machine.Pin(11))

for i in range(0, 5):
    dht11.measure()
    print(f'Temperature: {dht11.temperature()}, Humidity: {dht11.humidity()}')
    utime.sleep(1)

조도 센서의 경우 ADC를 사용하고 Pin 번호만 지정해주면 값을 간단히 얻어올 수 있다.

 

기존의  프로젝트에서 센서 측정 값만 추가해서 간단히 메시지를 보내본 결과이다.

News API

뭔가 실제 유용한 정보를 줄 수 없을까 생각하다가 뉴스를 생각했는데, 그냥 ChatGPT에게 요청하면 만들어(?) 줄 때도 있지만, 빈 응답을 주는 경우가 많아 실제 뉴스를 받아오면 좋겠다고 생각했다.

알아보니 무료로 지원되는 API가 있었다. ChatGPT 답을 참조함.

위 링크를 통해 가입할 수 있는데, 가입 과정도 사용도 아주 간단하다!

개발용, 비상업용으로 사용하면 무료로 사용할 수 있다. 대신 하루 요청은 100개로 제한되어 있다. Sendgrid와 동일하다.

무료 100개 중 얼마나 사용했는지는 newsapi의 내 계정 페이지에서 바로 확인할 수 있다.

비지니스 이상 플랜은 가격이 좀 있다.

가입하면 즉시 API Key가 발급 된다.

이 값은 친절하게 메일로도 전송해줘서, 따로 복사해두지 않아도 페이지에서 참조할 수 있다.

 

문서의 Get started를 사용해서 값을 얻어올 수 있는데, 로그인이 되어 있으면 내 계정에 대한 API key가 자동으로 들어가서 복사 - 붙여넣기만 하면 되어 아주 편리했다.

덕분에 빠르게 테스트를 하고 적용할 수 있었다.

Postman으로 테스트 해보니 잘 동작한다. 리턴 값에 다양한 정보들이 포함되어 있다.

ChatGPT가 알려준 Python 코드로도 테스트 했다.

옵션은 kr, us 언어 두 가지로 하고, page 수는 5로 지정했다. 그리고 카테고리는 관심 분야인 technology로 설정했다. 각자 원하는 취향대로 설정하면 된다.

 

아래는 각각 한국어, 영어로 요청해본 결과이다.

한국어(kr)

영어(us)

Python으로 API 동작 확인을 했으니, Micropython 코드로 수정하여 테스트를 진행했다.

이더넷 설정 코드를 추가했고, urequests에서 param 옵션을 지원하지 않아 url에 직접 포함시켰다.

다음은 News API의 Micropython 테스트 코드이다.

from machine import Pin, SPI, ADC
import network
import urequests
import json
import utime

NEWS_API_KEY = <API Key>

# W5x00 init
def init_ethernet():
    spi = SPI(0, 2_000_000, mosi=Pin(19), miso=Pin(16), sck=Pin(18))
    nic = network.WIZNET5K(spi, Pin(17), Pin(20))   # spi, cs, reset pin
    # Using DHCP
    nic.active(True)
    while not nic.isconnected():
        utime.sleep(1)
        # print(nic.regs())
        print('Connecting ethernet...')

    print(f'Ethernet connected. IP: {nic.ifconfig()}')

def get_news_list(api_key):
    url = f"https://newsapi.org/v2/top-headlines?country=us&apiKey={api_key}&category=technology&pageSize=5"
    print(f'url: {url}')
    response = urequests.get(url)
    print(f'response: {response}')

    if response.status_code == 200:
        data = json.loads(response.text)

        if data["status"] == "ok":
            news_articles = data["articles"]
            news_list = [f"News {i + 1}) [{article['title']}]({article['url']})" for i, article in enumerate(news_articles)]
            print(f'news_list: {news_list}')
            return news_list
        else:
            print("News request failed.")
            return None
    else:
        print(f'Error: {response.status_code}')
        return None

init_ethernet()
news_list = get_news_list(NEWS_API_KEY)
if news_list:
    news_str = ', '.join(news_list)
    print(f'news_str: {news_str}')
else:
    print("Failed to get news summary.")

응답에는 뉴스 기사에 대한 여러 정보가 포함되는데, 제목과 링크를 사용하고, 이를 마크다운 형태로 변환하기 위해 ChatGPT를 활용했다.

 

이제 남은 과제는 이것을 Slack block 메시지에 넣는 것이다.

user input 부분의 sensor 측정 값 뒤에 뉴스 리스트를 String 형태로 변환하여 추가했다.

 

Memo: 프롬프트를 딕셔너리 대신 문자열 형태로 사용하기

처음엔 데이터를 딕셔너리로 구성했는데, json.dumps() 를 사용해서 변환 후 넣었는데도 OpenAI API에서 값을 올바른 JSON 형태로 보지 않았다. 웹 JSON validate 사이트에서 하면 유효한 json 값이라고 나오는데, 뭔가 걸러내는 부분이 있는 듯 하다.

그래서 모두 string 형태로 변경했다.

# Get news list
news_list = get_news_list(NEWS_API_KEY)
news_str = ', '.join(news_list)

dht11.measure()
user_text = f'Temperature: {dht11.temperature()}, Humidity: {dht11.humidity()}, Light: {ldr.read_u16()}, {news_str}'

잘 출력된 결과물은 다음과 같다. 여러 번의 시도 끝에 완성된 메시지를 받을 때 기분이 좋다.😊

내가 요청한 정보들을 모두 포함한다.

  • 센서 데이터
  • 오늘의 뉴스
  • 오늘의 단어 (공부)
  • 오늘의 명언

슬랙을 위한 block 코드를 받으려고 하다 보니 응답에 대해 문자열을 가공하고 예외 처리하는 코드가 조금 길어졌는데, 이는 개선해야 할 부분이다.

결과물(ChatGPT의 답변)이 일정하지 않아서 다듬을 부분이 있다. 쉽지 않은 부분이다.

그래도 Open AI의 가이드 문서에 따라 system, user input을 조정해 보면서 이전보다는 나은 결과물을 얻을 수 있었다.

 

ChatGPT API를 사용한다면 꼭 한번 참고하길 추천한다.

https://platform.openai.com/docs/guides/gpt-best-practices)

 

OpenAI Platform

Explore developer resources, tutorials, API docs, and dynamic examples to get the most out of OpenAI's platform.

platform.openai.com

Conclusion

어떤 API 또는 서비스를 사용하느냐에 따라 결과물이 다양하게 출력될 수 있어서, 더 재밌는 것들을 할 수 있지 않을까 싶다.

제한은 있을 지라도 무료로 사용해볼 수 있는 API가 아주 다양하기 때문에, 실시간 날씨 정보를 받는다거나 금융 정보를 받는다거나 하는 기능을 구현하고, 그 데이터에 따라 뭔가 액션을 취할 수도 있다.

최근에는 AI와 관련된 API도 많이 나와있는 듯 하다.

아래는 ChatGPT가 알려준 API 목록이다. 

전부 동작하는 링크인지 확인해보진 못했는데, Cat Facts API 라는게 눈에 띄어서 들어가보니 고양이에 대한 역사, 정보 등을 알려주는 API가 있었다. 개발 쪽으로만 생각했는데 이런 API도 신선하고 재미있다.

 

다음에는 원격 제어와 같은 기능을 추가하고 새로운 API를 사용해서 실생활에 더 도움이 되고 재밌는 프로젝트를 만들어 보고 싶다.

각자 자신의 환경에 유용하게 사용될 수 있는 메시지를 구성해 보면 좋을 것 같다.

Comments