Skip to content

Commit d76c656

Browse files
authored
Release v0.0.2: ClaudeAgent, Genesis Docker, Logging, and Direct Movement Velocity Support Updates
# Release v0.0.2: ClaudeAgent, Genesis Docker, Logging, and Direct Movement Velocity Support Updates ### Version Updates - pyproject.toml: 0.0.1 -> 0.0.2 ### ClaudeAgent - Implemented Claude Agent with input query streaming and system query support. Image support WIP. - Added skills/tool calling capabilities with thinking model integration - Introduced `run_observable_query()` helper method in base LLMAgent - Enhanced web interface integration for input queries - Improved handling of Pydantic generic classes in observable query - Streamlined text streaming for Agents using FastAPIServer - Fixed system query handling and initialization ### Robot Control & Skills Framework - Re-implemented direct movement velocity controls in ROSControl - Added new Robot skill for `move_vel()` functionality ### Logging & Infrastructure - Standardized logging system with `DIMOS_LOG_LEVEL` environment variable - Fixed debug message handling and logger configuration - Cleaned up terminal output and removed redundant logging - Added standardized test file headers ### Docker & Simulation - Added support for Genesis simulator alongside Isaac - Created separate folders for simulation docker files - Updated Docker configurations for both simulators - Changed web server interface address from localhost to 0.0.0.0 Former-commit-id: fc601ac
2 parents 46c07b8 + 19d4753 commit d76c656

62 files changed

Lines changed: 1551 additions & 324 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

default.env

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
OPENAI_API_KEY=
2+
ANTHROPIC_API_KEY=
23
ROBOT_IP=
34
CONN_TYPE=webrtc
45
WEBRTC_SERVER_HOST=0.0.0.0

dimos/agents/agent.py

Lines changed: 42 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -58,7 +58,7 @@
5858
load_dotenv()
5959

6060
# Initialize logger for the agent module
61-
logger = setup_logger("dimos.agents", level=logging.DEBUG)
61+
logger = setup_logger("dimos.agents")
6262

6363
# Constants
6464
_TOKEN_BUDGET_PARTS = 4 # Number of parts to divide token budget
@@ -91,15 +91,13 @@ def __init__(self,
9191
self.agent_memory = agent_memory or AgentSemanticMemory()
9292
self.disposables = CompositeDisposable()
9393
self.pool_scheduler = pool_scheduler if pool_scheduler else get_scheduler()
94-
self.logger = setup_logger(
95-
f"dimos.agents.{self.agent_type}.{self.dev_name}")
9694

9795
def dispose_all(self):
9896
"""Disposes of all active subscriptions managed by this agent."""
9997
if self.disposables:
10098
self.disposables.dispose()
10199
else:
102-
self.logger.info("No disposables to dispose.")
100+
logger.info("No disposables to dispose.")
103101

104102

105103
# endregion Agent Base Class
@@ -207,8 +205,8 @@ def _get_rag_context(self) -> Tuple[str, str]:
207205
for (doc, score) in results)
208206
condensed_results = " | ".join(
209207
f"{doc.page_content}" for (doc, _) in results)
210-
self.logger.info(f"Agent Memory Query Results:\n{formatted_results}")
211-
self.logger.info("=== Results End ===")
208+
logger.info(f"Agent Memory Query Results:\n{formatted_results}")
209+
logger.info("=== Results End ===")
212210
return formatted_results, condensed_results
213211

