Skip to content

Commit 14c4d64

Browse files
committed
new actions for file, video, image, excel, powerpoint, fix twitter and updates
1 parent 70bd47b commit 14c4d64

File tree

13 files changed

+887
-49
lines changed

13 files changed

+887
-49
lines changed

‎.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -130,6 +130,7 @@ env.bak/
130130
venv.bak/
131131

132132
assistant_outputs/
133+
assistants_working_folder/
133134

134135
logs.txt
135136

‎logs/logs.txt

Lines changed: 41 additions & 16 deletions
Large diffs are not rendered by default.

‎main.py

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
import re
33
import threading
44
from contextlib import contextmanager
5+
import os
56

67
import gradio as gr
78

@@ -12,6 +13,7 @@
1213
from playground.environment_manager import EnvironmentManager
1314
from playground.logging import Logger
1415
from playground.semantic_manager import SemanticManager
16+
from playground.constants import ASSISTANTS_WORKING_FOLDER
1517

1618
thread = api.create_thread() # create a new thread everytime this is run
1719
actions_manager = ActionsManager()
@@ -78,6 +80,27 @@ def dummy_stream(*args, **kwargs):
7880
yield ["streaming data"]
7981

8082

83+
def extract_file_paths(text):
84+
# Regular expression pattern to match file paths
85+
# This pattern matches typical file paths in Windows and Unix-like systems
86+
pattern = r"(?:[a-zA-Z]:\\)?(?:[a-zA-Z0-9_-]+\\)*[a-zA-Z0-9_-]+\.[a-zA-Z0-9]+|(?:\/[a-zA-Z0-9_-]+)+\/?"
87+
88+
# Find all matching file paths in the text
89+
file_paths = re.findall(pattern, text)
90+
91+
unique_file_paths = list(set(file_paths))
92+
93+
return unique_file_paths
94+
95+
96+
def get_file_path(file):
97+
if os.path.isabs(file):
98+
return file
99+
100+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, file)
101+
return file_path
102+
103+
81104
def run(history, assistant_id):
82105
assistant = api.retrieve_assistant(assistant_id)
83106
output_queue = queue.Queue()
@@ -117,6 +140,14 @@ def stream_worker(assistant_id, thread_id, event_handler):
117140
pass
118141
# history[-1][1] = wrap_latex_with_markdown(history[-1][1])
119142
yield history
143+
144+
files = extract_file_paths(history[-1][1])
145+
for file in files:
146+
file_path = get_file_path(file)
147+
if os.path.exists(file_path):
148+
history.append((None, (file_path,)))
149+
yield history
150+
120151
# Final flush of images
121152
while len(eh.images) > 0:
122153
history.append((None, (eh.images.pop(),)))
@@ -171,6 +202,18 @@ def stream_worker(assistant_id, thread_id, event_handler):
171202
#actions {
172203
color: #000000;
173204
}
205+
206+
video {
207+
width: 300px; /* initial width */
208+
height: 200px; /* initial height */
209+
transition: width 0.5s ease, height 0.5s ease;
210+
cursor: pointer;
211+
}
212+
video:hover {
213+
width: auto;
214+
height: auto;
215+
max-width: 100%; /* ensures it doesn’t exceed the container's width */
216+
}
174217
"""
175218

176219
# theme = gr.themes.Default()
Lines changed: 64 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,64 @@
1+
import pandas as pd
2+
import io
3+
import os
4+
5+
from playground.actions_manager import agent_action
6+
from playground.constants import ASSISTANTS_WORKING_FOLDER
7+
8+
9+
@agent_action
10+
def excel_to_csv(filename, skiprows):
11+
"""
12+
Reads an Excel file, skips the specified number of rows, and returns the content as a CSV-formatted text string.
13+
14+
Parameters:
15+
filename (str): The path to the Excel file.
16+
skiprows (int or list of int): The number of rows to skip at the start or a list of row indices to skip.
17+
18+
Returns:
19+
str: The CSV-formatted text string.
20+
"""
21+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, filename)
22+
# Read the Excel file and skip the specified rows
23+
df = pd.read_excel(file_path, skiprows=skiprows)
24+
25+
# Create a buffer to store the CSV content
26+
buffer = io.StringIO()
27+
28+
# Write the DataFrame to the buffer as CSV
29+
df.to_csv(buffer, index=False)
30+
31+
# Get the CSV content from the buffer
32+
csv_content = buffer.getvalue()
33+
34+
# Close the buffer
35+
buffer.close()
36+
37+
return csv_content
38+
39+
40+
@agent_action
41+
def csv_to_excel(csv_content, start_row, filename):
42+
"""
43+
Reads a CSV-formatted text string, skips the specified number of rows, and saves the content as an Excel file.
44+
45+
Parameters:
46+
csv_content (str): The CSV-formatted text string.
47+
start_row (int): The row number to start to add content to.
48+
filename (str): The path to the output Excel file.
49+
50+
Returns:
51+
None
52+
"""
53+
# Create a buffer from the CSV content
54+
buffer = io.StringIO(csv_content)
55+
56+
# Read the CSV content into a DataFrame, skipping the specified rows
57+
df = pd.read_csv(buffer)
58+
59+
# Save the DataFrame to an Excel file
60+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, filename)
61+
df.to_excel(file_path, index=False, startrow=start_row)
62+
63+
# Close the buffer
64+
buffer.close()

‎playground/assistant_actions/file_actions.py

Lines changed: 21 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,7 @@
11
import os
22

33
from playground.actions_manager import agent_action
4-
5-
OUTPUT_FOLDER = "assistant_outputs"
4+
from playground.constants import ASSISTANTS_WORKING_FOLDER
65

76

87
@agent_action
@@ -13,10 +12,10 @@ def save_file(filename, content):
1312
:param filename: The name of the file including extension.
1413
:param content: The content to save in the file.
1514
"""
16-
file_path = os.path.join(OUTPUT_FOLDER, filename)
15+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, filename)
1716
with open(file_path, "w", encoding="utf-8") as file:
1817
file.write(content)
19-
print(f"File '{filename}' saved successfully.")
18+
return f"File '{filename}' saved successfully."
2019

