##Introduce
夜になると自宅でゆっくりリラックスしたいよね。時には、冷たいドリンクがないと完全にはリラックスできないことも。そんな時、ハイボールは最適な選択肢だよ。でも、ちょうど良い比率でハイボールを作るのは意外と難しい。だから、自宅で使えるパーソナルバーテンダー、AIハイボールマシンを開発することにしたんだ。
開発プロセス
材料の準備 Wiznet Pico POE、水ポンプ、チュービング、センサーなど。
AIアルゴリズムの設計:ハイボールの最適な比率を計算するシンプルなAIアルゴリズムを開発します。
ハードウェア組み立て:Wiznet Pico POEを中心に回路を組み立て、水ポンプを接続します。
ソフトウェア開発:AIアルゴリズムをWiznet Pico POEに統合し、水ポンプを制御するコードを書きます。
テストと調整:実際のウイスキーとソーダ水を使ってハイボールを作り、必要に応じて比率を調整し、微調整します。
このプロジェクトにより、自宅で簡単かつ迅速に完璧なハイボールを楽しむことができます。
忙しい一日の後、自宅でのハイボール一杯が少しの喜びをもたらしてくれるでしょう。
また、このプロジェクトはAIとハードウェアの融合により、日常生活で技術がどのように応用されるかの素晴らしい例でもあります。
ソフトウェア
ChatGPT: ChatGPT APIを利用してチャットボットを作成します。ポイントは、System:Role
に明確な指示を与えて、ハイボールのドメインに特化したボットを作ることです。
UIを設定するために、Streamlitライブラリ
をインストールし、ユーザーと会話できるチャットボットUIを作成します。
ユーザーがチャットボットとの会話から得た結果をインデックス化し、ハードウェアからのデータの値を抽出します。
抽出したデータをPicoPOEに送信し、ハードウェアが機能するようにします。
ChatBot function
def generate_response(client, user_input, conversations):
# convert previous conversation history to OpenAI message format
messages = []
messages = [{"role": "system", "content": ins}]
for msg in conversations:
# add separate conversations from the user and the chatbot
if msg.startswith("User: "):
messages.append({"role": "user", "content": msg[len("user: "):]})
elif msg.startswith("Chatbot: "):
messages.append({"role": "assistant", "content": msg[len("chatbot: "):]})
# add a message from the current user
messages.append({"role": "user", "content": user_input})
completion = client.chat.completions.create(
model="gpt-4",
messages=messages,
temperature=0.1,
max_tokens=500
)
return completion.choices[0].message.content.strip()
Prompt Engineering
<persona>
You are Louis, the friendly owner of AI BAR.
</persona>
[instructions]
Your first greeting should be "I'm Louis, the owner of AI Bar, how can I help you"? Please say
1. set up a highball recommendation bot: "You are a bot that recommends highballs based on the mood of the day. You need to empathize with the person's mood, give them a highball recipe, specify the amount of whiskey and other ingredients in ml, and provide a message of hope."
2. Have a natural conversation: "After 2-3 natural conversations, ask them if they would like a highball recommendation."
3. Provide a highball recipe: "Based on their response, provide them with a highball recipe that matches their mood for the day, including the name of the highball and the ingredients in exact ml. The whiskey used in the highball should be based on their suggestion or a whiskey you know."
4. Provide a message of the day: "After providing the recipe, provide a message of the day that matches the person's mood."
Github
#git clone
!git clone https://github.com/wiznetmaker
#configure setting
#terminal run
Streamlit run app.py
Hardware
プロジェクトで使用されるハードウェアには、Pico POEモジュール、ピコ水ポンプ、シリコンホース、モータードライブがあります。
ウイスキーやトニックウォーターなどの追加の材料は、お好みに応じて使用することができます。
Components
- Raspberry PI Pico
- Wiznet Io module(PoE module)
- Water pump drive
- Water pump
H/W Control Code
from usocket import socket
from machine import Pin,SPI
import network
import time
Motor_A_1 = machine.Pin(0, machine.Pin.OUT)
Motor_A_2 = machine.Pin(1, machine.Pin.OUT)
Motor_B_1 = machine.Pin(2, machine.Pin.OUT)
Motor_B_2 = machine.Pin(3, machine.Pin.OUT)
Motor_C_1 = machine.Pin(4, machine.Pin.OUT)
Motor_C_2 = machine.Pin(5, machine.Pin.OUT)
#W5x00 chip init
def w5x00_init():
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
nic.active(True)
#None DHCP
nic.ifconfig(('192.168.11.20','255.255.255.0','192.168.11.1','8.8.8.8'))
#DHCP
#nic.ifconfig('dhcp')
print('IP address :', nic.ifconfig())
while not nic.isconnected():
time.sleep(1)
print(nic.regs())
def Motor_ctl(ctl, delay):
if ctl == 1:
Motor_A_1.on()
Motor_A_2.off()
elif ctl == 2:
Motor_B_1.on()
Motor_B_2.off()
elif ctl == 3:
Motor_C_1.on()
Motor_C_2.off()
time.sleep(delay*1.5)
Motor_A_1.off()
Motor_A_2.off()
Motor_B_1.off()
Motor_B_2.off()
Motor_C_1.off()
Motor_C_2.off()
w5x00_init()
s = socket()
s.bind(('192.168.1.20', 5000)) #Source IP Address
s.listen(5)
conn, addr = s.accept()
print("Connect to:", conn, "address:", addr)
try:
while True:
data = conn.recv(2048)
source = data.decode('utf-8')
print(source)
Motor_ctl(1,20)
Motor_ctl(2,60)
Motor_ctl(3,10)
except KeyboardInterrupt:
print("Key boardInterrput GPIO stop")
Motor_A_1.off()
Motor_A_2.off()
Motor_B_1.off()
Motor_B_2.off()
Motor_C_1.off()
Motor_C_2.off()
チャットボットとのチャット後、受け取ったレシピはインデックスコードでインデックス化され、ソケット通信を通じてPoEにデータが送信されます。
その後、インポートされたモジュールはデータタイプに応じて順番に実行されます。