Chat Agent interacting with external env (could be human, or external tools). The agent (the LLM actually) is provided with an optional "Task Spec", which is a sequence of `LLMMessage`s. These are used to initialize the `task_messages` of the agent. In most applications we w
| 165 | |
| 166 | |
| 167 | class ChatAgent(Agent): |
| 168 | """ |
| 169 | Chat Agent interacting with external env |
| 170 | (could be human, or external tools). |
| 171 | The agent (the LLM actually) is provided with an optional "Task Spec", |
| 172 | which is a sequence of `LLMMessage`s. These are used to initialize |
| 173 | the `task_messages` of the agent. |
| 174 | In most applications we will use a `ChatAgent` rather than a bare `Agent`. |
| 175 | The `Agent` class mainly exists to hold various common methods and attributes. |
| 176 | One difference between `ChatAgent` and `Agent` is that `ChatAgent`'s |
| 177 | `llm_response` method uses "chat mode" API (i.e. one that takes a |
| 178 | message sequence rather than a single message), |
| 179 | whereas the same method in the `Agent` class uses "completion mode" API (i.e. one |
| 180 | that takes a single message). |
| 181 | """ |
| 182 | |
| 183 | def __init__( |
| 184 | self, |
| 185 | config: ChatAgentConfig = ChatAgentConfig(), |
| 186 | task: Optional[List[LLMMessage]] = None, |
| 187 | ): |
| 188 | """ |
| 189 | Chat-mode agent initialized with task spec as the initial message sequence |
| 190 | Args: |
| 191 | config: settings for the agent |
| 192 | |
| 193 | """ |
| 194 | super().__init__(config) |
| 195 | self.config: ChatAgentConfig = config |
| 196 | self.config._set_fn_or_tools() |
| 197 | self.message_history: List[LLMMessage] = [] |
| 198 | self.init_state() |
| 199 | # An agent's "task" is defined by a system msg and an optional user msg; |
| 200 | # These are "priming" messages that kick off the agent's conversation. |
| 201 | self.system_message: str = self.config.system_message |
| 202 | self.user_message: str | None = self.config.user_message |
| 203 | |
| 204 | if task is not None: |
| 205 | # if task contains a system msg, we override the config system msg |
| 206 | if len(task) > 0 and task[0].role == Role.SYSTEM: |
| 207 | self.system_message = task[0].content |
| 208 | # if task contains a user msg, we override the config user msg |
| 209 | if len(task) > 1 and task[1].role == Role.USER: |
| 210 | self.user_message = task[1].content |
| 211 | |
| 212 | # system-level instructions for using tools/functions: |
| 213 | # We maintain these as tools/functions are enabled/disabled, |
| 214 | # and whenever an LLM response is sought, these are used to |
| 215 | # recreate the system message (via `_create_system_and_tools_message`) |
| 216 | # each time, so it reflects the current set of enabled tools/functions. |
| 217 | # (a) these are general instructions on using certain tools/functions, |
| 218 | # if they are specified in a ToolMessage class as a classmethod `instructions` |
| 219 | self.system_tool_instructions: str = "" |
| 220 | # (b) these are only for the builtin in Langroid TOOLS mechanism: |
| 221 | self.system_tool_format_instructions: str = "" |
| 222 | |
| 223 | self.llm_functions_map: Dict[str, LLMFunctionSpec] = {} |
| 224 | self.llm_functions_handled: Set[str] = set() |
no outgoing calls
searching dependent graphs…