2120

2221
@agent_action
@@ -27,7 +26,7 @@ def load_file(filename):
2726
:param filename: The name of the file including extension.
2827
:return: The content of the file.
2928
"""
30-
file_path = os.path.join(OUTPUT_FOLDER, filename)
29+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, filename)
3130
if not os.path.exists(file_path):
3231
print(f"File '{filename}' does not exist.")
3332
return None
@@ -45,12 +44,12 @@ def delete_file(filename):
4544
4645
:param filename: The name of the file including extension.
4746
"""
48-
file_path = os.path.join(OUTPUT_FOLDER, filename)
47+
file_path = os.path.join(ASSISTANTS_WORKING_FOLDER, filename)
4948
if os.path.exists(file_path):
5049
os.remove(file_path)
51-
print(f"File '{filename}' deleted successfully.")
50+
return f"File '{filename}' deleted successfully."
5251
else:
53-
print(f"File '{filename}' does not exist.")
52+
return f"File '{filename}' does not exist."
5453

5554

5655
@agent_action
@@ -60,12 +59,23 @@ def create_folder(foldername):
6059
6160
:param foldername: The name of the folder to create.
6261
"""
63-
folder_path = os.path.join(OUTPUT_FOLDER, foldername)
62+
folder_path = os.path.join(ASSISTANTS_WORKING_FOLDER, foldername)
6463
if not os.path.exists(folder_path):
6564
os.makedirs(folder_path)
66-
print(f"Folder '{foldername}' created successfully.")
65+
return f"Folder '{foldername}' created successfully."
6766
else:
68-
print(f"Folder '{foldername}' already exists.")
67+
return f"Folder '{foldername}' already exists."
68+
69+
70+
@agent_action
71+
def list_files():
72+
"""
73+
List all files in the working folder.
74+
75+
:return: A list of file names.
76+
"""
77+
files = os.listdir(ASSISTANTS_WORKING_FOLDER)
78+
return files
6979

7080

7181
# # Example usage:
Lines changed: 116 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,116 @@
1+
import os
2+
import requests
3+
from openai import OpenAI
4+
from dotenv import load_dotenv
5+
import base64
6+
7+
from playground.actions_manager import agent_action
8+
from playground.constants import ASSISTANTS_WORKING_FOLDER
9+
10+
load_dotenv()
11+
12+
client = OpenAI()
13+
14+
15+
@agent_action
16+
def create_image(prompt, model="dall-e-3", size="1024x1024", quality="standard", n=1):
17+
"""
18+
Generate an image based on the provided prompt using the DALL-E model.
19+
Args:
20+
prompt (str): The prompt used to generate the image.
21+
model (str, optional): The model used to generate the image. Defaults to "dall-e-3".
22+
size (str, optional): The size of the image in pixels. Defaults to "1024x1024". Options are 1024x1024, 1024x1792 or 1792x1024.
23+
quality (str, optional): The quality of the generation. Defaults to "standard". Options are "standard" or "hd" for high definition.
24+
n (int, optional): The number of generations. Defaults to 1. Always 1 for now.
25+
Returns:
26+
str: The path to the generated image file.
27+
"""
28+
29+
try:
30+
response = client.images.generate(
31+
model=model, prompt=prompt, size=size, quality=quality, n=n
32+
)
33+
image_url = response.data[0].url
34+
except Exception as e:
35+
return str(e)
36+
37+
# Download the image
38+
image_response = requests.get(image_url)
39+
if image_response.status_code == 200:
40+
local_filename = f"{prompt.replace(' ', '_').replace(',','')[:50]}.png"
41+
local_path = os.path.join(ASSISTANTS_WORKING_FOLDER, local_filename)
42+
with open(local_path, "wb") as f:
43+
f.write(image_response.content)
44+
return local_filename
45+
else:
46+
raise Exception(
47+
f"Failed to download image, status code: {image_response.status_code}"
48+
)
49+
50+
51+
def encode_image(image_filename):
52+
"""
53+
Encode the image to base64 format.
54+
55+
Args:
56+
image_path (str): The path to the image file.
57+
58+
Returns:
59+
str: The base64 encoded string of the image.
60+
"""
61+
local_path = os.path.join(ASSISTANTS_WORKING_FOLDER, image_filename)
62+
if not os.path.exists(local_path):
63+
return f"File not found: {image_filename}"
64+
with open(local_path, "rb") as image_file:
65+
return base64.b64encode(image_file.read()).decode("utf-8")
66+
67+
68+
@agent_action
69+
def describe_image(
70+
image_filename,
71+
model="gpt-4o",
72+
prompt="""
73+
Describe exactly what is in the image and locate the objects in the image relative to its position.
74+
e.g. "There is a cat sitting on the table in the bottom right of the image."
75+
""",
76+
max_tokens=512,
77+
):
78+
"""
79+
Describe the content of an image using the OpenAI API.
80+
81+
Args:
82+
image_path (str): The path to the image file.
83+
model (str, optional): The model to use for the OpenAI API. Defaults to "gpt-4o".
84+
prompt (str, optional): The prompt to describe the image. Defaults to 'Describe exactly what is in the image and locate the objects in the image relative to its position. e.g. "There is a cat sitting on the table in the bottom right of the image.'.
85+
max_tokens (int, optional): The maximum number of tokens for the response. Defaults to 512.
86+
87+
Returns:
88+
dict: The response from the OpenAI API.
89+
"""
90+
# Getting the base64 string
91+
base64_image = encode_image(image_filename)
92+
api_key = os.getenv("OPENAI_API_KEY")
93+
headers = {"Content-Type": "application/json", "Authorization": f"Bearer {api_key}"}
94+
95+
payload = {
96+
"model": model,
97+
"messages": [
98+
{
99+
"role": "user",
100+
"content": [
101+
{"type": "text", "text": prompt},
102+
{
103+
"type": "image_url",
104+
"image_url": {"url": f"data:image/jpeg;base64,{base64_image}"},
105+
},
106+
],
107+
}
108+
],
109+
"max_tokens": max_tokens,
110+
}
111+
112+
response = requests.post(
113+
"https://api.openai.com/v1/chat/completions", headers=headers, json=payload
114+
)
115+
116+
return response.json()

0 commit comments

Comments
 (0)