214212
def _build_prompt(self, base64_image: Optional[str],
@@ -284,21 +282,21 @@ def _tooling_callback(message, messages, response_message,
284282
name = tool_call.function.name
285283
args = json.loads(tool_call.function.arguments)
286284
result = skills.call_function(name, **args)
287-
self.logger.info(f"Function Call Results: {result}")
285+
logger.info(f"Function Call Results: {result}")
288286
new_messages.append({
289287
"role": "tool",
290288
"tool_call_id": tool_call.id,
291289
"content": str(result),
292290
"name": name
293291
})
294292
if has_called_tools:
295-
self.logger.info("Sending Another Query.")
293+
logger.info("Sending Another Query.")
296294
messages.append(response_message)
297295
messages.extend(new_messages)
298296
# Delegate to sending the query again.
299297
return self._send_query(messages)
300298
else:
301-
self.logger.info("No Need for Another Query.")
299+
logger.info("No Need for Another Query.")
302300
return None
303301

304302
if response_message.tool_calls is not None:
@@ -330,10 +328,10 @@ def _observable_query(self,
330328
messages = self._build_prompt(base64_image, dimensions,
331329
override_token_limit,
332330
condensed_results)
333-
# self.logger.debug(f"Sending Query: {messages}")
334-
self.logger.info("Sending Query.")
331+
# logger.debug(f"Sending Query: {messages}")
332+
logger.info("Sending Query.")
335333
response_message = self._send_query(messages)
336-
self.logger.info(f"Received Response: {response_message}")
334+
logger.info(f"Received Response: {response_message}")
337335
if response_message is None:
338336
raise Exception("Response message does not exist.")
339337

@@ -358,7 +356,7 @@ def _observable_query(self,
358356
self.response_subject.on_next(final_msg)
359357
observer.on_completed()
360358
except Exception as e:
361-
self.logger.error(f"Query failed in {self.dev_name}: {e}")
359+
logger.error(f"Query failed in {self.dev_name}: {e}")
362360
observer.on_error(e)
363361
self.response_subject.on_error(e)
364362

@@ -393,7 +391,7 @@ def _log_response_to_file(self, response, output_dir: str = None):
393391
log_path = os.path.join(output_dir, 'memory.txt')
394392
with open(log_path, 'a') as file:
395393
file.write(f"{self.dev_name}: {response}\n")
396-
self.logger.info(f"LLM Response [{self.dev_name}]: {response}")
394+
logger.info(f"LLM Response [{self.dev_name}]: {response}")
397395

398396
def subscribe_to_image_processing(
399397
self, frame_observable: Observable) -> Disposable:
@@ -487,8 +485,8 @@ def process_if_free(frame):
487485
disposable = observable.subscribe(
488486
on_next=lambda response: self._log_response_to_file(
489487
response, self.output_dir),
490-
on_error=lambda e: self.logger.error(f"Error encountered: {e}"),
491-
on_completed=lambda: self.logger.info(
488+
on_error=lambda e: logger.error(f"Error encountered: {e}"),
489+
on_completed=lambda: logger.info(
492490
f"Stream processing completed for {self.dev_name}"))
493491
self.disposables.add(disposable)
494492
return disposable
@@ -529,13 +527,13 @@ def _process_query(query) -> Observable:
529527
is_processing = [False]
530528

531529
def process_if_free(query):
532-
self.logger.info(f"Processing Query: {query}")
530+
logger.info(f"Processing Query: {query}")
533531
if not self.process_all_inputs and is_processing[0]:
534532
# Drop query if a request is already in progress and process_all_inputs is False
535533
return empty()
536534
else:
537535
is_processing[0] = True
538-
self.logger.info("Processing Query.")
536+
logger.info("Processing Query.")
539537
return _process_query(query).pipe(
540538
MyOps.print_emission(id='B', **print_emission_args),
541539
RxOps.observe_on(self.pool_scheduler),
@@ -557,9 +555,9 @@ def process_if_free(query):
557555
disposable = observable.subscribe(
558556
on_next=lambda response: self._log_response_to_file(
559557
response, self.output_dir),
560-
on_error=lambda e: self.logger.error(
558+
on_error=lambda e: logger.error(
561559
f"Error processing query for {self.dev_name}: {e}"),
562-
on_completed=lambda: self.logger.info(
560+
on_completed=lambda: logger.info(
563561
f"Stream processing completed for {self.dev_name}"))
564562
self.disposables.add(disposable)
565563
return disposable
@@ -575,6 +573,22 @@ def get_response_observable(self) -> Observable:
575573
RxOps.subscribe_on(self.pool_scheduler),
576574
RxOps.share())
577575

576+
def run_observable_query(self, query_text: str) -> Observable:
577+
"""Creates an observable that processes a one-off text query to Agent and emits the response.
578+
579+
This method provides a simple way to send a text query and get an observable
580+
stream of the response. It's designed for one-off queries rather than
581+
continuous processing of input streams. Useful for testing and development.
582+
583+
Args:
584+
query_text (str): The query text to process.
585+
586+
Returns:
587+
Observable: An observable that emits the response as a string.
588+
"""
589+
return create(lambda observer, _: self._observable_query(
590+
observer, incoming_query=query_text))
591+
578592
def dispose_all(self):
579593
"""Disposes of all active subscriptions managed by this agent."""
580594
super().dispose_all()
@@ -697,15 +711,15 @@ def __init__(self,
697711
)
698712

699713
if self.input_video_stream is not None:
700-
self.logger.info("Subscribing to input video stream...")
714+
logger.info("Subscribing to input video stream...")
701715
self.disposables.add(
702716
self.subscribe_to_image_processing(self.input_video_stream))
703717
if self.input_query_stream is not None:
704-
self.logger.info("Subscribing to input query stream...")
718+
logger.info("Subscribing to input query stream...")
705719
self.disposables.add(
706720
self.subscribe_to_query_processing(self.input_query_stream))
707721

708-
self.logger.info("OpenAI Agent Initialized.")
722+
logger.info("OpenAI Agent Initialized.")
709723

710724
def _add_context_to_memory(self):
711725
"""Adds initial context to the agent's memory."""
@@ -765,17 +779,17 @@ def _send_query(self, messages: list) -> Any:
765779

766780
response_message = response.choices[0].message
767781
if response_message is None:
768-
self.logger.error("Response message does not exist.")
782+
logger.error("Response message does not exist.")
769783
raise Exception("Response message does not exist.")
770784
return response_message
771785
except ConnectionError as ce:
772-
self.logger.error(f"Connection error with API: {ce}")
786+
logger.error(f"Connection error with API: {ce}")
773787
raise
774788
except ValueError as ve:
775-
self.logger.error(f"Invalid parameters: {ve}")
789+
logger.error(f"Invalid parameters: {ve}")
776790
raise
777791
except Exception as e:
778-
self.logger.error(f"Unexpected error in API call: {e}")
792+
logger.error(f"Unexpected error in API call: {e}")
779793
raise
780794

781795
def stream_query(self, query_text: str) -> Observable:
@@ -795,4 +809,4 @@ def stream_query(self, query_text: str) -> Observable:
795809
observer, incoming_query=query_text))
796810

797811

798-
# endregion OpenAIAgent Subclass (OpenAI-Specific Implementation)
812+
# endregion OpenAIAgent Subclass (OpenAI-Specific Implementation)

0 commit comments

Comments
 (0)