Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

File upload fixes. Set auto_continue to True by default #1271

Merged
merged 17 commits into from
Oct 22, 2024
54 changes: 42 additions & 12 deletions agixt/Agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -9,8 +9,10 @@
ChainStep,
ChainStepArgument,
ChainStepResponse,
Chain as ChainDB,
Provider as ProviderModel,
User,
Extension,
UserPreferences,
get_session,
)
Expand Down Expand Up @@ -481,23 +483,49 @@ def update_agent_config(self, new_config, config_key):

if config_key == "commands":
for command_name, enabled in new_config.items():
# First try to find an existing command
command = session.query(Command).filter_by(name=command_name).first()

if not command:
# If the command doesn't exist, create it (this handles chain commands)
command = Command(name=command_name)
session.add(command)
session.commit()

agent_command = (
session.query(AgentCommand)
.filter_by(agent_id=agent.id, command_id=command.id)
.first()
)
# Check if this is a chain command
chain = session.query(ChainDB).filter_by(name=command_name).first()
if chain:
# Find or create the AGiXT Chains extension
extension = (
session.query(Extension)
.filter_by(name="AGiXT Chains")
.first()
)
if not extension:
extension = Extension(name="AGiXT Chains")
session.add(extension)
session.commit()

# Create a new command entry for the chain
command = Command(name=command_name, extension_id=extension.id)
session.add(command)
session.commit()
else:
logging.error(f"Command {command_name} not found.")
continue

# Now handle the agent command association
try:
agent_command = (
session.query(AgentCommand)
.filter_by(agent_id=agent.id, command_id=command.id)
.first()
)
except:
agent_command = None

if agent_command:
agent_command.state = enabled
else:
agent_command = AgentCommand(
agent_id=agent.id, command_id=command.id, state=enabled
agent_id=self.agent_id,
command_id=command.id,
state=enabled,
)
session.add(agent_command)
else:
Expand All @@ -511,7 +539,9 @@ def update_agent_config(self, new_config, config_key):
agent_setting.value = str(setting_value)
else:
agent_setting = AgentSettingModel(
agent_id=agent.id, name=setting_name, value=str(setting_value)
agent_id=agent.id,
name=setting_name,
value=str(setting_value),
)
session.add(agent_setting)

