|
14 | 14 |
|
15 | 15 | from __future__ import annotations
|
16 | 16 |
|
| 17 | +import logging |
17 | 18 | from typing import Optional
|
| 19 | +from typing import Union |
18 | 20 |
|
19 | 21 | from google.genai import types
|
20 | 22 | from pydantic import BaseModel
|
@@ -86,17 +88,73 @@ class LlmRequest(BaseModel):
|
86 | 88 | cache_metadata: Optional[CacheMetadata] = None
|
87 | 89 | """Cache metadata from previous requests, used for cache management."""
|
88 | 90 |
|
89 |
| - def append_instructions(self, instructions: list[str]) -> None: |
| 91 | + def append_instructions( |
| 92 | + self, instructions: Union[list[str], types.Content] |
| 93 | + ) -> None: |
90 | 94 | """Appends instructions to the system instruction.
|
91 | 95 |
|
92 | 96 | Args:
|
93 |
| - instructions: The instructions to append. |
| 97 | + instructions: The instructions to append. Can be: |
| 98 | + - list[str]: Strings to append/concatenate to system instruction |
| 99 | + - types.Content: Content object to append to system instruction |
| 100 | +
|
| 101 | + Note: Only text content is supported. Model API requires system_instruction |
| 102 | + to be a string. Non-text parts in Content will be handled differently. |
| 103 | +
|
| 104 | + Behavior: |
| 105 | + - list[str]: concatenates with existing system_instruction using \\n\\n |
| 106 | + - types.Content: extracts text from parts and concatenates |
94 | 107 | """
|
95 | 108 |
|
96 |
| - if self.config.system_instruction: |
97 |
| - self.config.system_instruction += '\n\n' + '\n\n'.join(instructions) |
98 |
| - else: |
99 |
| - self.config.system_instruction = '\n\n'.join(instructions) |
| 109 | + # Handle Content object - extract only text parts |
| 110 | + if isinstance(instructions, types.Content): |
| 111 | + # TODO: Handle non-text contents in instruction by putting non-text parts |
| 112 | + # into llm_request.contents and adding a reference in the system instruction |
| 113 | + # that references the contents. |
| 114 | + |
| 115 | + # Extract text from all text parts |
| 116 | + text_parts = [part.text for part in instructions.parts if part.text] |
| 117 | + |
| 118 | + if not text_parts: |
| 119 | + return # No text content to append |
| 120 | + |
| 121 | + new_text = "\n\n".join(text_parts) |
| 122 | + if not self.config.system_instruction: |
| 123 | + self.config.system_instruction = new_text |
| 124 | + elif isinstance(self.config.system_instruction, str): |
| 125 | + self.config.system_instruction += "\n\n" + new_text |
| 126 | + else: |
| 127 | + # Log warning for unsupported system_instruction types |
| 128 | + logging.warning( |
| 129 | + "Cannot append to system_instruction of unsupported type: %s. " |
| 130 | + "Only string system_instruction is supported.", |
| 131 | + type(self.config.system_instruction), |
| 132 | + ) |
| 133 | + return |
| 134 | + |
| 135 | + # Handle list of strings |
| 136 | + if isinstance(instructions, list) and all( |
| 137 | + isinstance(inst, str) for inst in instructions |
| 138 | + ): |
| 139 | + if not instructions: # Handle empty list |
| 140 | + return |
| 141 | + |
| 142 | + new_text = "\n\n".join(instructions) |
| 143 | + if not self.config.system_instruction: |
| 144 | + self.config.system_instruction = new_text |
| 145 | + elif isinstance(self.config.system_instruction, str): |
| 146 | + self.config.system_instruction += "\n\n" + new_text |
| 147 | + else: |
| 148 | + # Log warning for unsupported system_instruction types |
| 149 | + logging.warning( |
| 150 | + "Cannot append to system_instruction of unsupported type: %s. " |
| 151 | + "Only string system_instruction is supported.", |
| 152 | + type(self.config.system_instruction), |
| 153 | + ) |
| 154 | + return |
| 155 | + |
| 156 | + # Invalid input |
| 157 | + raise TypeError("instructions must be list[str] or types.Content") |
100 | 158 |
|
101 | 159 | def append_tools(self, tools: list[BaseTool]) -> None:
|
102 | 160 | """Appends tools to the request.
|
@@ -138,4 +196,4 @@ def set_output_schema(self, base_model: type[BaseModel]) -> None:
|
138 | 196 | """
|
139 | 197 |
|
140 | 198 | self.config.response_schema = base_model
|
141 |
| - self.config.response_mime_type = 'application/json' |
| 199 | + self.config.response_mime_type = "application/json" |
0 commit comments