Skip to content

Commit

Permalink
Format Python code with psf/black push
Browse files Browse the repository at this point in the history
  • Loading branch information
github-actions authored and github-actions committed Oct 28, 2023
1 parent ca8193c commit 02d9f1e
Show file tree
Hide file tree
Showing 4 changed files with 125 additions and 83 deletions.
116 changes: 79 additions & 37 deletions cogs/code_interpreter_service_cog.py
Original file line number Diff line number Diff line change
Expand Up @@ -107,12 +107,12 @@ class CodeInterpreterService(discord.Cog, name="CodeInterpreterService"):
"""Cog containing translation commands and retrieval of translation services"""

def __init__(
self,
bot,
gpt_model,
usage_service,
deletion_service,
converser_cog,
self,
bot,
gpt_model,
usage_service,
deletion_service,
converser_cog,
):
super().__init__()
self.bot = bot
Expand All @@ -131,7 +131,7 @@ async def paginate_chat_embed(self, response_text):
"""Given a response text make embed pages and return a list of the pages."""

response_text = [
response_text[i: i + 3500] for i in range(0, len(response_text), 7000)
response_text[i : i + 3500] for i in range(0, len(response_text), 7000)
]
pages = []
first = False
Expand Down Expand Up @@ -194,7 +194,10 @@ async def on_message(self, message):
# If the message channel is in self.chat_agents, then we delegate the message to the agent.
if message.channel.id in self.chat_agents:
if prompt.lower() in ["stop", "end", "quit", "exit"]:
await message.reply("Ending chat session. You can access the sandbox of this session at https://"+self.sessions[message.channel.id].get_hostname())
await message.reply(
"Ending chat session. You can access the sandbox of this session at https://"
+ self.sessions[message.channel.id].get_hostname()
)
self.sessions[message.channel.id].close()
self.chat_agents.pop(message.channel.id)

Expand Down Expand Up @@ -237,30 +240,36 @@ async def on_message(self, message):
# Determine if we have artifacts in the response
artifacts_available = "Artifacts: []" not in stdout_output


# Parse the artifact names. After Artifacts: there should be a list in form [] where the artifact names are inside, comma separated inside stdout_output
artifact_names = re.findall(r"Artifacts: \[(.*?)\]", stdout_output)
# The artifacts list may be formatted like ["'/home/user/artifacts/test2.txt', '/home/user/artifacts/test.txt'"], where its technically 1 element in the list, so we need to split it by comma and then remove the quotes and spaces
if len(artifact_names) > 0:
artifact_names = artifact_names[0].split(",")
artifact_names = [artifact_name.strip().replace("'", "") for artifact_name in artifact_names]
artifact_names = [
artifact_name.strip().replace("'", "")
for artifact_name in artifact_names
]

if len(response) > 2000:
embed_pages = await self.paginate_chat_embed(response)
paginator = pages.Paginator(
pages=embed_pages,
timeout=None,
author_check=False,
custom_view=CodeInterpreterDownloadArtifactsView(message, self, self.sessions[message.channel.id], artifact_names) if artifacts_available else None,
custom_view=CodeInterpreterDownloadArtifactsView(
message, self, self.sessions[message.channel.id], artifact_names
)
if artifacts_available
else None,
)
try:
await paginator.respond(message)
except:
response = [
response[i: i + 1900] for i in range(0, len(response), 1900)
response[i : i + 1900] for i in range(0, len(response), 1900)
]
for count, chunk in enumerate(response, start=1):
await message.channel.send(chunk)
await message.channel.send(chunk)

else:
response = response.replace("\\n", "\n")
Expand All @@ -270,13 +279,18 @@ async def on_message(self, message):
description=response,
color=0x808080,
)
await message.reply(embed=response_embed, view=CodeInterpreterDownloadArtifactsView(message, self, self.sessions[message.channel.id], artifact_names) if artifacts_available else None)

await message.reply(
embed=response_embed,
view=CodeInterpreterDownloadArtifactsView(
message, self, self.sessions[message.channel.id], artifact_names
)
if artifacts_available
else None,
)