Expand Down
144 changes: 82 additions & 62 deletions agixt/XT.py
Original file line number Diff line number Diff line change
Expand Up @@ -483,27 +483,18 @@ async def run_chain_step(
role=self.agent_name,
message=f"[ACTIVITY] Running prompt: `{prompt_name}` with args:\n```json\n{json.dumps(args, indent=2)}```",
)
if "user_input" in args:
user_input = args["user_input"]
del args["user_input"]
if "browse_links" not in args:
args["browse_links"] = False
if "log_output" in args:
del args["log_output"]
if "voice_response" in args:
del args["voice_response"]
if "log_user_input" in args:
del args["log_user_input"]
if "prompt_name" in args:
del args["prompt_name"]
if prompt_name != "":
result = await self.inference(
if "browse_links" not in args:
args["browse_links"] = False
args["prompt_name"] = prompt_name
args["log_user_input"] = False
args["voice_response"] = False
args["log_output"] = False
args["user_input"] = user_input
result = self.ApiClient.prompt_agent(
agent_name=agent_name,
prompt_name=prompt_name,
user_input=user_input,
log_user_input=False,
log_output=False,
voice_response=False,
**args,
prompt_args=args,
)
elif prompt_type == "chain":
self.conversation.log_interaction(
Expand Down Expand Up @@ -647,51 +638,73 @@ async def learn_from_websites(
async def learn_spreadsheet(self, user_input, file_path):
file_name = os.path.basename(file_path)
file_type = str(file_name).split(".")[-1]
if file_type.lower() == "csv":
df = pd.read_csv(file_path)
else: # Excel file
try:
if file_type.lower() == "csv":
df = pd.read_csv(file_path)
else: # Excel file
try:
xl = pd.ExcelFile(file_path)
if len(xl.sheet_names) > 1:
sheet_count = len(xl.sheet_names)
for i, sheet_name in enumerate(xl.sheet_names, 1):
df = xl.parse(sheet_name)
csv_file_path = file_path.replace(
f".{file_type}", f"_{i}.csv"
)
csv_file_name = os.path.basename(csv_file_path)
self.conversation.log_interaction(
role=self.agent_name,
message=f"[ACTIVITY] ({i}/{sheet_count}) Converted sheet `{sheet_name}` in `{file_name}` to CSV file `{csv_file_name}`.",
)
df.to_csv(csv_file_path, index=False)
message = await self.learn_spreadsheet(
user_input=user_input,
file_path=csv_file_path,
)
self.conversation.log_interaction(
role=self.agent_name, message=f"[ACTIVITY] {message}"
)
return f"Processed all sheets in [{file_name}]({file_path})."
else:
df = pd.read_excel(file_path)
except Exception as e:
self.conversation.log_interaction(
role=self.agent_name,
message=f"[ACTIVITY][ERROR] Failed to read Excel file `{file_name}`: {str(e)}",
)
return f"Failed to read [{file_name}]({file_path}). Error: {str(e)}"

try:
xl = pd.ExcelFile(file_path)
if len(xl.sheet_names) > 1:
sheet_count = len(xl.sheet_names)
for i, sheet_name in enumerate(xl.sheet_names, 1):
df = xl.parse(sheet_name)
csv_file_path = file_path.replace(f".{file_type}", f"_{i}.csv")
csv_file_name = os.path.basename(csv_file_path)
self.conversation.log_interaction(
role=self.agent_name,
message=f"[ACTIVITY] ({i}/{sheet_count}) Converted sheet `{sheet_name}` in `{file_name}` to CSV file `{csv_file_name}`.",
)
df.to_csv(csv_file_path, index=False)
message = await self.learn_spreadsheet(
user_input=user_input,
file_path=csv_file_path,
)
self.conversation.log_interaction(
role=self.agent_name, message=f"[ACTIVITY] {message}"
)
return f"Processed all sheets in [{file_name}]({file_path})."
else:
df = pd.read_excel(file_path)
df_dict = df.to_dict("records")
# Test JSON serialization before proceeding
json.dumps(df_dict)
except Exception as e:
self.conversation.log_interaction(
role=self.agent_name,
message=f"[ACTIVITY][ERROR] Failed to read Excel file `{file_name}`: {str(e)}",
)
return f"Failed to read [{file_name}]({file_path}). Error: {str(e)}"
logging.error(f"Error converting DataFrame to dict: {e}")
return f"Failed to process [{file_name}]({file_path}). Error converting data format: {str(e)}"

df_dict = df.to_dict("records")
self.input_tokens += get_tokens(json.dumps(df_dict))
for item in df_dict:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = f"Content from file uploaded at {timestamp} named `{file_name}`:\n```json\n{json.dumps(item, indent=2)}```\n"
await self.file_reader.write_text_to_memory(
user_input=f"{user_input}\n{message}",
text=message,
external_source=f"file {file_path}",
)
try:
self.input_tokens += get_tokens(json.dumps(df_dict))
except Exception as e:
logging.error(f"Error calculating tokens: {e}")
# Continue processing even if token calculation fails

return f"Read [{file_name}]({file_path}) into memory."
try:
for item in df_dict:
timestamp = datetime.now().strftime("%Y-%m-%d %H:%M:%S")
message = f"Content from file uploaded at {timestamp} named `{file_name}`:\n```json\n{json.dumps(item, indent=2)}```\n"
await self.file_reader.write_text_to_memory(
user_input=f"{user_input}\n{message}",
text=message,
external_source=f"file {file_path}",
)
return f"Read [{file_name}]({file_path}) into memory."
except Exception as e:
logging.error(f"Error writing to memory: {e}")
return f"Failed to save [{file_name}]({file_path}) to memory. Error: {str(e)}"

except Exception as e:
logging.error(f"Unexpected error processing spreadsheet: {e}")
return f"Failed to process [{file_name}]({file_path}). Unexpected error: {str(e)}"

async def learn_from_file(
self,
Expand Down Expand Up @@ -756,7 +769,7 @@ async def learn_from_file(
message=f"[ACTIVITY] Converting PowerPoint file [{file_name}]({file_url}) to PDF.",
)
try:
subprocess.run(
result = subprocess.run(
[
"libreoffice",
"--headless",
Expand All @@ -768,10 +781,17 @@ async def learn_from_file(
],
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
timeout=30,
)
if result.returncode != 0:
raise Exception(
f"Conversion failed: {result.stderr.decode('utf-8', errors='ignore')}"
)
except Exception as e:
logging.error(f"Error converting PowerPoint to PDF: {e}")
return f"Failed to convert PowerPoint file [{file_name}]({file_url}) to PDF. Error: {str(e)}"
file_path = pdf_file_path
file_type = "pdf"
if user_input == "":
user_input = "Describe each stage of this image."
disallowed_types = ["exe", "bin", "rar"]
Expand Down Expand Up @@ -1328,7 +1348,7 @@ async def chat_completions(self, prompt: ChatCompletions):
analyze_user_input = (
str(self.agent_settings["analyze_user_input"]).lower() == "true"
)
auto_continue = False
auto_continue = True
if "auto_continue" in self.agent_settings:
auto_continue = str(self.agent_settings["auto_continue"]).lower() == "true"
include_sources = False
Expand Down
28 changes: 4 additions & 24 deletions agixt/endpoints/Agent.py
Original file line number Diff line number Diff line change
Expand Up @@ -344,30 +344,10 @@ async def toggle_command(
raise HTTPException(status_code=403, detail="Access Denied")
ApiClient = get_api_client(authorization=authorization)
agent = Agent(agent_name=agent_name, user=user, ApiClient=ApiClient)
try:
if payload.command_name == "*":
for each_command_name in agent.AGENT_CONFIG["commands"]:
agent.AGENT_CONFIG["commands"][each_command_name] = payload.enable

agent.update_agent_config(
new_config=agent.AGENT_CONFIG["commands"], config_key="commands"
)
return ResponseMessage(
message=f"All commands enabled for agent '{agent_name}'."
)
else:
agent.AGENT_CONFIG["commands"][payload.command_name] = payload.enable
agent.update_agent_config(
new_config=agent.AGENT_CONFIG["commands"], config_key="commands"
)
return ResponseMessage(
message=f"Command '{payload.command_name}' toggled for agent '{agent_name}'."
)
except Exception as e:
raise HTTPException(
status_code=500,
detail=f"Error enabling all commands for agent '{agent_name}': {str(e)}",
)
update_config = agent.update_agent_config(
new_config={payload.command_name: payload.enable}, config_key="commands"
)
return ResponseMessage(message=update_config)


# Get agent browsed links
Expand Down
2 changes: 1 addition & 1 deletion docker-compose-dev.yml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
services:
agixt:
image: joshxt/agixt:main
image: ghcr.io/josh-xt/agixt:dev
init: true
environment:
DATABASE_TYPE: ${DATABASE_TYPE:-sqlite}
Expand Down
Loading
Loading