Table of contents

Abstract
Project
ChatGPT Talks
My Festivus gizmo connects to ChatGPT to ask it for "artificial intelligence generated" festivus quotes. It will then (try to ) turn the received reply into voice, and say the message.
Consistent with this "artificial content generation" theme: the logo is generated by Nightcafe. I asked it to create "chatgpt logo in christmas style".
Example quote:
Look and Feel
It's a plain looking device (yeah - I know - not very Holiday compliant). A box with a button, a speaker and a wall plug. When the bored partygoers want some distraction, they can push the button. They will get energised by a new intelligent festive thought.
Technology and Flow
Simplicity and off-the-shelf are the key words. I want to use existing assets.
- OpenAI's Chat API
- Python and shell scripts
- OpenAI's Text To Speech API
- Raspberry Pi
- Little amplifier and speaker
- Button
When the button is pushed, my scripts will run to call the API. The API returns a quote that's handed over to the speech module.
Artificial Intelligence content:
- the gizmo quotes are generated by OpenAI
- all speech is generated by OpenAI
- all art in this article is generated by Nightcafe
Button Listener
todo
OpenAI API
This section describes how to get access to the API and use it as a query / response unit.
Key provisioning
Get yourself a ChaTGPT / OpenAI account. The standard free one will do. You can then request a secret API key.
Copy the key to a safe store. Don't share it. Note to self: also don't put it in source code that is uploaded to the forum.
Install OpenAI library
execute this command:
pip3 install -q openai
Code
I based the initial version on OpenAI's Assistant example.
Set the environment variable OPENAI_API_KEY
$Env:OPENAI_API_KEY = "<api key>"
Test with minimal changes to example:
# --- assistant = client.beta.assistants.create( name="Festivus", instructions="You are a festivus narrator. Generate a random festivus quote when asked.", tools=[{"type": "code_interpreter"}], model="gpt-3.5-turbo", ) # --- message = client.beta.threads.messages.create( thread_id=thread.id, role="user", content="Please generate a new random festive quote", ) run = client.beta.threads.runs.create( thread_id=thread.id, assistant_id=assistant.id, instructions="Be merry. Always generate a fresh quote.", ) # ---
Result
PS > & python3.9.exe openai_festivus.py
checking assistant status.
in progress...
done!
messages:
{'role': 'assistant', 'message': 'Of course! Here\'s a merry quote just for you:\n\n"May your days be merry and bright, and may all your troubles be out of sight."'}
{'role': 'user', 'message': 'Please generate a new random quote'}
PS > & python3.9.exe openai_festivus.py
checking assistant status.
in progress...
in progress...
done!
messages:
{'role': 'assistant', 'message': 'Of course! Here\'s a new random quote just for you:\n\n"Believe you can and you\'re halfway there." - Theodore Roosevelt'}
{'role': 'user', 'message': 'Please generate a new random quote'}
Early success!
Train OpenAI to give only the quote. No confirmation or comments.
run = client.beta.threads.runs.create( thread_id=thread.id, assistant_id=assistant.id, instructions="Be merry. Always generate a fresh quote. Do not include any explanation.", )
Result:
messages:
{'role': 'assistant', 'message': '"May your days be merry and bright."'}
{'role': 'user', 'message': 'Please generate a new random festive quote'}
Better!
Get the actual quote:
if message.role == "assistant" : print(message.content[0].text.value)
'Tis the season to be jolly!
Best!
Speech
OpenAI has a speech module. You send it a text, and it can generate an mp3 file. I pass the part of the payload that represents the quote:
from pathlib import Path # --- speech_file_path = Path(__file__).parent / "speech.mp3" # --- if message.role == "assistant" : response = openai.audio.speech.create(model="tts-1", voice="alloy", input=message.content[0].text.value) response.stream_to_file(speech_file_path) # ---
Example result:
'Tis the season to be jolly!
Success!
Hardware Hookup
todo
Software Hookup
Almost everything is contained into a single python script. OpenAI does the majority of the work in the cloud: "get quote, turn to speech, say it".
#!/usr/bin/env python from pathlib import Path import time import openai from playsound import playsound # gets API Key from environment variable OPENAI_API_KEY client = openai.OpenAI() speech_file_path = Path(__file__).parent assistant = client.beta.assistants.create( name="Festivus", instructions="You are a festivus narrator. Generate a random festivus quote when asked.", tools=[{"type": "code_interpreter"}], model="gpt-3.5-turbo", ) thread = client.beta.threads.create() message = client.beta.threads.messages.create( thread_id=thread.id, role="user", content="Please generate a new random festive quote", ) run = client.beta.threads.runs.create( thread_id=thread.id, assistant_id=assistant.id, instructions="Be merry. Always generate a fresh quote. Do not include any explanation.", ) #print("checking assistant status. ") while True: run = client.beta.threads.runs.retrieve(thread_id=thread.id, run_id=run.id) if run.status == "completed": #print("done!") messages = client.beta.threads.messages.list(thread_id=thread.id) #print("messages: ") for message in messages: assert message.content[0].type == "text" if message.role == "assistant" : print(message.content[0].text.value) response = openai.audio.speech.create(model="tts-1", voice="alloy", input="Ho! Ho! Ho!" + message.content[0].text.value) response.stream_to_file(speech_file_path / "speech.mp3") playsound('./speech.mp3') client.beta.assistants.delete(assistant.id) break else: #print("in progress...") time.sleep(5)
I need to create a button listener that executes the python script, when activity is detected.
todo
References
logo AI-generated: https://creator.nightcafe.studio/creation/ADSMAN2hDBg8iRYl1CWj
bored partygoer AI generated: https://creator.nightcafe.studio/creation/fHWqZDYB1ZRNunRenpTo
API I use to talk to OpenAI / ChatGPT: https://www.makeuseof.com/chatgpt-api-complete-guide/
examples I used as a starting point: https://github.com/openai/openai-python/tree/v1.3.4/examples
how to make result only return the quote: https://community.openai.com/t/how-to-let-gpt-do-not-return-any-accompanying-text/324513/8
text to speach: https://github.com/openai/openai-python/blob/v1.3.4/examples/audio.py
audio output for headless raspberry os: https://elinux.org/R-Pi_Troubleshooting#Sound