swarms 7.6.2__py3-none-any.whl → 7.6.5__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- swarms/__init__.py +1 -0
- swarms/agents/__init__.py +0 -3
- swarms/agents/flexion_agent.py +2 -1
- swarms/client/__init__.py +15 -0
- swarms/prompts/multi_agent_collab_prompt.py +313 -0
- swarms/structs/__init__.py +5 -17
- swarms/structs/agent.py +219 -255
- swarms/structs/base_swarm.py +0 -7
- swarms/structs/concurrent_workflow.py +1 -1
- swarms/structs/conversation.py +16 -2
- swarms/structs/de_hallucination_swarm.py +8 -4
- swarms/structs/groupchat.py +80 -84
- swarms/structs/hybrid_hiearchical_peer_swarm.py +23 -40
- swarms/structs/multi_agent_exec.py +63 -139
- swarms/structs/rearrange.py +65 -204
- swarms/structs/sequential_workflow.py +34 -47
- swarms/structs/swarm_router.py +2 -1
- swarms/telemetry/bootup.py +19 -38
- swarms/telemetry/main.py +56 -20
- swarms/tools/mcp_integration.py +321 -483
- swarms/utils/auto_download_check_packages.py +2 -2
- swarms/utils/disable_logging.py +0 -17
- swarms/utils/history_output_formatter.py +8 -3
- swarms/utils/litellm_wrapper.py +117 -1
- swarms/utils/vllm_wrapper.py +146 -0
- {swarms-7.6.2.dist-info → swarms-7.6.5.dist-info}/METADATA +1 -5
- {swarms-7.6.2.dist-info → swarms-7.6.5.dist-info}/RECORD +31 -31
- swarms/structs/auto_swarm.py +0 -229
- swarms/utils/agent_ops_check.py +0 -26
- swarms/utils/pandas_utils.py +0 -92
- /swarms/{structs/swarms_api.py → client/main.py} +0 -0
- {swarms-7.6.2.dist-info → swarms-7.6.5.dist-info}/LICENSE +0 -0
- {swarms-7.6.2.dist-info → swarms-7.6.5.dist-info}/WHEEL +0 -0
- {swarms-7.6.2.dist-info → swarms-7.6.5.dist-info}/entry_points.txt +0 -0
swarms/structs/agent.py
CHANGED
@@ -6,7 +6,6 @@ import random
|
|
6
6
|
import threading
|
7
7
|
import time
|
8
8
|
import uuid
|
9
|
-
|
10
9
|
from concurrent.futures import ThreadPoolExecutor
|
11
10
|
from datetime import datetime
|
12
11
|
from typing import (
|
@@ -39,10 +38,8 @@ from swarms.schemas.base_schemas import (
|
|
39
38
|
ChatCompletionResponseChoice,
|
40
39
|
ChatMessageResponse,
|
41
40
|
)
|
42
|
-
from swarms.structs.
|
41
|
+
from swarms.structs.agent_roles import agent_roles
|
43
42
|
from swarms.structs.conversation import Conversation
|
44
|
-
|
45
|
-
# from swarms.structs.multi_agent_exec import run_agents_concurrently
|
46
43
|
from swarms.structs.safe_loading import (
|
47
44
|
SafeLoaderUtils,
|
48
45
|
SafeStateManager,
|
@@ -54,11 +51,19 @@ from swarms.utils.any_to_str import any_to_str
|
|
54
51
|
from swarms.utils.data_to_text import data_to_text
|
55
52
|
from swarms.utils.file_processing import create_file_in_folder
|
56
53
|
from swarms.utils.formatter import formatter
|
54
|
+
from swarms.utils.history_output_formatter import (
|
55
|
+
history_output_formatter,
|
56
|
+
)
|
57
57
|
from swarms.utils.litellm_tokenizer import count_tokens
|
58
58
|
from swarms.utils.pdf_to_text import pdf_to_text
|
59
|
-
from swarms.structs.agent_roles import agent_roles
|
60
59
|
from swarms.utils.str_to_dict import str_to_dict
|
61
60
|
|
61
|
+
from swarms.tools.mcp_integration import (
|
62
|
+
batch_mcp_flow,
|
63
|
+
mcp_flow_get_tool_schema,
|
64
|
+
MCPServerSseParams,
|
65
|
+
)
|
66
|
+
|
62
67
|
|
63
68
|
# Utils
|
64
69
|
# Custom stopping condition
|
@@ -353,6 +358,7 @@ class Agent:
|
|
353
358
|
role: agent_roles = "worker",
|
354
359
|
no_print: bool = False,
|
355
360
|
tools_list_dictionary: Optional[List[Dict[str, Any]]] = None,
|
361
|
+
mcp_servers: List[MCPServerSseParams] = [],
|
356
362
|
*args,
|
357
363
|
**kwargs,
|
358
364
|
):
|
@@ -472,13 +478,23 @@ class Agent:
|
|
472
478
|
self.role = role
|
473
479
|
self.no_print = no_print
|
474
480
|
self.tools_list_dictionary = tools_list_dictionary
|
481
|
+
self.mcp_servers = mcp_servers
|
482
|
+
|
483
|
+
if (
|
484
|
+
self.agent_name is not None
|
485
|
+
or self.agent_description is not None
|
486
|
+
):
|
487
|
+
prompt = f"Your Name: {self.agent_name} \n\n Your Description: {self.agent_description} \n\n {system_prompt}"
|
488
|
+
else:
|
489
|
+
prompt = system_prompt
|
475
490
|
|
476
491
|
# Initialize the short term memory
|
477
492
|
self.short_memory = Conversation(
|
478
|
-
system_prompt=
|
493
|
+
system_prompt=prompt,
|
479
494
|
time_enabled=False,
|
480
495
|
user=user_name,
|
481
496
|
rules=rules,
|
497
|
+
token_count=False,
|
482
498
|
*args,
|
483
499
|
**kwargs,
|
484
500
|
)
|
@@ -504,24 +520,10 @@ class Agent:
|
|
504
520
|
tool_system_prompt=tool_system_prompt,
|
505
521
|
)
|
506
522
|
|
507
|
-
#
|
508
|
-
|
509
|
-
|
510
|
-
|
511
|
-
|
512
|
-
# If multimodal = yes then set the sop to the multimodal sop
|
513
|
-
if self.multi_modal is True:
|
514
|
-
self.sop = MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1
|
515
|
-
|
516
|
-
# If the preset stopping token is enabled then set the stopping token to the preset stopping token
|
517
|
-
if preset_stopping_token is not None:
|
518
|
-
self.stopping_token = "<DONE>"
|
519
|
-
|
520
|
-
# If the docs exist then ingest the docs
|
521
|
-
# if exists(self.docs):
|
522
|
-
# threading.Thread(
|
523
|
-
# target=self.ingest_docs, args=(self.docs)
|
524
|
-
# ).start()
|
523
|
+
# Some common configuration settings
|
524
|
+
threading.Thread(
|
525
|
+
target=self.setup_config, daemon=True
|
526
|
+
).start()
|
525
527
|
|
526
528
|
# If docs folder exists then get the docs from docs folder
|
527
529
|
if exists(self.docs_folder):
|
@@ -567,10 +569,6 @@ class Agent:
|
|
567
569
|
if exists(self.sop) or exists(self.sop_list):
|
568
570
|
threading.Thread(target=self.handle_sop_ops()).start()
|
569
571
|
|
570
|
-
# If agent_ops is on => activate agentops
|
571
|
-
if agent_ops_on is True:
|
572
|
-
threading.Thread(target=self.activate_agentops()).start()
|
573
|
-
|
574
572
|
# Many steps
|
575
573
|
self.agent_output = ManySteps(
|
576
574
|
agent_id=agent_id,
|
@@ -594,6 +592,12 @@ class Agent:
|
|
594
592
|
if self.llm is None:
|
595
593
|
self.llm = self.llm_handling()
|
596
594
|
|
595
|
+
if (
|
596
|
+
self.tools_list_dictionary is None
|
597
|
+
and self.mcp_servers is not None
|
598
|
+
):
|
599
|
+
self.tools_list_dictionary = self.mcp_tool_handling()
|
600
|
+
|
597
601
|
def llm_handling(self):
|
598
602
|
from swarms.utils.litellm_wrapper import LiteLLM
|
599
603
|
|
@@ -634,12 +638,90 @@ class Agent:
|
|
634
638
|
temperature=self.temperature,
|
635
639
|
max_tokens=self.max_tokens,
|
636
640
|
system_prompt=self.system_prompt,
|
641
|
+
stream=self.streaming_on,
|
637
642
|
)
|
638
643
|
return llm
|
639
644
|
except Exception as e:
|
640
645
|
logger.error(f"Error in llm_handling: {e}")
|
641
646
|
return None
|
642
647
|
|
648
|
+
def mcp_execution_flow(self, response: any):
|
649
|
+
"""
|
650
|
+
Executes the MCP (Model Context Protocol) flow based on the provided response.
|
651
|
+
|
652
|
+
This method takes a response, converts it from a string to a dictionary format,
|
653
|
+
and checks for the presence of a tool name or a name in the response. If either
|
654
|
+
is found, it retrieves the tool name and proceeds to call the batch_mcp_flow
|
655
|
+
function to execute the corresponding tool actions.
|
656
|
+
|
657
|
+
Args:
|
658
|
+
response (any): The response to be processed, which can be in string format
|
659
|
+
that represents a dictionary.
|
660
|
+
|
661
|
+
Returns:
|
662
|
+
The output from the batch_mcp_flow function, which contains the results of
|
663
|
+
the tool execution. If an error occurs during processing, it logs the error
|
664
|
+
and returns None.
|
665
|
+
|
666
|
+
Raises:
|
667
|
+
Exception: Logs any exceptions that occur during the execution flow.
|
668
|
+
"""
|
669
|
+
try:
|
670
|
+
response = str_to_dict(response)
|
671
|
+
|
672
|
+
tool_output = batch_mcp_flow(
|
673
|
+
self.mcp_servers,
|
674
|
+
function_call=response,
|
675
|
+
)
|
676
|
+
|
677
|
+
return tool_output
|
678
|
+
except Exception as e:
|
679
|
+
logger.error(f"Error in mcp_execution_flow: {e}")
|
680
|
+
return None
|
681
|
+
|
682
|
+
def mcp_tool_handling(self):
|
683
|
+
"""
|
684
|
+
Handles the retrieval of tool schemas from the MCP servers.
|
685
|
+
|
686
|
+
This method iterates over the list of MCP servers, retrieves the tool schema
|
687
|
+
for each server using the mcp_flow_get_tool_schema function, and compiles
|
688
|
+
these schemas into a list. The resulting list is stored in the
|
689
|
+
tools_list_dictionary attribute.
|
690
|
+
|
691
|
+
Returns:
|
692
|
+
list: A list of tool schemas retrieved from the MCP servers. If an error
|
693
|
+
occurs during the retrieval process, it logs the error and returns None.
|
694
|
+
|
695
|
+
Raises:
|
696
|
+
Exception: Logs any exceptions that occur during the tool handling process.
|
697
|
+
"""
|
698
|
+
try:
|
699
|
+
self.tools_list_dictionary = []
|
700
|
+
|
701
|
+
for mcp_server in self.mcp_servers:
|
702
|
+
tool_schema = mcp_flow_get_tool_schema(mcp_server)
|
703
|
+
self.tools_list_dictionary.append(tool_schema)
|
704
|
+
|
705
|
+
print(self.tools_list_dictionary)
|
706
|
+
return self.tools_list_dictionary
|
707
|
+
except Exception as e:
|
708
|
+
logger.error(f"Error in mcp_tool_handling: {e}")
|
709
|
+
return None
|
710
|
+
|
711
|
+
def setup_config(self):
|
712
|
+
# The max_loops will be set dynamically if the dynamic_loop
|
713
|
+
if self.dynamic_loops is True:
|
714
|
+
logger.info("Dynamic loops enabled")
|
715
|
+
self.max_loops = "auto"
|
716
|
+
|
717
|
+
# If multimodal = yes then set the sop to the multimodal sop
|
718
|
+
if self.multi_modal is True:
|
719
|
+
self.sop = MULTI_MODAL_AUTO_AGENT_SYSTEM_PROMPT_1
|
720
|
+
|
721
|
+
# If the preset stopping token is enabled then set the stopping token to the preset stopping token
|
722
|
+
if self.preset_stopping_token is not None:
|
723
|
+
self.stopping_token = "<DONE>"
|
724
|
+
|
643
725
|
def prepare_tools_list_dictionary(self):
|
644
726
|
import json
|
645
727
|
|
@@ -775,18 +857,6 @@ class Agent:
|
|
775
857
|
""",
|
776
858
|
)
|
777
859
|
|
778
|
-
def loop_count_print(
|
779
|
-
self, loop_count: int, max_loops: int
|
780
|
-
) -> None:
|
781
|
-
"""loop_count_print summary
|
782
|
-
|
783
|
-
Args:
|
784
|
-
loop_count (_type_): _description_
|
785
|
-
max_loops (_type_): _description_
|
786
|
-
"""
|
787
|
-
logger.info(f"\nLoop {loop_count} of {max_loops}")
|
788
|
-
print("\n")
|
789
|
-
|
790
860
|
# Check parameters
|
791
861
|
def check_parameters(self):
|
792
862
|
if self.llm is None:
|
@@ -837,8 +907,6 @@ class Agent:
|
|
837
907
|
try:
|
838
908
|
self.check_if_no_prompt_then_autogenerate(task)
|
839
909
|
|
840
|
-
self.agent_output.task = task
|
841
|
-
|
842
910
|
# Add task to memory
|
843
911
|
self.short_memory.add(role=self.user_name, content=task)
|
844
912
|
|
@@ -848,17 +916,17 @@ class Agent:
|
|
848
916
|
|
849
917
|
# Set the loop count
|
850
918
|
loop_count = 0
|
919
|
+
|
851
920
|
# Clear the short memory
|
852
921
|
response = None
|
853
|
-
all_responses = []
|
854
922
|
|
855
923
|
# Query the long term memory first for the context
|
856
924
|
if self.long_term_memory is not None:
|
857
925
|
self.memory_query(task)
|
858
926
|
|
859
|
-
#
|
860
|
-
|
927
|
+
# Autosave
|
861
928
|
if self.autosave:
|
929
|
+
log_agent_data(self.to_dict())
|
862
930
|
self.save()
|
863
931
|
|
864
932
|
# Print the request
|
@@ -873,8 +941,11 @@ class Agent:
|
|
873
941
|
or loop_count < self.max_loops
|
874
942
|
):
|
875
943
|
loop_count += 1
|
876
|
-
|
877
|
-
|
944
|
+
|
945
|
+
# self.short_memory.add(
|
946
|
+
# role=f"{self.agent_name}",
|
947
|
+
# content=f"Internal Reasoning Loop: {loop_count} of {self.max_loops}",
|
948
|
+
# )
|
878
949
|
|
879
950
|
# Dynamic temperature
|
880
951
|
if self.dynamic_temperature_enabled is True:
|
@@ -905,48 +976,24 @@ class Agent:
|
|
905
976
|
if img is None
|
906
977
|
else (task_prompt, img, *args)
|
907
978
|
)
|
979
|
+
|
980
|
+
# Call the LLM
|
908
981
|
response = self.call_llm(
|
909
982
|
*response_args, **kwargs
|
910
983
|
)
|
911
984
|
|
912
985
|
# Convert to a str if the response is not a str
|
913
|
-
response = self.
|
986
|
+
response = self.parse_llm_output(response)
|
914
987
|
|
915
|
-
|
916
|
-
|
917
|
-
|
918
|
-
# # break
|
988
|
+
self.short_memory.add(
|
989
|
+
role=self.agent_name, content=response
|
990
|
+
)
|
919
991
|
|
920
992
|
# Print
|
921
|
-
|
922
|
-
|
923
|
-
|
924
|
-
|
925
|
-
f"{self.agent_name}: {response}",
|
926
|
-
title=f"Agent Name: {self.agent_name} [Max Loops: {loop_count}]",
|
927
|
-
)
|
928
|
-
else:
|
929
|
-
# logger.info(f"Response: {response}")
|
930
|
-
formatter.print_panel(
|
931
|
-
f"{self.agent_name}: {response}",
|
932
|
-
f"Agent Name {self.agent_name} [Max Loops: {loop_count} ]",
|
933
|
-
)
|
934
|
-
|
935
|
-
# Check if response is a dictionary and has 'choices' key
|
936
|
-
if (
|
937
|
-
isinstance(response, dict)
|
938
|
-
and "choices" in response
|
939
|
-
):
|
940
|
-
response = response["choices"][0][
|
941
|
-
"message"
|
942
|
-
]["content"]
|
943
|
-
elif isinstance(response, str):
|
944
|
-
# If response is already a string, use it as is
|
945
|
-
pass
|
946
|
-
else:
|
947
|
-
raise ValueError(
|
948
|
-
f"Unexpected response format: {type(response)}"
|
949
|
-
)
|
993
|
+
self.pretty_print(response, loop_count)
|
994
|
+
|
995
|
+
# Output Cleaner
|
996
|
+
self.output_cleaner_op(response)
|
950
997
|
|
951
998
|
# Check and execute tools
|
952
999
|
if self.tools is not None:
|
@@ -978,34 +1025,7 @@ class Agent:
|
|
978
1025
|
role=self.agent_name, content=out
|
979
1026
|
)
|
980
1027
|
|
981
|
-
|
982
|
-
self.short_memory.add(
|
983
|
-
role=self.agent_name, content=response
|
984
|
-
)
|
985
|
-
|
986
|
-
# Add to all responses
|
987
|
-
all_responses.append(response)
|
988
|
-
|
989
|
-
# # TODO: Implement reliability check
|
990
|
-
|
991
|
-
if self.evaluator:
|
992
|
-
logger.info("Evaluating response...")
|
993
|
-
evaluated_response = self.evaluator(
|
994
|
-
response
|
995
|
-
)
|
996
|
-
print(
|
997
|
-
"Evaluated Response:"
|
998
|
-
f" {evaluated_response}"
|
999
|
-
)
|
1000
|
-
self.short_memory.add(
|
1001
|
-
role="Evaluator",
|
1002
|
-
content=evaluated_response,
|
1003
|
-
)
|
1004
|
-
|
1005
|
-
# Sentiment analysis
|
1006
|
-
if self.sentiment_analyzer:
|
1007
|
-
logger.info("Analyzing sentiment...")
|
1008
|
-
self.sentiment_analysis_handler(response)
|
1028
|
+
self.sentiment_and_evaluator(response)
|
1009
1029
|
|
1010
1030
|
success = True # Mark as successful to exit the retry loop
|
1011
1031
|
|
@@ -1062,7 +1082,7 @@ class Agent:
|
|
1062
1082
|
break
|
1063
1083
|
|
1064
1084
|
self.short_memory.add(
|
1065
|
-
role=
|
1085
|
+
role="User", content=user_input
|
1066
1086
|
)
|
1067
1087
|
|
1068
1088
|
if self.loop_interval:
|
@@ -1077,91 +1097,14 @@ class Agent:
|
|
1077
1097
|
if self.autosave is True:
|
1078
1098
|
self.save()
|
1079
1099
|
|
1080
|
-
# Apply the cleaner function to the response
|
1081
|
-
if self.output_cleaner is not None:
|
1082
|
-
logger.info("Applying output cleaner to response.")
|
1083
|
-
response = self.output_cleaner(response)
|
1084
|
-
logger.info(
|
1085
|
-
f"Response after output cleaner: {response}"
|
1086
|
-
)
|
1087
|
-
self.short_memory.add(
|
1088
|
-
role="Output Cleaner",
|
1089
|
-
content=response,
|
1090
|
-
)
|
1091
|
-
|
1092
|
-
if self.agent_ops_on is True and is_last is True:
|
1093
|
-
self.check_end_session_agentops()
|
1094
|
-
|
1095
|
-
# Merge all responses
|
1096
|
-
all_responses = [
|
1097
|
-
response
|
1098
|
-
for response in all_responses
|
1099
|
-
if response is not None
|
1100
|
-
]
|
1101
|
-
|
1102
|
-
self.agent_output.steps = self.short_memory.to_dict()
|
1103
|
-
self.agent_output.full_history = (
|
1104
|
-
self.short_memory.get_str()
|
1105
|
-
)
|
1106
|
-
self.agent_output.total_tokens = count_tokens(
|
1107
|
-
self.short_memory.get_str()
|
1108
|
-
)
|
1109
|
-
|
1110
|
-
# # Handle artifacts
|
1111
|
-
# if self.artifacts_on is True:
|
1112
|
-
# self.handle_artifacts(
|
1113
|
-
# concat_strings(all_responses),
|
1114
|
-
# self.artifacts_output_path,
|
1115
|
-
# self.artifacts_file_extension,
|
1116
|
-
# )
|
1117
|
-
|
1118
1100
|
log_agent_data(self.to_dict())
|
1119
1101
|
|
1120
1102
|
if self.autosave is True:
|
1121
1103
|
self.save()
|
1122
1104
|
|
1123
|
-
|
1124
|
-
|
1125
|
-
|
1126
|
-
or self.output_type == "str"
|
1127
|
-
):
|
1128
|
-
return concat_strings(all_responses)
|
1129
|
-
elif self.output_type == "list":
|
1130
|
-
return all_responses
|
1131
|
-
elif (
|
1132
|
-
self.output_type == "json"
|
1133
|
-
or self.return_step_meta is True
|
1134
|
-
):
|
1135
|
-
return self.agent_output.model_dump_json(indent=4)
|
1136
|
-
elif self.output_type == "csv":
|
1137
|
-
return self.dict_to_csv(
|
1138
|
-
self.agent_output.model_dump()
|
1139
|
-
)
|
1140
|
-
elif self.output_type == "dict":
|
1141
|
-
return self.agent_output.model_dump()
|
1142
|
-
elif self.output_type == "yaml":
|
1143
|
-
return yaml.safe_dump(
|
1144
|
-
self.agent_output.model_dump(), sort_keys=False
|
1145
|
-
)
|
1146
|
-
|
1147
|
-
elif self.output_type == "memory-list":
|
1148
|
-
return self.short_memory.return_messages_as_list()
|
1149
|
-
|
1150
|
-
elif self.output_type == "memory-dict":
|
1151
|
-
return (
|
1152
|
-
self.short_memory.return_messages_as_dictionary()
|
1153
|
-
)
|
1154
|
-
elif self.return_history is True:
|
1155
|
-
history = self.short_memory.get_str()
|
1156
|
-
|
1157
|
-
formatter.print_panel(
|
1158
|
-
history, title=f"{self.agent_name} History"
|
1159
|
-
)
|
1160
|
-
return history
|
1161
|
-
else:
|
1162
|
-
raise ValueError(
|
1163
|
-
f"Invalid output type: {self.output_type}"
|
1164
|
-
)
|
1105
|
+
return history_output_formatter(
|
1106
|
+
self.short_memory, type=self.output_type
|
1107
|
+
)
|
1165
1108
|
|
1166
1109
|
except Exception as error:
|
1167
1110
|
self._handle_run_error(error)
|
@@ -1937,7 +1880,7 @@ class Agent:
|
|
1937
1880
|
"""Send a message to the agent"""
|
1938
1881
|
try:
|
1939
1882
|
logger.info(f"Sending agent message: {message}")
|
1940
|
-
message = f"{agent_name}: {message}"
|
1883
|
+
message = f"To: {agent_name}: {message}"
|
1941
1884
|
return self.run(message, *args, **kwargs)
|
1942
1885
|
except Exception as error:
|
1943
1886
|
logger.info(f"Error sending agent message: {error}")
|
@@ -2014,20 +1957,6 @@ class Agent:
|
|
2014
1957
|
)
|
2015
1958
|
raise error
|
2016
1959
|
|
2017
|
-
def check_end_session_agentops(self):
|
2018
|
-
if self.agent_ops_on is True:
|
2019
|
-
try:
|
2020
|
-
from swarms.utils.agent_ops_check import (
|
2021
|
-
end_session_agentops,
|
2022
|
-
)
|
2023
|
-
|
2024
|
-
# Try ending the session
|
2025
|
-
return end_session_agentops()
|
2026
|
-
except ImportError:
|
2027
|
-
logger.error(
|
2028
|
-
"Could not import agentops, try installing agentops: $ pip3 install agentops"
|
2029
|
-
)
|
2030
|
-
|
2031
1960
|
def memory_query(self, task: str = None, *args, **kwargs) -> None:
|
2032
1961
|
try:
|
2033
1962
|
# Query the long term memory
|
@@ -2154,50 +2083,6 @@ class Agent:
|
|
2154
2083
|
|
2155
2084
|
return out
|
2156
2085
|
|
2157
|
-
def activate_agentops(self):
|
2158
|
-
if self.agent_ops_on is True:
|
2159
|
-
try:
|
2160
|
-
from swarms.utils.agent_ops_check import (
|
2161
|
-
try_import_agentops,
|
2162
|
-
)
|
2163
|
-
|
2164
|
-
# Try importing agent ops
|
2165
|
-
logger.info(
|
2166
|
-
"Agent Ops Initializing, ensure that you have the agentops API key and the pip package installed."
|
2167
|
-
)
|
2168
|
-
try_import_agentops()
|
2169
|
-
self.agent_ops_agent_name = self.agent_name
|
2170
|
-
|
2171
|
-
logger.info("Agentops successfully activated!")
|
2172
|
-
except ImportError:
|
2173
|
-
logger.error(
|
2174
|
-
"Could not import agentops, try installing agentops: $ pip3 install agentops"
|
2175
|
-
)
|
2176
|
-
|
2177
|
-
def llm_output_parser(self, response: Any) -> str:
|
2178
|
-
"""Parse the output from the LLM"""
|
2179
|
-
try:
|
2180
|
-
if isinstance(response, dict):
|
2181
|
-
if "choices" in response:
|
2182
|
-
return response["choices"][0]["message"][
|
2183
|
-
"content"
|
2184
|
-
]
|
2185
|
-
else:
|
2186
|
-
return json.dumps(
|
2187
|
-
response
|
2188
|
-
) # Convert dict to string
|
2189
|
-
elif isinstance(response, str):
|
2190
|
-
return response
|
2191
|
-
else:
|
2192
|
-
return str(
|
2193
|
-
response
|
2194
|
-
) # Convert any other type to string
|
2195
|
-
except Exception as e:
|
2196
|
-
logger.error(f"Error parsing LLM output: {e}")
|
2197
|
-
return str(
|
2198
|
-
response
|
2199
|
-
) # Return string representation as fallback
|
2200
|
-
|
2201
2086
|
def log_step_metadata(
|
2202
2087
|
self, loop: int, task: str, response: str
|
2203
2088
|
) -> Step:
|
@@ -2693,9 +2578,88 @@ class Agent:
|
|
2693
2578
|
"""
|
2694
2579
|
return self.role
|
2695
2580
|
|
2696
|
-
|
2697
|
-
|
2698
|
-
|
2699
|
-
|
2700
|
-
|
2701
|
-
|
2581
|
+
def pretty_print(self, response: str, loop_count: int):
|
2582
|
+
if self.no_print is False:
|
2583
|
+
if self.streaming_on is True:
|
2584
|
+
# self.stream_response(response)
|
2585
|
+
formatter.print_panel_token_by_token(
|
2586
|
+
f"{self.agent_name}: {response}",
|
2587
|
+
title=f"Agent Name: {self.agent_name} [Max Loops: {loop_count}]",
|
2588
|
+
)
|
2589
|
+
else:
|
2590
|
+
# logger.info(f"Response: {response}")
|
2591
|
+
formatter.print_panel(
|
2592
|
+
f"{self.agent_name}: {response}",
|
2593
|
+
f"Agent Name {self.agent_name} [Max Loops: {loop_count} ]",
|
2594
|
+
)
|
2595
|
+
|
2596
|
+
def parse_llm_output(self, response: Any) -> str:
|
2597
|
+
"""Parse and standardize the output from the LLM.
|
2598
|
+
|
2599
|
+
Args:
|
2600
|
+
response (Any): The response from the LLM in any format
|
2601
|
+
|
2602
|
+
Returns:
|
2603
|
+
str: Standardized string output
|
2604
|
+
|
2605
|
+
Raises:
|
2606
|
+
ValueError: If the response format is unexpected and can't be handled
|
2607
|
+
"""
|
2608
|
+
try:
|
2609
|
+
# Handle dictionary responses
|
2610
|
+
if isinstance(response, dict):
|
2611
|
+
if "choices" in response:
|
2612
|
+
return response["choices"][0]["message"][
|
2613
|
+
"content"
|
2614
|
+
]
|
2615
|
+
return json.dumps(
|
2616
|
+
response
|
2617
|
+
) # Convert other dicts to string
|
2618
|
+
|
2619
|
+
# Handle string responses
|
2620
|
+
elif isinstance(response, str):
|
2621
|
+
return response
|
2622
|
+
|
2623
|
+
# Handle list responses (from check_llm_outputs)
|
2624
|
+
elif isinstance(response, list):
|
2625
|
+
return "\n".join(response)
|
2626
|
+
|
2627
|
+
# Handle any other type by converting to string
|
2628
|
+
else:
|
2629
|
+
return str(response)
|
2630
|
+
|
2631
|
+
except Exception as e:
|
2632
|
+
logger.error(f"Error parsing LLM output: {e}")
|
2633
|
+
raise ValueError(
|
2634
|
+
f"Failed to parse LLM output: {type(response)}"
|
2635
|
+
)
|
2636
|
+
|
2637
|
+
def sentiment_and_evaluator(self, response: str):
|
2638
|
+
if self.evaluator:
|
2639
|
+
logger.info("Evaluating response...")
|
2640
|
+
|
2641
|
+
evaluated_response = self.evaluator(response)
|
2642
|
+
print("Evaluated Response:" f" {evaluated_response}")
|
2643
|
+
self.short_memory.add(
|
2644
|
+
role="Evaluator",
|
2645
|
+
content=evaluated_response,
|
2646
|
+
)
|
2647
|
+
|
2648
|
+
# Sentiment analysis
|
2649
|
+
if self.sentiment_analyzer:
|
2650
|
+
logger.info("Analyzing sentiment...")
|
2651
|
+
self.sentiment_analysis_handler(response)
|
2652
|
+
|
2653
|
+
def output_cleaner_op(self, response: str):
|
2654
|
+
# Apply the cleaner function to the response
|
2655
|
+
if self.output_cleaner is not None:
|
2656
|
+
logger.info("Applying output cleaner to response.")
|
2657
|
+
|
2658
|
+
response = self.output_cleaner(response)
|
2659
|
+
|
2660
|
+
logger.info(f"Response after output cleaner: {response}")
|
2661
|
+
|
2662
|
+
self.short_memory.add(
|
2663
|
+
role="Output Cleaner",
|
2664
|
+
content=response,
|
2665
|
+
)
|
swarms/structs/base_swarm.py
CHANGED
@@ -89,7 +89,6 @@ class BaseSwarm(ABC):
|
|
89
89
|
stopping_function: Optional[Callable] = None,
|
90
90
|
stopping_condition: Optional[str] = "stop",
|
91
91
|
stopping_condition_args: Optional[Dict] = None,
|
92
|
-
agentops_on: Optional[bool] = False,
|
93
92
|
speaker_selection_func: Optional[Callable] = None,
|
94
93
|
rules: Optional[str] = None,
|
95
94
|
collective_memory_system: Optional[Any] = False,
|
@@ -112,7 +111,6 @@ class BaseSwarm(ABC):
|
|
112
111
|
self.stopping_function = stopping_function
|
113
112
|
self.stopping_condition = stopping_condition
|
114
113
|
self.stopping_condition_args = stopping_condition_args
|
115
|
-
self.agentops_on = agentops_on
|
116
114
|
self.speaker_selection_func = speaker_selection_func
|
117
115
|
self.rules = rules
|
118
116
|
self.collective_memory_system = collective_memory_system
|
@@ -167,11 +165,6 @@ class BaseSwarm(ABC):
|
|
167
165
|
self.stopping_condition_args = stopping_condition_args
|
168
166
|
self.stopping_condition = stopping_condition
|
169
167
|
|
170
|
-
# If agentops is enabled, try to import agentops
|
171
|
-
if agentops_on is True:
|
172
|
-
for agent in self.agents:
|
173
|
-
agent.agent_ops_on = True
|
174
|
-
|
175
168
|
# Handle speaker selection function
|
176
169
|
if speaker_selection_func is not None:
|
177
170
|
if not callable(speaker_selection_func):
|