You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

317 lines
10 KiB

# imports
import os
import json
from dotenv import load_dotenv
from openai import OpenAI
import gradio as gr
import base64
from io import BytesIO
from PIL import Image
from IPython.display import Audio, display
import pygame
import time
from tools import price_function, get_ticket_price, make_a_booking, booking_function
import ollama
import anthropic
from anthropic import Anthropic
import whisper
import sounddevice as sd
import soundfile as sf
import numpy as np
# And this is included in a list of tools:
tools = [{"type": "function", "function": price_function}, {"type": "function", "function": booking_function}]
# tools = [price_function, booking_function]
# System messages
system_message = "You are a helpful assistant for an Airline called FlightAI. "
system_message += "Give short, courteous answers, no more than 1 sentence. "
system_message += "Always be accurate. If you don't know the answer, say so."
# Initialization
load_dotenv(override=True)
openai_api_key = os.getenv('OPENAI_API_KEY')
if openai_api_key:
print(f"OpenAI API Key exists and begins {openai_api_key[:8]}")
else:
print("OpenAI API Key not set")
MODEL = "gpt-4o-mini"
openai = OpenAI()
def chat(history):
messages = [{"role": "system", "content": system_message}] + history
response = openai.chat.completions.create(model=MODEL, messages=messages, tools=tools)
image = None
if response.choices[0].finish_reason == "tool_calls":
message = response.choices[0].message
response, city = handle_tool_call(message)
messages.append(message)
messages.append(response)
if message.tool_calls[0].function.name == "get_ticket_price":
# image = artist(city)
pass
response = openai.chat.completions.create(model=MODEL, messages=messages)
reply = response.choices[0].message.content
# ✅ SAFETY CHECK: Never add empty or None replies
if reply:
history.append({"role": "assistant", "content": str(reply)})
talker(reply)
else:
history.append({"role": "assistant", "content": "Sorry, no response available."})
return history, image
# We have to write that function handle_tool_call:
def handle_tool_call(message):
print(f"Handling tool call: {message}")
tool_call = message.tool_calls[0]
function_name = tool_call.function.name
arguments = json.loads(tool_call.function.arguments)
if function_name == "get_ticket_price":
city = arguments.get('destination_city')
price = get_ticket_price(city)
response = {
"role": "tool",
"content": json.dumps({"destination_city": city, "price": price}),
"tool_call_id": tool_call.id
}
return response, city
elif function_name == "make_a_booking":
city = arguments.get('destination_city')
customer_name = arguments.get('customer_name')
customer_id = arguments.get('customer_id')
booking_result = make_a_booking(city, customer_name, customer_id)
response = {
"role": "tool",
"content": json.dumps({
"destination_city": city,
"customer_name": customer_name,
"customer_id": customer_id,
"booking_result": booking_result
}),
"tool_call_id": tool_call.id
}
return response, city
else:
raise ValueError(f"Unknown function: {function_name}")
def artist(city):
image_response = openai.images.generate(
model="dall-e-3",
prompt=f"An image representing a vacation in {city}, showing tourist spots and everything unique about {city}, in a vibrant pop-art style",
size="1024x1024",
n=1,
response_format="b64_json",
)
image_base64 = image_response.data[0].b64_json
image_data = base64.b64decode(image_base64)
return Image.open(BytesIO(image_data))
def talker(message):
response = openai.audio.speech.create(
model="tts-1",
voice="onyx",
input=message)
audio_stream = BytesIO(response.content)
output_filename = f"output_audio_{time.time()}.mp3"
with open(output_filename, "wb") as f:
f.write(audio_stream.read())
# Play the generated audio
# display(Audio(output_filename, autoplay=True)) # This code is suitable for Juopyter
print(f"Created audio file at {output_filename}")
# Using pygame
pygame.init()
pygame.mixer.init()
pygame.mixer.music.load(output_filename)
pygame.mixer.music.play()
while pygame.mixer.music.get_busy():
continue
def ollama_translator(text, target_language="German"):
"""
Translates text to the specified language using Ollama.
Args:
text (str): The text to translate
target_language (str): The language to translate to (default: Arabic)
Returns:
str: The translated text
"""
try:
# Create a prompt that instructs the model to translate
prompt = f"Translate the following text to {target_language}. Only output the translation, nothing else:\n\n{text}"
response = ollama.chat(
model='llama3.2:latest', # or any other model you have installed
messages=[
{"role": "system", "content": "You are a professional translator. Translate the given text accurately."},
{"role": "user", "content": prompt}
]
)
translated_text = response['message']['content'].strip()
return translated_text
except Exception as e:
print(f"Translation error: {str(e)}")
return f"Translation failed: {str(e)}"
def translate_message(history):
"""
Translates the last message in the chat history.
Args:
history (list): List of chat messages
Returns:
str: Translated text of the last message
"""
if not history:
return ""
# Get the last message from history
last_message = history[-1]
# Extract the content from the last message
message_content = last_message.get('content', '')
if message_content:
return ollama_translator(message_content)
return ""
def clear_chat():
return [], ""
def convert_audio_to_text(audio_file_path):
"""
Converts audio to text using OpenAI's Whisper model.
Supports MP3, WAV, and other common audio formats.
Args:
audio_file_path (str): Path to the audio file
Returns:
str: Transcribed text
"""
try:
# Load the Whisper model
model = whisper.load_model("base")
# Transcribe the audio file
result = model.transcribe(audio_file_path)
# Return the transcribed text
return result["text"]
except Exception as e:
print(f"Audio transcription error: {str(e)}")
return f"Transcription failed: {str(e)}"
def handle_audio(audio_file, history):
history = history or []
if audio_file:
try:
if not os.path.exists(audio_file):
raise Exception("Audio file not found")
try:
transcribed_text = convert_audio_to_text(audio_file)
except Exception as e:
print(f"Transcription error: {str(e)}")
return history, None # 🛠 match expected outputs
if transcribed_text:
history.append({"role": "user", "content": str(transcribed_text)})
try:
if os.path.exists(audio_file):
os.remove(audio_file)
except Exception as e:
print(f"Warning: Could not delete audio file: {str(e)}")
return history, None # ✅ return both expected outputs
except Exception as e:
print(f"Error processing audio: {str(e)}")
return history, None
return history, None
if __name__ == "__main__":
# gr.ChatInterface(fn=chat, type="messages").launch()
# talker("Hello, how are you?")
# Passing in inbrowser=True in the last line will cause a Gradio window to pop up immediately.
# print(ollama_translator("Hello, how are you?"))
# print(convert_audio_to_text("output_audio_1744898241.4550629.mp3"))
with gr.Blocks() as ui:
with gr.Row():
with gr.Column():
chatbot = gr.Chatbot(height=500, type="messages")
with gr.Row():
entry = gr.Textbox(label="Chat with our AI Assistant:")
audio_input = gr.Audio(
type="filepath",
label="Or speak your message:",
interactive=True,
format="wav",
# source="microphone"
)
clear = gr.Button("Clear")
with gr.Column():
translation_output = gr.Textbox(label="Translation (Arabic):", lines=5)
image_output = gr.Image(height=500)
def do_entry(message, history):
history = history or []
if message:
history.append({"role": "user", "content": str(message)})
return "", history
def translate_message(history):
if not history:
return ""
last_message = history[-1]
message_content = last_message.get('content', '')
if message_content:
return ollama_translator(message_content)
return ""
def clear_chat():
return [], ""
# Handle text input
entry.submit(do_entry, inputs=[entry, chatbot], outputs=[entry, chatbot]).then(
chat, inputs=chatbot, outputs=[chatbot, image_output]
).then(
translate_message, inputs=chatbot, outputs=translation_output
)
# Handle audio input
audio_input.stop_recording(
handle_audio, inputs=[audio_input, chatbot], outputs=[chatbot, image_output]
).then(
chat, inputs=chatbot, outputs=[chatbot, image_output]
).then(
translate_message, inputs=chatbot, outputs=translation_output
)
clear.click(clear_chat, inputs=None, outputs=[chatbot, translation_output])
ui.launch(inbrowser=False)