Spaces:
Sleeping
Sleeping
File size: 9,526 Bytes
5f52293 ed2f5ce 69f2e98 ed2f5ce 2a36ff2 82043d5 ed2f5ce 1197e50 72a27e8 038f995 a742a0d fee053d a742a0d ed2f5ce 2a200be ed2f5ce 2e5cfb3 ed2f5ce 1197e50 ed2f5ce b1f3cf3 1197e50 5f53de2 2e5a20c d5685b0 7f9822a ed2f5ce d5685b0 1197e50 2e5cfb3 2b4eaa1 1197e50 2e5cfb3 d5685b0 1197e50 79549f2 2a200be 1197e50 ed2f5ce d5685b0 1197e50 ed2f5ce 1197e50 c1e9d2a 1197e50 ed2f5ce 1197e50 72a27e8 1197e50 4fba4d9 72a27e8 4fba4d9 1197e50 4fba4d9 72a27e8 d5685b0 1197e50 2a36ff2 2a200be c1e9d2a 2a200be 1197e50 fee053d a742a0d fee053d 2a36ff2 fee053d 9748b93 03ff38e 2a200be 1197e50 2a200be 1197e50 c1e9d2a 2a200be c1e9d2a 2a200be 82043d5 2a200be 1197e50 2a200be 1197e50 2a200be 1197e50 2a200be d5685b0 1197e50 c1e9d2a 1197e50 a742a0d 1197e50 a742a0d 2a200be a742a0d |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 |
import gradio as gr
import torch
import os
import numpy as np
from groq import Groq
import spaces
from transformers import AutoModel, AutoTokenizer
from diffusers import StableDiffusionXLPipeline, UNet2DConditionModel, EulerDiscreteScheduler
from parler_tts import ParlerTTSForConditionalGeneration
import soundfile as sf
from langchain_community.embeddings import OpenAIEmbeddings
from langchain_community.vectorstores import Chroma
from langchain.text_splitter import RecursiveCharacterTextSplitter
from langchain.chains import RetrievalQA
from langchain import LLMChain, PromptTemplate
from langchain.agents import AgentExecutor, Tool, ZeroShotAgent
from langchain.llms import OpenAI
from PIL import Image
from decord import VideoReader, cpu
from tavily import TavilyClient
import requests
from huggingface_hub import hf_hub_download
from safetensors.torch import load_file
# Initialize models and clients
client = Groq(api_key=os.environ.get("GROQ_API_KEY"))
MODEL = 'llama3-groq-70b-8192-tool-use-preview'
vqa_model = AutoModel.from_pretrained('openbmb/MiniCPM-V-2', trust_remote_code=True,
device_map="auto", torch_dtype=torch.bfloat16)
tokenizer = AutoTokenizer.from_pretrained('openbmb/MiniCPM-V-2', trust_remote_code=True)
tts_model = ParlerTTSForConditionalGeneration.from_pretrained("parler-tts/parler-tts-large-v1")
tts_tokenizer = AutoTokenizer.from_pretrained("parler-tts/parler-tts-large-v1")
# Image generation model
base = "stabilityai/stable-diffusion-xl-base-1.0"
repo = "ByteDance/SDXL-Lightning"
ckpt = "sdxl_lightning_4step_unet.safetensors"
unet = UNet2DConditionModel.from_config(base, subfolder="unet")
unet.load_state_dict(load_file(hf_hub_download(repo, ckpt)))
image_pipe = StableDiffusionXLPipeline.from_pretrained(base, unet=unet, torch_dtype=torch.float16, variant="fp16")
image_pipe.scheduler = EulerDiscreteScheduler.from_config(image_pipe.scheduler.config, timestep_spacing="trailing")
# Tavily Client for web search
tavily_client = TavilyClient(api_key=os.environ.get("TAVILY_API"))
# Function to play voice output
def play_voice_output(response):
description = "Jon's voice is monotone yet slightly fast in delivery, with a very close recording that almost has no background noise."
input_ids = tts_tokenizer(description, return_tensors="pt").input_ids.to('cuda')
prompt_input_ids = tts_tokenizer(response, return_tensors="pt").input_ids.to('cuda')
generation = tts_model.generate(input_ids=input_ids, prompt_input_ids=prompt_input_ids)
audio_arr = generation.cpu().numpy().squeeze()
sf.write("output.wav", audio_arr, tts_model.config.sampling_rate)
return "output.wav"
# NumPy Code Calculator Tool
def numpy_code_calculator(query):
try:
llm_response = client.chat.completions.create(
model=MODEL,
messages=[
{"role": "user", "content": f"Write NumPy code to: {query}"}
]
)
code = llm_response.choices[0].message.content
print(f"Generated NumPy code:\n{code}")
# Execute the code in a safe environment
local_dict = {"np": np}
exec(code, local_dict)
result = local_dict.get("result", "No result found")
return str(result)
except Exception as e:
return f"Error: {e}"
# Web Search Tool
def web_search(query):
answer = tavily_client.qna_search(query=query)
return answer
# Image Generation Tool
def image_generation(query):
image = image_pipe(prompt=query, num_inference_steps=20, guidance_scale=7.5).images[0]
image.save("output.jpg")
return "output.jpg"
# Document Question Answering Tool
def doc_question_answering(query, file_path):
with open(file_path, 'r') as f:
file_content = f.read()
# Split the document into smaller chunks
text_splitter = RecursiveCharacterTextSplitter(chunk_size=1000, chunk_overlap=0)
docs = text_splitter.create_documents([file_content])
# Create embeddings using the groq model
embeddings = OpenAIEmbeddings() # If you're using a custom embeddings model, replace this line with the corresponding embeddings model for groq
# Set up the Chroma database for document retrieval
db = Chroma.from_documents(docs, embeddings, persist_directory=".chroma_db")
# Create a custom function to use groq for the question-answering step
def groq_llm(query):
response = client.chat.completions.create(
model=MODEL,
messages=[{"role": "user", "content": query}]
)
return response.choices[0].message.content
# Set up the RetrievalQA chain using the custom groq LLM function
qa = RetrievalQA.from_chain_type(llm=groq_llm, chain_type="stuff", retriever=db.as_retriever())
# Run the QA process with the groq model
return qa.run(query)
# Function to handle different input types and choose the right tool
def handle_input(user_prompt, image=None, video=None, audio=None, doc=None, websearch=False):
if audio:
if isinstance(audio, str):
audio = open(audio, "rb")
transcription = client.audio.transcriptions.create(
file=(audio.name, audio.read()),
model="whisper-large-v3"
)
user_prompt = transcription.text
tools = [
Tool(
name="Numpy Code Calculator",
func=numpy_code_calculator,
description="Useful for when you need to perform mathematical calculations using NumPy. Provide the calculation you want to perform.",
),
Tool(
name="Web Search",
func=web_search,
description="Useful for when you need to find information from the real world.",
),
Tool(
name="Image Generation",
func=image_generation,
description="Useful for when you need to generate an image based on a description.",
),
]
if doc:
tools.append(
Tool(
name="Document Question Answering",
func=lambda query: doc_question_answering(query, doc.name),
description="Useful for when you need to answer questions about the uploaded document.",
)
)
# Add this new code block:
prefix = """You are an AI assistant. You have access to the following tools:"""
suffix = """Begin!"
{chat_history}
Human: {input}
AI: I will do my best to assist you. Let me think about this step-by-step:"""
prompt = ZeroShotAgent.create_prompt(
tools,
prefix=prefix,
suffix=suffix,
input_variables=["input", "chat_history"]
)
llm = Groq(model=MODEL)
llm_chain = LLMChain(llm=llm, prompt=prompt)
agent = ZeroShotAgent(llm_chain=llm_chain, tools=tools, verbose=True)
agent_executor = AgentExecutor.from_agent_and_tools(agent=agent, tools=tools, verbose=True)
if image:
image = Image.open(image).convert('RGB')
messages = [{"role": "user", "content": [image, user_prompt]}]
response = vqa_model.chat(image=None, msgs=messages, tokenizer=tokenizer)
return response
if websearch:
response = agent_executor.run(f"{user_prompt} Use the Web Search tool if necessary.")
else:
response = agent_executor.run(user_prompt)
return response
# Gradio UI Setup
def create_ui():
with gr.Blocks() as demo:
gr.Markdown("# AI Assistant")
with gr.Row():
with gr.Column(scale=2):
user_prompt = gr.Textbox(placeholder="Type your message here...", lines=1)
with gr.Column(scale=1):
image_input = gr.Image(type="filepath", label="Upload an image", elem_id="image-icon")
audio_input = gr.Audio(type="filepath", label="Upload audio", elem_id="mic-icon")
doc_input = gr.File(type="filepath", label="Upload a document", elem_id="document-icon")
voice_only_mode = gr.Checkbox(label="Enable Voice Only Mode", elem_id="voice-only-mode")
websearch_mode = gr.Checkbox(label="Enable Web Search", elem_id="websearch-mode")
with gr.Column(scale=1):
submit = gr.Button("Submit")
output_label = gr.Label(label="Output")
audio_output = gr.Audio(label="Audio Output", visible=False)
submit.click(
fn=main_interface,
inputs=[user_prompt, image_input, audio_input, doc_input, voice_only_mode, websearch_mode],
outputs=[output_label, audio_output]
)
voice_only_mode.change(
lambda x: gr.update(visible=not x),
inputs=voice_only_mode,
outputs=[user_prompt, image_input, doc_input, websearch_mode, submit]
)
voice_only_mode.change(
lambda x: gr.update(visible=x),
inputs=voice_only_mode,
outputs=[audio_input]
)
return demo
# Main interface function
@spaces.GPU()
def main_interface(user_prompt, image=None, audio=None, doc=None, voice_only=False, websearch=False):
vqa_model.to(device='cuda', dtype=torch.bfloat16)
tts_model.to("cuda")
unet.to("cuda")
image_pipe.to("cuda")
response = handle_input(user_prompt, image=image, audio=audio, doc=doc, websearch=websearch)
if voice_only:
audio_output = play_voice_output(response)
return "Response generated.", audio_output
else:
return response, None
# Launch the UI
demo = create_ui()
demo.launch()
|