|
101 | 101 | ], |
102 | 102 | "source": [ |
103 | 103 | "from pyrit.models import Message, MessagePiece\n", |
104 | | - "from pyrit.prompt_target.openai.openai_response_target import OpenAIResponseTarget\n", |
105 | 104 | "from pyrit.setup import IN_MEMORY, initialize_pyrit\n", |
106 | 105 | "\n", |
107 | 106 | "initialize_pyrit(memory_db_type=IN_MEMORY)\n", |
|
135 | 134 | "\n", |
136 | 135 | "# Let the model auto-select tools\n", |
137 | 136 | "target = OpenAIResponseTarget(\n", |
138 | | - " model_name=\"o4-mini\",\n", |
139 | 137 | " custom_functions={\"get_current_weather\": get_current_weather},\n", |
140 | 138 | " extra_body_parameters={\n", |
141 | 139 | " \"tools\": [function_tool],\n", |
|
187 | 185 | "name": "stdout", |
188 | 186 | "output_type": "stream", |
189 | 187 | "text": [ |
190 | | - "1 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb4db6148194b034c920a816a3ad\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"October 23 2025 positive news story\"}}\n", |
191 | | - "3 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb4f44988194afba2fcd2ba16277\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"good news story October 23 2025 USA\"}}\n", |
192 | | - "5 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb50ace481949a24558e23723e9a\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Good News Network October 23 2025\"}}\n", |
193 | | - "7 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb5291488194893ff4ba621d13b9\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"open_page\"}}\n", |
194 | | - "9 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb540ed88194b03acd6052d7130c\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Woman Rescues Cat Survived in Derelict Bathroom for Two Years Rescuing starts with noticing Good News Network\"}}\n", |
195 | | - "11 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb57c0dc819491322103b1333154\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"open_page\",\"url\":\"https://www.goodnewsnetwork.org/fortress-unearthed-in-egypt-features-thick-curving-walls-built-3500-years-ago/\"}}\n", |
196 | | - "13 | assistant: {\"id\":\"ws_084e1fa6b70d4c190068fabb5921608194b363cf710edd6163\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"open_page\",\"url\":\"https://www.goodnewsnetwork.org/virus-that-kills-more-elephants-than-any-other-cause-is-finally-defeated/\"}}\n", |
197 | | - "15 | assistant: One uplifting story today comes from the Good News Network: veterinary researchers have, for the first time, developed and successfully trialed a vaccine against elephant endotheliotropic herpesvirus (EEHV)—the leading cause of death for young elephants both in the wild and in human care. Early trials showed the two-dose vaccine triggers a strong immune response with no harmful side effects, marking a “landmark moment” in efforts to protect these iconic animals from a previously untreatable disease ([goodnewsnetwork.org](https://www.goodnewsnetwork.org/virus-that-kills-more-elephants-than-any-other-cause-is-finally-defeated/)).\n" |
| 188 | + "1 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c09cd10819d9094acc94db1e9b8\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"October 28 2025 positive news story\"}}\n", |
| 189 | + "3 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c0c6018819d8748260711df9d07\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"site:reuters.com October 28 2025 positive news Reuters\"}}\n", |
| 190 | + "5 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c0eb990819d9badc437da40d3d4\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Oct 28 2025 Reuters conservation positive Oct 28\"}}\n", |
| 191 | + "7 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c12830c819d9af29ce9359bb845\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"October 28 2025 'good news' site:goodnewsnetwork.org\"}}\n", |
| 192 | + "9 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c156f24819d84a01c0a9434429c\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Oct 28 2025 Greenpeace positive story Reuters Oct 28\"}}\n", |
| 193 | + "11 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c18abd0819d8812b7df936429ab\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Reuters Oct 28 2025 scientists discover\"}}\n", |
| 194 | + "13 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c1c0a20819d8dfae61d9a38e390\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"AP News October 28 2025 good news\"}}\n", |
| 195 | + "15 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c1f720c819da2b09372d48d1386\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Oct 28 2025 Reuters child mortality decline UN Oct 28 2025\"}}\n", |
| 196 | + "17 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c22eadc819dbe71f68926b4635a\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Oct 28 2025 CNN good news story\"}}\n", |
| 197 | + "19 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c26c934819d90506cad3f9d1352\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"open_page\",\"url\":\"https://www.reuters.com/business/energy/us-department-energy-forms-1-billion-supercomputer-ai-partnership-with-amd-2025-10-27/\"}}\n", |
| 198 | + "21 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c2a2bc0819d900dc446636516ef\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"open_page\"}}\n", |
| 199 | + "23 | assistant: {\"id\":\"ws_0f4da57d2d3f46590069004c2b97ac819d929413078f891848\",\"type\":\"web_search_call\",\"status\":\"completed\",\"action\":{\"type\":\"search\",\"query\":\"Oct 28 (Reuters) Positive scientists discover\"}}\n", |
| 200 | + "25 | assistant: One positive story from today: the U.S. Department of Energy announced a $1 billion partnership with AMD to build two next-generation supercomputers—named “Lux” and “Discovery”—that will “supercharge” research into fusion energy, national security and even molecular-level cancer drug discovery ([reuters.com](https://www.reuters.com/business/energy/us-department-energy-forms-1-billion-supercomputer-ai-partnership-with-amd-2025-10-27/)).\n" |
198 | 201 | ] |
199 | 202 | } |
200 | 203 | ], |
|
208 | 211 | "\n", |
209 | 212 | "initialize_pyrit(memory_db_type=IN_MEMORY)\n", |
210 | 213 | "\n", |
| 214 | + "# Note: web search is not yet supported by Azure OpenAI endpoints so we'll use OpenAI from here on.\n", |
211 | 215 | "target = OpenAIResponseTarget(\n", |
212 | 216 | " endpoint=os.getenv(\"PLATFORM_OPENAI_RESPONSES_ENDPOINT\"),\n", |
213 | 217 | " api_key=os.getenv(\"PLATFORM_OPENAI_RESPONSES_KEY\"),\n", |
214 | | - " model_name=os.getenv(\"PLATFORM_OPENAI_RESPONSES_MODEL\", \"gpt-4o-mini\"),\n", |
| 218 | + " model_name=os.getenv(\"PLATFORM_OPENAI_RESPONSES_MODEL\"),\n", |
215 | 219 | " api_version=None,\n", |
216 | 220 | " extra_body_parameters={\n", |
217 | 221 | " \"tools\": [web_search_tool()],\n", |
|
228 | 232 | "response = await target.send_prompt_async(prompt_request=prompt_request) # type: ignore\n", |
229 | 233 | "\n", |
230 | 234 | "for idx, piece in enumerate(response.message_pieces):\n", |
231 | | - " # Reasoning traces are necessary to be sent back to the endpoint for function calling even if they're empty.\n", |
232 | | - " # They are excluded here for a cleaner output.\n", |
233 | 235 | " if piece.original_value_data_type != \"reasoning\":\n", |
234 | 236 | " print(f\"{idx} | {piece.role}: {piece.original_value}\")" |
235 | 237 | ] |
| 238 | + }, |
| 239 | + { |
| 240 | + "cell_type": "markdown", |
| 241 | + "id": "6", |
| 242 | + "metadata": {}, |
| 243 | + "source": [ |
| 244 | + "## Grammar-Constrained Generation\n", |
| 245 | + "\n", |
| 246 | + "OpenAI models also support constrained generation in the [Responses API](https://platform.openai.com/docs/guides/function-calling#context-free-grammars). This forces the LLM to produce output which conforms to the given grammar, which is useful when specific syntax is required in the output.\n", |
| 247 | + "\n", |
| 248 | + "In this example, we will define a simple Lark grammar which prevents the model from giving a correct answer to a simple question, and compare that to the unconstrained model.\n", |
| 249 | + "\n", |
| 250 | + "Note that as of October 2025, this is only supported by OpenAI (not Azure) on \"gpt-5\"" |
| 251 | + ] |
| 252 | + }, |
| 253 | + { |
| 254 | + "cell_type": "code", |
| 255 | + "execution_count": null, |
| 256 | + "id": "7", |
| 257 | + "metadata": {}, |
| 258 | + "outputs": [ |
| 259 | + { |
| 260 | + "name": "stdout", |
| 261 | + "output_type": "stream", |
| 262 | + "text": [ |
| 263 | + "Unconstrained Response:\n", |
| 264 | + "1 | assistant: Rome.\n", |
| 265 | + "\n", |
| 266 | + "Constrained Response:\n", |
| 267 | + "1 | assistant: I think that it is cat\n" |
| 268 | + ] |
| 269 | + } |
| 270 | + ], |
| 271 | + "source": [ |
| 272 | + "from pyrit.setup import IN_MEMORY, initialize_pyrit\n", |
| 273 | + "\n", |
| 274 | + "initialize_pyrit(memory_db_type=IN_MEMORY)\n", |
| 275 | + "\n", |
| 276 | + "\n", |
| 277 | + "message_piece = MessagePiece(\n", |
| 278 | + " role=\"user\",\n", |
| 279 | + " original_value=\"What is the capital of Italy?\",\n", |
| 280 | + " original_value_data_type=\"text\",\n", |
| 281 | + ")\n", |
| 282 | + "prompt_request = Message(message_pieces=[message_piece])\n", |
| 283 | + "\n", |
| 284 | + "# Define a grammar that prevents \"Rome\" from being generated\n", |
| 285 | + "lark_grammar = r\"\"\"\n", |
| 286 | + "start: \"I think that it is \" SHORTTEXT \n", |
| 287 | + "SHORTTEXT: /[^RrOoMmEe]{1,8}/\n", |
| 288 | + "\"\"\"\n", |
| 289 | + "\n", |
| 290 | + "grammar_tool = {\n", |
| 291 | + " \"type\": \"custom\",\n", |
| 292 | + " \"name\": \"CitiesGrammar\",\n", |
| 293 | + " \"description\": \"Constrains generation.\",\n", |
| 294 | + " \"format\": {\n", |
| 295 | + " \"type\": \"grammar\",\n", |
| 296 | + " \"syntax\": \"lark\",\n", |
| 297 | + " \"definition\": lark_grammar,\n", |
| 298 | + " },\n", |
| 299 | + "}\n", |
| 300 | + "\n", |
| 301 | + "target = OpenAIResponseTarget(\n", |
| 302 | + " endpoint=os.getenv(\"PLATFORM_OPENAI_RESPONSES_ENDPOINT\"),\n", |
| 303 | + " api_key=os.getenv(\"PLATFORM_OPENAI_RESPONSES_KEY\"),\n", |
| 304 | + " model_name=\"gpt-5\",\n", |
| 305 | + " api_version=None,\n", |
| 306 | + " extra_body_parameters={\"tools\": [grammar_tool], \"tool_choice\": \"required\"},\n", |
| 307 | + " temperature=1.0,\n", |
| 308 | + ")\n", |
| 309 | + "\n", |
| 310 | + "unconstrained_target = OpenAIResponseTarget(\n", |
| 311 | + " endpoint=os.getenv(\"PLATFORM_OPENAI_RESPONSES_ENDPOINT\"),\n", |
| 312 | + " api_key=os.getenv(\"PLATFORM_OPENAI_RESPONSES_KEY\"),\n", |
| 313 | + " model_name=\"gpt-5\",\n", |
| 314 | + " api_version=None,\n", |
| 315 | + " temperature=1.0,\n", |
| 316 | + ")\n", |
| 317 | + "\n", |
| 318 | + "unconstrained_result = await unconstrained_target.send_prompt_async(prompt_request=prompt_request) # type: ignore\n", |
| 319 | + "\n", |
| 320 | + "result = await target.send_prompt_async(prompt_request=prompt_request) # type: ignore\n", |
| 321 | + "\n", |
| 322 | + "print(\"Unconstrained Response:\")\n", |
| 323 | + "for idx, piece in enumerate(unconstrained_result.message_pieces):\n", |
| 324 | + " if piece.original_value_data_type != \"reasoning\":\n", |
| 325 | + " print(f\"{idx} | {piece.role}: {piece.original_value}\")\n", |
| 326 | + "\n", |
| 327 | + "print()\n", |
| 328 | + "\n", |
| 329 | + "print(\"Constrained Response:\")\n", |
| 330 | + "for idx, piece in enumerate(result.message_pieces):\n", |
| 331 | + " if piece.original_value_data_type != \"reasoning\":\n", |
| 332 | + " print(f\"{idx} | {piece.role}: {piece.original_value}\")" |
| 333 | + ] |
| 334 | + }, |
| 335 | + { |
| 336 | + "cell_type": "code", |
| 337 | + "execution_count": null, |
| 338 | + "id": "8", |
| 339 | + "metadata": {}, |
| 340 | + "outputs": [], |
| 341 | + "source": [] |
236 | 342 | } |
237 | 343 | ], |
238 | 344 | "metadata": { |
|
249 | 355 | "name": "python", |
250 | 356 | "nbconvert_exporter": "python", |
251 | 357 | "pygments_lexer": "ipython3", |
252 | | - "version": "3.12.11" |
| 358 | + "version": "3.11.13" |
253 | 359 | } |
254 | 360 | }, |
255 | 361 | "nbformat": 4, |
|
0 commit comments