Source code for bio_reasoning.coordinator

from dataclasses import asdict, dataclass
from typing import Any, Dict, List, Optional, Sequence

from cicada.core import MultiModalModel, PromptBuilder
from loguru import logger
from openai.types.chat.chat_completion_message import ChatCompletionMessage

from .reasoning.example_reasoning import ExampleReasoningMode, ReasoningMode
from .reasoning.prompts import create_reasoning_mode_from_prompt, REASONING_PROMPTS

import json


[docs] @dataclass class Configuration: api_key: str api_base_url: str model_name: str stream: bool = True
[docs] def to_dict(self) -> Dict[str, Any]: dict_repr = asdict(self) return dict_repr
def __str__(self) -> str: """ This is a hack to make the Configuration object printable. """ return str(self.to_dict()) def __repr__(self) -> str: """ This is a hack to make the Configuration object printable. """ return self.__str__() # what's the method to override for **config unpacking? def __getitem__(self, key: str) -> Any: """ This is a hack to make the Configuration object unpackable. For example, we can use **config to unpack the Configuration object. """ return getattr(self, key)
[docs] class Coordinator: """ This is the orchestrator of layers. """
[docs] def __init__( self, *, config: Configuration, system_prompt: str = "You are a helpful assistant.", ) -> None: logger.debug(config) self._core = MultiModalModel(**config.to_dict()) self._reasoning_mode: Optional[ReasoningMode] = None self._reasoning_modes: List[ReasoningMode] = [] self.system_prompt = system_prompt
# TODO: we may need a method called determine_reasoning_mode. It could be simply a llm query to score the query against definition of each reasoning mode, then select the one with the highest score. But we need a collection of reasoning modes to test and develop this method. @property def reasoning_mode(self) -> ReasoningMode: if self._reasoning_mode is None: raise ValueError("Reasoning mode is not set.") return self._reasoning_mode @reasoning_mode.setter def reasoning_mode(self, reasoning_mode: ReasoningMode) -> None: """ Set the reasoning mode for the coordinator. This will update the system prompt and the tools available to the coordinator. """ self._reasoning_mode = reasoning_mode self._reasoning_modes = [reasoning_mode] if reasoning_mode else []
[docs] def construct_system_prompt(self, messages=None, user_question_override=None) -> str: """Construct system prompt combining default and reasoning mode prompts, filling in [USER_QUESTION].""" combined_prompt = self.system_prompt + "\n\n" # Extract user question from messages or use override user_question = "" if user_question_override: user_question = user_question_override elif messages: # Find the first user message for m in messages: if m.get("role") == "user": user_question = m.get("content", "") break # Add comprehensive introduction about reasoning composition if self._reasoning_modes: reasoning_names = [mode.name for mode in self._reasoning_modes] combined_prompt += f"You are a composition of many forms of reasoning. These include {', '.join(reasoning_names)}.\n\n" # Add each reasoning mode with its full description combined_prompt += "Each reasoning form provides specialized expertise:\n\n" for mode in self._reasoning_modes: # Extract the reasoning type from the mode name (e.g., "Spatial Reasoning Expert" -> "spatial") reasoning_type = mode.name.lower().replace(" reasoning expert", "") # Fill in [USER_QUESTION] in the sys_prompt sys_prompt_filled = mode.sys_prompt.replace("[USER_QUESTION]", user_question) combined_prompt += f'"{reasoning_type}": """{sys_prompt_filled}"""\n\n' return combined_prompt
[docs] def query( self, messages: Sequence[ChatCompletionMessage | dict[str, str]], stream: bool = False, user_question_override: str = None, ) -> str: # prepend system prompt to messages. system_content = self.construct_system_prompt(messages, user_question_override) messages = [ { "role": "system", "content": system_content, } ] + list(messages) for i, message in enumerate(messages): logger.debug(f"Message {i}: {message}") response = self._core.query( messages=messages, tools=self._get_combined_tools(), stream=stream, ) return response["content"]
def _get_combined_tools(self): """Get combined tools from all reasoning modes.""" if not self._reasoning_modes: return None # For now, use the first reasoning mode's tools (backward compatibility) # TODO: Implement proper tool merging from multiple reasoning modes return self._reasoning_modes[0].layers if self._reasoning_modes else None
[docs] def add_reasoning_mode(self, reasoning_mode: ReasoningMode) -> None: """Add a reasoning mode to the active set.""" self._reasoning_modes.append(reasoning_mode) # Update single reasoning mode for backward compatibility if not self._reasoning_mode: self._reasoning_mode = reasoning_mode
[docs] def set_reasoning_modes(self, reasoning_modes: List[ReasoningMode]) -> None: """Set the complete set of reasoning modes.""" self._reasoning_modes = reasoning_modes # Update single reasoning mode for backward compatibility self._reasoning_mode = reasoning_modes[0] if reasoning_modes else None
if __name__ == "__main__": import os import sys from dotenv import load_dotenv load_dotenv() # Load environment variables from .env file config = Configuration( api_key=os.getenv("API_KEY", "sk-xxxxxxxxx"), api_base_url=os.getenv("BASE_URL", "https://api.openai.com/v1"), model_name=os.getenv("MODEL_NAME", "gpt-4.1"), ) coordinator = Coordinator( config=config, system_prompt=( "You are a coordinator of a team of experts and tools. " " You are provided with a collections of tools. Tools are labeled with a prefix from layer_a, layer_b, or layer_c. " "Layer A is the parametric memory of a general large language model (LLM), capturing broadly applicable knowledge pre-trained or fine-tuned into its weights. Layer B consists of bespoke foundation models specialized for non-textual or multimodal data (e.g. genomic sequences, protein structures, images) that interface with the LLM. Layer C encompasses external knowledge sources - APIs, databases, and knowledge graphs - to provide access to large, dynamic, or regulated datasets that cannot reside fully within models. " # "You may be provided with URLs to images, use the tools to analyze them. " "You are given a question and you need to answer it by commanding the tools available to you." ), ) # Check for command line arguments for reasoning modes user_question_override = None if len(sys.argv) > 1: if sys.argv[1] == "--reasoning-modes": # Parse reasoning modes from command line if len(sys.argv) > 2: mode_names_raw = sys.argv[2] logger.debug(f"Raw mode names argument: '{mode_names_raw}'") mode_names = [name.strip() for name in mode_names_raw.split(",")] logger.info(f"Using reasoning modes: {mode_names}") # Create reasoning modes from prompts.py reasoning_modes = [] for mode_name in mode_names: try: mode = create_reasoning_mode_from_prompt(mode_name) reasoning_modes.append(mode) except ValueError as e: logger.warning(f"Skipping unknown reasoning mode '{mode_name}': {e}") coordinator.set_reasoning_modes(reasoning_modes) else: # Default to all reasoning modes from prompts.py logger.info("Using all available reasoning modes from prompts.py") reasoning_modes = [] for mode_name in REASONING_PROMPTS.keys(): mode = create_reasoning_mode_from_prompt(mode_name) reasoning_modes.append(mode) coordinator.set_reasoning_modes(reasoning_modes) elif sys.argv[1] == "--user-question": # Parse user question from command line if len(sys.argv) > 2: user_question_override = sys.argv[2] logger.info(f"Using user question override: '{user_question_override}'") else: logger.warning("--user-question specified but no question provided") else: # Default behavior - use all reasoning modes from prompts.py logger.info("Using all available reasoning modes from prompts.py") reasoning_modes = [] for mode_name in REASONING_PROMPTS.keys(): mode = create_reasoning_mode_from_prompt(mode_name) reasoning_modes.append(mode) coordinator.set_reasoning_modes(reasoning_modes) pb = PromptBuilder() pb.add_user_message("what tools do you have access to?") pb.add_user_message( "What is this image about? https://epi-rsc.rsc-cdn.org/globalassets/05-journals-books-databases/our-journals/00-journal-pages-heros/Chemical-biology-HERO.jpg" ) pb.add_user_message( "if any tool fails, report back to me with the error message and the tool name." ) for message in pb.messages: logger.debug(json.dumps(message, indent=4)) # Show the constructed system prompt without making the API call system_prompt = coordinator.construct_system_prompt(pb.messages, user_question_override) logger.info("=== CONSTRUCTED SYSTEM PROMPT ===") logger.info(system_prompt) logger.info("=== END SYSTEM PROMPT ===") #coordinator.query(pb.messages, stream=True)