self.thread_awaiting_responses.remove(message.channel.id)

class SessionedCodeExecutor:

def __init__(self):
try:
self.session = DataAnalysis(api_key=E2B_API_KEY)
Expand All @@ -299,7 +313,14 @@ async def execute_code_async(self, code: str):

if len(stdout) > 12000:
stdout = stdout[:12000]
return "STDOUT: "+stdout +"\nSTDERR: "+stderr+ "\nArtifacts: " + str([artifact.name for artifact in artifacts])
return (
"STDOUT: "
+ stdout
+ "\nSTDERR: "
+ stderr
+ "\nArtifacts: "
+ str([artifact.name for artifact in artifacts])
)

def close(self):
self.session.close()
Expand All @@ -320,13 +341,15 @@ def is_sessioned(self):
return self.sessioned

async def code_interpreter_chat_command(
self, ctx: discord.ApplicationContext, model,
self,
ctx: discord.ApplicationContext,
model,
):
embed_title = f"{ctx.user.name}'s code interpreter conversation with GPT"
message_embed = discord.Embed(
title=embed_title,
description=f"The agent is able to execute Python code and manipulate its environment.\nModel: {model}\n\nType `end` to stop the conversation",
color=0xf82c45,
color=0xF82C45,
)
message_embed.set_thumbnail(url="https://i.imgur.com/qua6Bya.png")
message_embed.set_footer(
Expand All @@ -342,7 +365,9 @@ async def code_interpreter_chat_command(
self.sessions[thread.id] = self.SessionedCodeExecutor()

if not self.sessions[thread.id].is_sessioned():
await thread.send("Failed to start code interpreter session. This may be an issue with E2B. Please try again later.")
await thread.send(
"Failed to start code interpreter session. This may be an issue with E2B. Please try again later."
)
await thread.edit(name="Closed-GPT (Error)")
await thread.edit(archived=True)
return
Expand All @@ -357,12 +382,12 @@ async def code_interpreter_chat_command(
Tool(
name="Install-python-package-tool",
func=self.sessions[thread.id].install_python_package,
description=f"This tool installs a python package into the execution environment. The input to the tool is a single python package name (e.g 'numpy'). If you need to install multiple python packages, call this tool multiple times."
description=f"This tool installs a python package into the execution environment. The input to the tool is a single python package name (e.g 'numpy'). If you need to install multiple python packages, call this tool multiple times.",
),
Tool(
name="Install-system-package-tool",
func=self.sessions[thread.id].install_python_package,
description=f"This tool installs a system package into the system environment. The input to the tool is a single package name (e.g 'htop'). If you need to install multiple system packages, call this tool multiple times."
description=f"This tool installs a system package into the system environment. The input to the tool is a single package name (e.g 'htop'). If you need to install multiple system packages, call this tool multiple times.",
),
]

Expand All @@ -372,10 +397,11 @@ async def code_interpreter_chat_command(
"extra_prompt_messages": [MessagesPlaceholder(variable_name="memory")],
"system_message": SystemMessage(
content="You are an expert programmer that is able to use the tools to your advantage to execute "
"python code. Help the user iterate on their code and test it through execution. Always "
"respond in the specified JSON format. Always provide the full code output when asked for "
"when you execute code. Ensure that all your code is formatted with backticks followed by the "
"markdown identifier of the language that the code is in. For example ```python3 {code} ```. When asked to write code that saves files, always prefix the file with the artifacts/ folder. For example, if asked to create test.txt, in the function call you make to whatever library that creates the file, you would use artifacts/test.txt. Always show the output of code execution explicitly and separately at the end of the rest of your output. You are also able to install system and python packages using your tools. However, the tools can only install one package at a time, if you need to install multiple packages, call the tools multiple times. Always first display your code to the user BEFORE you execute it using your tools. The user should always explicitly ask you to execute code.")
"python code. Help the user iterate on their code and test it through execution. Always "
"respond in the specified JSON format. Always provide the full code output when asked for "
"when you execute code. Ensure that all your code is formatted with backticks followed by the "
"markdown identifier of the language that the code is in. For example ```python3 {code} ```. When asked to write code that saves files, always prefix the file with the artifacts/ folder. For example, if asked to create test.txt, in the function call you make to whatever library that creates the file, you would use artifacts/test.txt. Always show the output of code execution explicitly and separately at the end of the rest of your output. You are also able to install system and python packages using your tools. However, the tools can only install one package at a time, if you need to install multiple packages, call the tools multiple times. Always first display your code to the user BEFORE you execute it using your tools. The user should always explicitly ask you to execute code."
),
}

llm = ChatOpenAI(model=model, temperature=0, openai_api_key=OPENAI_API_KEY)
Expand All @@ -391,20 +417,25 @@ async def code_interpreter_chat_command(

self.chat_agents[thread.id] = agent_chain


class CodeInterpreterDownloadArtifactsView(discord.ui.View):
def __init__(
self,
ctx,
code_interpreter_cog,
session,
artifact_names,
self,
ctx,
code_interpreter_cog,
session,
artifact_names,
):
super().__init__(timeout=None) # No timeout
self.code_interpreter_cog = code_interpreter_cog
self.ctx = ctx
self.session = session
self.artifact_names = artifact_names
self.add_item(DownloadButton(self.ctx, self.code_interpreter_cog, self.session, self.artifact_names))
self.add_item(
DownloadButton(
self.ctx, self.code_interpreter_cog, self.session, self.artifact_names
)
)


# A view for a follow-up button
Expand All @@ -418,20 +449,31 @@ def __init__(self, ctx, code_interpreter_cog, session, artifact_names):

async def callback(self, interaction: discord.Interaction):
"""Send the followup modal"""
await interaction.response.send_message("Downloading the artifacts: " + str(self.artifact_names) +". This may take a while.", ephemeral=True, delete_after=120)
await interaction.response.send_message(
"Downloading the artifacts: "
+ str(self.artifact_names)
+ ". This may take a while.",
ephemeral=True,
delete_after=120,
)
for artifact in self.artifact_names:
try:
runner = functools.partial(self.session.download_file, filepath=artifact)
runner = functools.partial(
self.session.download_file, filepath=artifact
)

bytes = await asyncio.get_running_loop().run_in_executor(None, runner)
# Save these bytes into a tempfile
with tempfile.NamedTemporaryFile(delete=False) as temp:
temp.write(bytes)
temp.flush()
temp.seek(0)
await self.ctx.channel.send(file=discord.File(temp.name, filename=artifact))
await self.ctx.channel.send(
file=discord.File(temp.name, filename=artifact)
)
os.unlink(temp.name)
except:
traceback.print_exc()
await self.ctx.channel.send("Failed to download artifact: " + artifact, delete_after=120)

await self.ctx.channel.send(
"Failed to download artifact: " + artifact, delete_after=120
)
10 changes: 5 additions & 5 deletions cogs/commands.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,9 @@ def __init__(
name="code",
description="Code interpreter functionalities",
guild_ids=ALLOWED_GUILDS,
checks=[Check.check_index_roles()], # TODO new role checker for code interpreter
checks=[
Check.check_index_roles()
], # TODO new role checker for code interpreter
)

#
Expand Down Expand Up @@ -1029,10 +1031,10 @@ async def ask_gpt_action(self, ctx, message: discord.Message):
async def draw_action(self, ctx, message: discord.Message):
await self.image_draw_cog.draw_action(ctx, message)


"""
Code interpreter commands and actions
"""

@add_to_group("code")
@discord.slash_command(
name="chat",
Expand All @@ -1057,9 +1059,7 @@ async def chat_code(
"Code interpretation is disabled on this server.", ephemeral=True
)
return
await self.code_interpreter_cog.code_interpreter_chat_command(
ctx, model=model
)
await self.code_interpreter_cog.code_interpreter_chat_command(ctx, model=model)

"""
Translation commands and actions
Expand Down
Loading

0 comments on commit 02d9f1e

Please sign in to comment.