-
Notifications
You must be signed in to change notification settings - Fork 2
Providing proper step logs #40 #42
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
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -23,16 +23,19 @@ | |
{ | ||
task_done: true | false, | ||
command: "<command to run> | null", | ||
result: str | null | ||
result: str | null, | ||
reasoning: "Brief explanation of what you're thinking and why you're running this command" | ||
} | ||
``` | ||
""" | ||
|
||
system_prompt_common = """There is a shell session open for you. | ||
I will provide a task to achieve using the shell. | ||
You will provide the commands to achieve the task in this particular below json format, Ensure all the time to respond in this format only and nothing else, also all the properties ( task_done, command, result ) are mandatory on each response | ||
You will provide the commands to achieve the task in this particular below json format, Ensure all the time to respond in this format only and nothing else, also all the properties ( task_done, command, result, reasoning ) are mandatory on each response | ||
{llm_output_format} | ||
after each command I will provide the output of the command. | ||
|
||
IMPORTANT: Always include 'reasoning' field to explain your thought process before executing each command. | ||
ensure to run only one command at a time. | ||
I won't be able to intervene once I have given task. .""" | ||
|
||
|
@@ -105,9 +108,28 @@ def run(self, task, max_iterations=20, timeout_in_seconds=200) -> BotRunResult: | |
result=None, | ||
error="Did not complete", | ||
) | ||
logger.info("%s TASK STARTED : %s...", LogLevelEmoji.INFO, task[0:15]) | ||
print(f"\n{'='*80}") | ||
print(f"🚀 TASK STARTED: {task}") | ||
print(f"{'='*80}") | ||
|
||
logger.info("%s TASK STARTED : %s...", LogLevelEmoji.INFO, task[0:50]) | ||
|
||
while llm_response.task_done is False: | ||
print(f"\n{'─'*80}") | ||
print(f"🔄 STEP {iteration_count}") | ||
print(f"{'─'*80}") | ||
|
||
# Show LLM's thought process | ||
print(f"\n💭 LLM ANALYSIS:") | ||
if hasattr(llm_response, 'reasoning') and llm_response.reasoning: | ||
print(f" {llm_response.reasoning}") | ||
else: | ||
print(f" Analyzing current situation and determining next action...") | ||
|
||
# Show the command to execute | ||
print(f"\n⚡ COMMAND TO EXECUTE:") | ||
print(f" {LogTextColor.OKBLUE}{llm_response.command}{LogTextColor.ENDC}") | ||
|
||
logger.info("%s Step-%d %s", "-" * 20, iteration_count, "-" * 20) | ||
logger.info( | ||
f" ➡️ LLM tool call : {LogTextColor.OKBLUE}{json.dumps(llm_response.command)}{LogTextColor.ENDC}", | ||
|
@@ -132,11 +154,27 @@ def run(self, task, max_iterations=20, timeout_in_seconds=200) -> BotRunResult: | |
return return_value | ||
|
||
llm_command_output = self.environment.execute(llm_response.command) | ||
|
||
# Show command output clearly | ||
print(f"\n📤 COMMAND OUTPUT:") | ||
if llm_command_output.stdout: | ||
print(f" ✅ STDOUT:") | ||
for line in llm_command_output.stdout.split('\n'): | ||
if line.strip(): | ||
print(f" {line}") | ||
logger.info( | ||
" ⬅️ Command Execution Output: %s", | ||
llm_command_output.stdout, | ||
) | ||
|
||
if llm_command_output.stderr: | ||
print(f" ❌ STDERR:") | ||
for line in llm_command_output.stderr.split('\n'): | ||
if line.strip(): | ||
print(f" {line}") | ||
|
||
if not llm_command_output.stdout and not llm_command_output.stderr: | ||
print(f" ℹ️ No output received") | ||
|
||
# Convert CmdReturn to string for LLM | ||
if llm_command_output.stdout: | ||
|
@@ -146,9 +184,22 @@ def run(self, task, max_iterations=20, timeout_in_seconds=200) -> BotRunResult: | |
else: | ||
output_text = "No output received" | ||
|
||
print(f"\n🔄 SENDING OUTPUT TO LLM...") | ||
llm_response = self.llm.ask(output_text) | ||
|
||
logger.info("🔚 TASK COMPLETED : %s...", task[0:15]) | ||
print(f"\n{'='*80}") | ||
print(f"✅ TASK COMPLETED!") | ||
print(f"{'='*80}") | ||
print(f"\n🎯 FINAL RESULT:") | ||
if llm_response.result: | ||
for line in str(llm_response.result).split('\n'): | ||
if line.strip(): | ||
print(f" {line}") | ||
else: | ||
print(" Task completed successfully") | ||
print(f"\n{'='*80}") | ||
|
||
logger.info("🔚 TASK COMPLETED : %s...", task[0:50]) | ||
return BotRunResult(status=True, result=llm_response.result, error=None) | ||
|
||
# TODO : pass the sandbox path | ||
|
@@ -167,7 +218,7 @@ def _create_environment(self, folder_to_mount: Optional[Mount]): | |
) | ||
|
||
def _create_llm(self): | ||
if self.model_provider == ModelProvider.OPENAI: | ||
if self.model_provider in [ModelProvider.OPENAI, ModelProvider.OPENAI_STANDARD]: | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more.
|
||
self.llm = OpenAIApi( | ||
system_prompt=self.system_prompt, deployment_name=self.deployment_name | ||
) | ||
|
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -24,6 +24,7 @@ class llmAskResponse: | |
task_done: bool = False | ||
command: str = "" | ||
result: str | None = None | ||
reasoning: str | None = None | ||
|
||
|
||
class OpenAIApi: | ||
|
@@ -38,12 +39,12 @@ def ask(self, message) -> llmAskResponse: | |
self.messages.append({"role": "user", "content": message}) | ||
return_value = {} | ||
while self._validate_llm_response(return_value) is False: | ||
response = self.ai_client.responses.create( | ||
response = self.ai_client.chat.completions.create( | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Our intention to use If you still wish to stick with We'll have provision to include appropriate API class in |
||
model=self.deployment_name, | ||
input=self.messages, | ||
messages=self.messages, | ||
) | ||
try: | ||
return_value = json.loads(response.output_text) | ||
return_value = json.loads(response.choices[0].message.content) | ||
except Exception as e: | ||
logger.error( | ||
f"%s Error occurred while dumping JSON: {e}", LogLevelEmoji.ERROR | ||
|
@@ -52,14 +53,15 @@ def ask(self, message) -> llmAskResponse: | |
"%s Failed to parse JSON from LLM response and the response is", | ||
LogLevelEmoji.ERROR, | ||
) | ||
logger.error(response.output_text) | ||
logger.error(response.choices[0].message.content) | ||
|
||
self.messages.append({"role": "assistant", "content": json.dumps(return_value)}) | ||
|
||
return llmAskResponse( | ||
task_done=return_value["task_done"], | ||
result=return_value["result"], | ||
command=return_value["command"], | ||
reasoning=return_value.get("reasoning", "No reasoning provided"), | ||
) | ||
|
||
def clear_history(self): | ||
|
@@ -72,7 +74,8 @@ def clear_history(self): | |
return True | ||
|
||
def _validate_llm_response(self, response: dict) -> bool: | ||
if "task_done" in response and "command" in response and "result" in response: | ||
required_fields = ["task_done", "command", "result"] | ||
if all(field in response for field in required_fields): | ||
logger.info("The llm response is %s ", response) | ||
return True | ||
return False |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Let's convert all
print
statements intoINFO
log statements. To avoid being unresponsive in the console while running, add aWARNING
log to mentionLog Level is above INFO. So, no output will be printed here during normal operation. Please wait patiently
.It gives us better control over the output and log stream. Particularly useful to run in quiet mode.