langchain-core 0.4.0.dev0__py3-none-any.whl → 1.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of langchain-core might be problematic. Click here for more details.

Files changed (172) hide show
  1. langchain_core/__init__.py +1 -1
  2. langchain_core/_api/__init__.py +3 -4
  3. langchain_core/_api/beta_decorator.py +45 -70
  4. langchain_core/_api/deprecation.py +80 -80
  5. langchain_core/_api/path.py +22 -8
  6. langchain_core/_import_utils.py +10 -4
  7. langchain_core/agents.py +25 -21
  8. langchain_core/caches.py +53 -63
  9. langchain_core/callbacks/__init__.py +1 -8
  10. langchain_core/callbacks/base.py +341 -348
  11. langchain_core/callbacks/file.py +55 -44
  12. langchain_core/callbacks/manager.py +546 -683
  13. langchain_core/callbacks/stdout.py +29 -30
  14. langchain_core/callbacks/streaming_stdout.py +35 -36
  15. langchain_core/callbacks/usage.py +65 -70
  16. langchain_core/chat_history.py +48 -55
  17. langchain_core/document_loaders/base.py +46 -21
  18. langchain_core/document_loaders/langsmith.py +39 -36
  19. langchain_core/documents/__init__.py +0 -1
  20. langchain_core/documents/base.py +96 -74
  21. langchain_core/documents/compressor.py +12 -9
  22. langchain_core/documents/transformers.py +29 -28
  23. langchain_core/embeddings/fake.py +56 -57
  24. langchain_core/env.py +2 -3
  25. langchain_core/example_selectors/base.py +12 -0
  26. langchain_core/example_selectors/length_based.py +1 -1
  27. langchain_core/example_selectors/semantic_similarity.py +21 -25
  28. langchain_core/exceptions.py +15 -9
  29. langchain_core/globals.py +4 -163
  30. langchain_core/indexing/api.py +132 -125
  31. langchain_core/indexing/base.py +64 -67
  32. langchain_core/indexing/in_memory.py +26 -6
  33. langchain_core/language_models/__init__.py +15 -27
  34. langchain_core/language_models/_utils.py +267 -117
  35. langchain_core/language_models/base.py +92 -177
  36. langchain_core/language_models/chat_models.py +547 -407
  37. langchain_core/language_models/fake.py +11 -11
  38. langchain_core/language_models/fake_chat_models.py +72 -118
  39. langchain_core/language_models/llms.py +168 -242
  40. langchain_core/load/dump.py +8 -11
  41. langchain_core/load/load.py +32 -28
  42. langchain_core/load/mapping.py +2 -4
  43. langchain_core/load/serializable.py +50 -56
  44. langchain_core/messages/__init__.py +36 -51
  45. langchain_core/messages/ai.py +377 -150
  46. langchain_core/messages/base.py +239 -47
  47. langchain_core/messages/block_translators/__init__.py +111 -0
  48. langchain_core/messages/block_translators/anthropic.py +470 -0
  49. langchain_core/messages/block_translators/bedrock.py +94 -0
  50. langchain_core/messages/block_translators/bedrock_converse.py +297 -0
  51. langchain_core/messages/block_translators/google_genai.py +530 -0
  52. langchain_core/messages/block_translators/google_vertexai.py +21 -0
  53. langchain_core/messages/block_translators/groq.py +143 -0
  54. langchain_core/messages/block_translators/langchain_v0.py +301 -0
  55. langchain_core/messages/block_translators/openai.py +1010 -0
  56. langchain_core/messages/chat.py +2 -3
  57. langchain_core/messages/content.py +1423 -0
  58. langchain_core/messages/function.py +7 -7
  59. langchain_core/messages/human.py +44 -38
  60. langchain_core/messages/modifier.py +3 -2
  61. langchain_core/messages/system.py +40 -27
  62. langchain_core/messages/tool.py +160 -58
  63. langchain_core/messages/utils.py +527 -638
  64. langchain_core/output_parsers/__init__.py +1 -14
  65. langchain_core/output_parsers/base.py +68 -104
  66. langchain_core/output_parsers/json.py +13 -17
  67. langchain_core/output_parsers/list.py +11 -33
  68. langchain_core/output_parsers/openai_functions.py +56 -74
  69. langchain_core/output_parsers/openai_tools.py +68 -109
  70. langchain_core/output_parsers/pydantic.py +15 -13
  71. langchain_core/output_parsers/string.py +6 -2
  72. langchain_core/output_parsers/transform.py +17 -60
  73. langchain_core/output_parsers/xml.py +34 -44
  74. langchain_core/outputs/__init__.py +1 -1
  75. langchain_core/outputs/chat_generation.py +26 -11
  76. langchain_core/outputs/chat_result.py +1 -3
  77. langchain_core/outputs/generation.py +17 -6
  78. langchain_core/outputs/llm_result.py +15 -8
  79. langchain_core/prompt_values.py +29 -123
  80. langchain_core/prompts/__init__.py +3 -27
  81. langchain_core/prompts/base.py +48 -63
  82. langchain_core/prompts/chat.py +259 -288
  83. langchain_core/prompts/dict.py +19 -11
  84. langchain_core/prompts/few_shot.py +84 -90
  85. langchain_core/prompts/few_shot_with_templates.py +14 -12
  86. langchain_core/prompts/image.py +19 -14
  87. langchain_core/prompts/loading.py +6 -8
  88. langchain_core/prompts/message.py +7 -8
  89. langchain_core/prompts/prompt.py +42 -43
  90. langchain_core/prompts/string.py +37 -16
  91. langchain_core/prompts/structured.py +43 -46
  92. langchain_core/rate_limiters.py +51 -60
  93. langchain_core/retrievers.py +52 -192
  94. langchain_core/runnables/base.py +1727 -1683
  95. langchain_core/runnables/branch.py +52 -73
  96. langchain_core/runnables/config.py +89 -103
  97. langchain_core/runnables/configurable.py +128 -130
  98. langchain_core/runnables/fallbacks.py +93 -82
  99. langchain_core/runnables/graph.py +127 -127
  100. langchain_core/runnables/graph_ascii.py +63 -41
  101. langchain_core/runnables/graph_mermaid.py +87 -70
  102. langchain_core/runnables/graph_png.py +31 -36
  103. langchain_core/runnables/history.py +145 -161
  104. langchain_core/runnables/passthrough.py +141 -144
  105. langchain_core/runnables/retry.py +84 -68
  106. langchain_core/runnables/router.py +33 -37
  107. langchain_core/runnables/schema.py +79 -72
  108. langchain_core/runnables/utils.py +95 -139
  109. langchain_core/stores.py +85 -131
  110. langchain_core/structured_query.py +11 -15
  111. langchain_core/sys_info.py +31 -32
  112. langchain_core/tools/__init__.py +1 -14
  113. langchain_core/tools/base.py +221 -247
  114. langchain_core/tools/convert.py +144 -161
  115. langchain_core/tools/render.py +10 -10
  116. langchain_core/tools/retriever.py +12 -19
  117. langchain_core/tools/simple.py +52 -29
  118. langchain_core/tools/structured.py +56 -60
  119. langchain_core/tracers/__init__.py +1 -9
  120. langchain_core/tracers/_streaming.py +6 -7
  121. langchain_core/tracers/base.py +103 -112
  122. langchain_core/tracers/context.py +29 -48
  123. langchain_core/tracers/core.py +142 -105
  124. langchain_core/tracers/evaluation.py +30 -34
  125. langchain_core/tracers/event_stream.py +162 -117
  126. langchain_core/tracers/langchain.py +34 -36
  127. langchain_core/tracers/log_stream.py +87 -49
  128. langchain_core/tracers/memory_stream.py +3 -3
  129. langchain_core/tracers/root_listeners.py +18 -34
  130. langchain_core/tracers/run_collector.py +8 -20
  131. langchain_core/tracers/schemas.py +0 -125
  132. langchain_core/tracers/stdout.py +3 -3
  133. langchain_core/utils/__init__.py +1 -4
  134. langchain_core/utils/_merge.py +47 -9
  135. langchain_core/utils/aiter.py +70 -66
  136. langchain_core/utils/env.py +12 -9
  137. langchain_core/utils/function_calling.py +139 -206
  138. langchain_core/utils/html.py +7 -8
  139. langchain_core/utils/input.py +6 -6
  140. langchain_core/utils/interactive_env.py +6 -2
  141. langchain_core/utils/iter.py +48 -45
  142. langchain_core/utils/json.py +14 -4
  143. langchain_core/utils/json_schema.py +159 -43
  144. langchain_core/utils/mustache.py +32 -25
  145. langchain_core/utils/pydantic.py +67 -40
  146. langchain_core/utils/strings.py +5 -5
  147. langchain_core/utils/usage.py +1 -1
  148. langchain_core/utils/utils.py +104 -62
  149. langchain_core/vectorstores/base.py +131 -179
  150. langchain_core/vectorstores/in_memory.py +113 -182
  151. langchain_core/vectorstores/utils.py +23 -17
  152. langchain_core/version.py +1 -1
  153. langchain_core-1.0.0.dist-info/METADATA +68 -0
  154. langchain_core-1.0.0.dist-info/RECORD +172 -0
  155. {langchain_core-0.4.0.dev0.dist-info → langchain_core-1.0.0.dist-info}/WHEEL +1 -1
  156. langchain_core/beta/__init__.py +0 -1
  157. langchain_core/beta/runnables/__init__.py +0 -1
  158. langchain_core/beta/runnables/context.py +0 -448
  159. langchain_core/memory.py +0 -116
  160. langchain_core/messages/content_blocks.py +0 -1435
  161. langchain_core/prompts/pipeline.py +0 -133
  162. langchain_core/pydantic_v1/__init__.py +0 -30
  163. langchain_core/pydantic_v1/dataclasses.py +0 -23
  164. langchain_core/pydantic_v1/main.py +0 -23
  165. langchain_core/tracers/langchain_v1.py +0 -23
  166. langchain_core/utils/loading.py +0 -31
  167. langchain_core/v1/__init__.py +0 -1
  168. langchain_core/v1/chat_models.py +0 -1047
  169. langchain_core/v1/messages.py +0 -755
  170. langchain_core-0.4.0.dev0.dist-info/METADATA +0 -108
  171. langchain_core-0.4.0.dev0.dist-info/RECORD +0 -177
  172. langchain_core-0.4.0.dev0.dist-info/entry_points.txt +0 -4
@@ -4,21 +4,21 @@ from __future__ import annotations
4
4
 
5
5
  import inspect
6
6
  from collections import defaultdict
7
+ from collections.abc import Callable
7
8
  from dataclasses import dataclass, field
8
9
  from enum import Enum
9
10
  from typing import (
10
11
  TYPE_CHECKING,
11
12
  Any,
12
- Callable,
13
13
  NamedTuple,
14
- Optional,
15
14
  Protocol,
16
15
  TypedDict,
17
- Union,
18
16
  overload,
19
17
  )
20
18
  from uuid import UUID, uuid4
21
19
 
20
+ from langchain_core.load.serializable import to_json_not_implemented
21
+ from langchain_core.runnables.base import Runnable, RunnableSerializable
22
22
  from langchain_core.utils.pydantic import _IgnoreUnserializable, is_basemodel_subclass
23
23
 
24
24
  if TYPE_CHECKING:
@@ -52,7 +52,7 @@ def is_uuid(value: str) -> bool:
52
52
  value: The string to check.
53
53
 
54
54
  Returns:
55
- True if the string is a valid UUID, False otherwise.
55
+ `True` if the string is a valid UUID, `False` otherwise.
56
56
  """
57
57
  try:
58
58
  UUID(value)
@@ -62,28 +62,23 @@ def is_uuid(value: str) -> bool:
62
62
 
63
63
 
64
64
  class Edge(NamedTuple):
65
- """Edge in a graph.
66
-
67
- Parameters:
68
- source: The source node id.
69
- target: The target node id.
70
- data: Optional data associated with the edge. Defaults to None.
71
- conditional: Whether the edge is conditional. Defaults to False.
72
- """
65
+ """Edge in a graph."""
73
66
 
74
67
  source: str
68
+ """The source node id."""
75
69
  target: str
76
- data: Optional[Stringifiable] = None
70
+ """The target node id."""
71
+ data: Stringifiable | None = None
72
+ """Optional data associated with the edge. """
77
73
  conditional: bool = False
74
+ """Whether the edge is conditional."""
78
75
 
79
- def copy(
80
- self, *, source: Optional[str] = None, target: Optional[str] = None
81
- ) -> Edge:
76
+ def copy(self, *, source: str | None = None, target: str | None = None) -> Edge:
82
77
  """Return a copy of the edge with optional new source and target nodes.
83
78
 
84
79
  Args:
85
- source: The new source node id. Defaults to None.
86
- target: The new target node id. Defaults to None.
80
+ source: The new source node id.
81
+ target: The new target node id.
87
82
 
88
83
  Returns:
89
84
  A copy of the edge with the new source and target nodes.
@@ -97,31 +92,28 @@ class Edge(NamedTuple):
97
92
 
98
93
 
99
94
  class Node(NamedTuple):
100
- """Node in a graph.
101
-
102
- Parameters:
103
- id: The unique identifier of the node.
104
- name: The name of the node.
105
- data: The data of the node.
106
- metadata: Optional metadata for the node. Defaults to None.
107
- """
95
+ """Node in a graph."""
108
96
 
109
97
  id: str
98
+ """The unique identifier of the node."""
110
99
  name: str
111
- data: Union[type[BaseModel], RunnableType, None]
112
- metadata: Optional[dict[str, Any]]
100
+ """The name of the node."""
101
+ data: type[BaseModel] | RunnableType | None
102
+ """The data of the node."""
103
+ metadata: dict[str, Any] | None
104
+ """Optional metadata for the node. """
113
105
 
114
106
  def copy(
115
107
  self,
116
108
  *,
117
- id: Optional[str] = None,
118
- name: Optional[str] = None,
109
+ id: str | None = None,
110
+ name: str | None = None,
119
111
  ) -> Node:
120
112
  """Return a copy of the node with optional new id and name.
121
113
 
122
114
  Args:
123
- id: The new node id. Defaults to None.
124
- name: The new node name. Defaults to None.
115
+ id: The new node id.
116
+ name: The new node name.
125
117
 
126
118
  Returns:
127
119
  A copy of the node with the new id and name.
@@ -135,16 +127,12 @@ class Node(NamedTuple):
135
127
 
136
128
 
137
129
  class Branch(NamedTuple):
138
- """Branch in a graph.
139
-
140
- Parameters:
141
- condition: A callable that returns a string representation of the condition.
142
- ends: Optional dictionary of end node ids for the branches. Defaults
143
- to None.
144
- """
130
+ """Branch in a graph."""
145
131
 
146
132
  condition: Callable[..., str]
147
- ends: Optional[dict[str, str]]
133
+ """A callable that returns a string representation of the condition."""
134
+ ends: dict[str, str] | None
135
+ """Optional dictionary of end node ids for the branches. """
148
136
 
149
137
 
150
138
  class CurveStyle(Enum):
@@ -168,10 +156,10 @@ class CurveStyle(Enum):
168
156
  class NodeStyles:
169
157
  """Schema for Hexadecimal color codes for different node types.
170
158
 
171
- Parameters:
172
- default: The default color code. Defaults to "fill:#f2f0ff,line-height:1.2".
173
- first: The color code for the first node. Defaults to "fill-opacity:0".
174
- last: The color code for the last node. Defaults to "fill:#bfb6fc".
159
+ Args:
160
+ default: The default color code.
161
+ first: The color code for the first node.
162
+ last: The color code for the last node.
175
163
  """
176
164
 
177
165
  default: str = "fill:#f2f0ff,line-height:1.2"
@@ -182,13 +170,15 @@ class NodeStyles:
182
170
  class MermaidDrawMethod(Enum):
183
171
  """Enum for different draw methods supported by Mermaid."""
184
172
 
185
- PYPPETEER = "pyppeteer" # Uses Pyppeteer to render the graph
186
- API = "api" # Uses Mermaid.INK API to render the graph
173
+ PYPPETEER = "pyppeteer"
174
+ """Uses Pyppeteer to render the graph"""
175
+ API = "api"
176
+ """Uses Mermaid.INK API to render the graph"""
187
177
 
188
178
 
189
179
  def node_data_str(
190
180
  id: str,
191
- data: Union[type[BaseModel], RunnableType, None],
181
+ data: type[BaseModel] | RunnableType | None,
192
182
  ) -> str:
193
183
  """Convert the data of a node to a string.
194
184
 
@@ -199,8 +189,6 @@ def node_data_str(
199
189
  Returns:
200
190
  A string representation of the data.
201
191
  """
202
- from langchain_core.runnables.base import Runnable
203
-
204
192
  if not is_uuid(id) or data is None:
205
193
  return id
206
194
  data_str = data.get_name() if isinstance(data, Runnable) else data.__name__
@@ -209,20 +197,17 @@ def node_data_str(
209
197
 
210
198
  def node_data_json(
211
199
  node: Node, *, with_schemas: bool = False
212
- ) -> dict[str, Union[str, dict[str, Any]]]:
200
+ ) -> dict[str, str | dict[str, Any]]:
213
201
  """Convert the data of a node to a JSON-serializable format.
214
202
 
215
203
  Args:
216
- node: The node to convert.
217
- with_schemas: Whether to include the schema of the data if
218
- it is a Pydantic model. Defaults to False.
204
+ node: The `Node` to convert.
205
+ with_schemas: Whether to include the schema of the data if it is a Pydantic
206
+ model.
219
207
 
220
208
  Returns:
221
209
  A dictionary with the type of the data and the data itself.
222
210
  """
223
- from langchain_core.load.serializable import to_json_not_implemented
224
- from langchain_core.runnables.base import Runnable, RunnableSerializable
225
-
226
211
  if node.data is None:
227
212
  json: dict[str, Any] = {}
228
213
  elif isinstance(node.data, RunnableSerializable):
@@ -269,7 +254,7 @@ def node_data_json(
269
254
  class Graph:
270
255
  """Graph of nodes and edges.
271
256
 
272
- Parameters:
257
+ Args:
273
258
  nodes: Dictionary of nodes in the graph. Defaults to an empty dictionary.
274
259
  edges: List of edges in the graph. Defaults to an empty list.
275
260
  """
@@ -282,7 +267,7 @@ class Graph:
282
267
 
283
268
  Args:
284
269
  with_schemas: Whether to include the schemas of the nodes if they are
285
- Pydantic models. Defaults to False.
270
+ Pydantic models.
286
271
 
287
272
  Returns:
288
273
  A dictionary with the nodes and edges of the graph.
@@ -327,17 +312,17 @@ class Graph:
327
312
 
328
313
  def add_node(
329
314
  self,
330
- data: Union[type[BaseModel], RunnableType, None],
331
- id: Optional[str] = None,
315
+ data: type[BaseModel] | RunnableType | None,
316
+ id: str | None = None,
332
317
  *,
333
- metadata: Optional[dict[str, Any]] = None,
318
+ metadata: dict[str, Any] | None = None,
334
319
  ) -> Node:
335
320
  """Add a node to the graph and return it.
336
321
 
337
322
  Args:
338
323
  data: The data of the node.
339
- id: The id of the node. Defaults to None.
340
- metadata: Optional metadata for the node. Defaults to None.
324
+ id: The id of the node.
325
+ metadata: Optional metadata for the node.
341
326
 
342
327
  Returns:
343
328
  The node that was added to the graph.
@@ -368,7 +353,7 @@ class Graph:
368
353
  self,
369
354
  source: Node,
370
355
  target: Node,
371
- data: Optional[Stringifiable] = None,
356
+ data: Stringifiable | None = None,
372
357
  conditional: bool = False, # noqa: FBT001,FBT002
373
358
  ) -> Edge:
374
359
  """Add an edge to the graph and return it.
@@ -376,8 +361,8 @@ class Graph:
376
361
  Args:
377
362
  source: The source node of the edge.
378
363
  target: The target node of the edge.
379
- data: Optional data associated with the edge. Defaults to None.
380
- conditional: Whether the edge is conditional. Defaults to False.
364
+ data: Optional data associated with the edge.
365
+ conditional: Whether the edge is conditional.
381
366
 
382
367
  Returns:
383
368
  The edge that was added to the graph.
@@ -399,14 +384,14 @@ class Graph:
399
384
 
400
385
  def extend(
401
386
  self, graph: Graph, *, prefix: str = ""
402
- ) -> tuple[Optional[Node], Optional[Node]]:
387
+ ) -> tuple[Node | None, Node | None]:
403
388
  """Add all nodes and edges from another graph.
404
389
 
405
390
  Note this doesn't check for duplicates, nor does it connect the graphs.
406
391
 
407
392
  Args:
408
393
  graph: The graph to add.
409
- prefix: The prefix to add to the node ids. Defaults to "".
394
+ prefix: The prefix to add to the node ids.
410
395
 
411
396
  Returns:
412
397
  A tuple of the first and last nodes of the subgraph.
@@ -470,19 +455,27 @@ class Graph:
470
455
  ],
471
456
  )
472
457
 
473
- def first_node(self) -> Optional[Node]:
458
+ def first_node(self) -> Node | None:
474
459
  """Find the single node that is not a target of any edge.
475
460
 
476
- If there is no such node, or there are multiple, return None.
461
+ If there is no such node, or there are multiple, return `None`.
477
462
  When drawing the graph, this node would be the origin.
463
+
464
+ Returns:
465
+ The first node, or None if there is no such node or multiple
466
+ candidates.
478
467
  """
479
468
  return _first_node(self)
480
469
 
481
- def last_node(self) -> Optional[Node]:
470
+ def last_node(self) -> Node | None:
482
471
  """Find the single node that is not a source of any edge.
483
472
 
484
- If there is no such node, or there are multiple, return None.
473
+ If there is no such node, or there are multiple, return `None`.
485
474
  When drawing the graph, this node would be the destination.
475
+
476
+ Returns:
477
+ The last node, or None if there is no such node or multiple
478
+ candidates.
486
479
  """
487
480
  return _last_node(self)
488
481
 
@@ -513,8 +506,13 @@ class Graph:
513
506
  self.remove_node(last_node)
514
507
 
515
508
  def draw_ascii(self) -> str:
516
- """Draw the graph as an ASCII art string."""
517
- from langchain_core.runnables.graph_ascii import draw_ascii
509
+ """Draw the graph as an ASCII art string.
510
+
511
+ Returns:
512
+ The ASCII art string.
513
+ """
514
+ # Import locally to prevent circular import
515
+ from langchain_core.runnables.graph_ascii import draw_ascii # noqa: PLC0415
518
516
 
519
517
  return draw_ascii(
520
518
  {node.id: node.name for node in self.nodes.values()},
@@ -529,36 +527,38 @@ class Graph:
529
527
  def draw_png(
530
528
  self,
531
529
  output_file_path: str,
532
- fontname: Optional[str] = None,
533
- labels: Optional[LabelsDict] = None,
530
+ fontname: str | None = None,
531
+ labels: LabelsDict | None = None,
534
532
  ) -> None: ...
535
533
 
536
534
  @overload
537
535
  def draw_png(
538
536
  self,
539
537
  output_file_path: None,
540
- fontname: Optional[str] = None,
541
- labels: Optional[LabelsDict] = None,
538
+ fontname: str | None = None,
539
+ labels: LabelsDict | None = None,
542
540
  ) -> bytes: ...
543
541
 
544
542
  def draw_png(
545
543
  self,
546
- output_file_path: Optional[str] = None,
547
- fontname: Optional[str] = None,
548
- labels: Optional[LabelsDict] = None,
549
- ) -> Union[bytes, None]:
544
+ output_file_path: str | None = None,
545
+ fontname: str | None = None,
546
+ labels: LabelsDict | None = None,
547
+ ) -> bytes | None:
550
548
  """Draw the graph as a PNG image.
551
549
 
552
550
  Args:
553
- output_file_path: The path to save the image to. If None, the image
554
- is not saved. Defaults to None.
555
- fontname: The name of the font to use. Defaults to None.
556
- labels: Optional labels for nodes and edges in the graph. Defaults to None.
551
+ output_file_path: The path to save the image to. If `None`, the image
552
+ is not saved.
553
+ fontname: The name of the font to use.
554
+ labels: Optional labels for nodes and edges in the graph. Defaults to
555
+ `None`.
557
556
 
558
557
  Returns:
559
558
  The PNG image as bytes if output_file_path is None, None otherwise.
560
559
  """
561
- from langchain_core.runnables.graph_png import PngDrawer
560
+ # Import locally to prevent circular import
561
+ from langchain_core.runnables.graph_png import PngDrawer # noqa: PLC0415
562
562
 
563
563
  default_node_labels = {node.id: node.name for node in self.nodes.values()}
564
564
 
@@ -578,42 +578,39 @@ class Graph:
578
578
  *,
579
579
  with_styles: bool = True,
580
580
  curve_style: CurveStyle = CurveStyle.LINEAR,
581
- node_colors: Optional[NodeStyles] = None,
581
+ node_colors: NodeStyles | None = None,
582
582
  wrap_label_n_words: int = 9,
583
- frontmatter_config: Optional[dict[str, Any]] = None,
583
+ frontmatter_config: dict[str, Any] | None = None,
584
584
  ) -> str:
585
585
  """Draw the graph as a Mermaid syntax string.
586
586
 
587
587
  Args:
588
- with_styles: Whether to include styles in the syntax. Defaults to True.
589
- curve_style: The style of the edges. Defaults to CurveStyle.LINEAR.
590
- node_colors: The colors of the nodes. Defaults to NodeStyles().
588
+ with_styles: Whether to include styles in the syntax.
589
+ curve_style: The style of the edges.
590
+ node_colors: The colors of the nodes.
591
591
  wrap_label_n_words: The number of words to wrap the node labels at.
592
- Defaults to 9.
593
- frontmatter_config (dict[str, Any], optional): Mermaid frontmatter config.
592
+ frontmatter_config: Mermaid frontmatter config.
594
593
  Can be used to customize theme and styles. Will be converted to YAML and
595
- added to the beginning of the mermaid graph. Defaults to None.
594
+ added to the beginning of the mermaid graph.
596
595
 
597
596
  See more here: https://mermaid.js.org/config/configuration.html.
598
597
 
599
598
  Example config:
600
599
 
601
- .. code-block:: python
602
-
600
+ ```python
603
601
  {
604
602
  "config": {
605
603
  "theme": "neutral",
606
604
  "look": "handDrawn",
607
- "themeVariables": { "primaryColor": "#e2e2e2"},
605
+ "themeVariables": {"primaryColor": "#e2e2e2"},
608
606
  }
609
607
  }
610
-
611
-
608
+ ```
612
609
  Returns:
613
610
  The Mermaid syntax string.
614
-
615
611
  """
616
- from langchain_core.runnables.graph_mermaid import draw_mermaid
612
+ # Import locally to prevent circular import
613
+ from langchain_core.runnables.graph_mermaid import draw_mermaid # noqa: PLC0415
617
614
 
618
615
  graph = self.reid()
619
616
  first_node = graph.first_node()
@@ -635,56 +632,58 @@ class Graph:
635
632
  self,
636
633
  *,
637
634
  curve_style: CurveStyle = CurveStyle.LINEAR,
638
- node_colors: Optional[NodeStyles] = None,
635
+ node_colors: NodeStyles | None = None,
639
636
  wrap_label_n_words: int = 9,
640
- output_file_path: Optional[str] = None,
637
+ output_file_path: str | None = None,
641
638
  draw_method: MermaidDrawMethod = MermaidDrawMethod.API,
642
639
  background_color: str = "white",
643
640
  padding: int = 10,
644
641
  max_retries: int = 1,
645
642
  retry_delay: float = 1.0,
646
- frontmatter_config: Optional[dict[str, Any]] = None,
643
+ frontmatter_config: dict[str, Any] | None = None,
644
+ base_url: str | None = None,
647
645
  ) -> bytes:
648
646
  """Draw the graph as a PNG image using Mermaid.
649
647
 
650
648
  Args:
651
- curve_style: The style of the edges. Defaults to CurveStyle.LINEAR.
652
- node_colors: The colors of the nodes. Defaults to NodeStyles().
649
+ curve_style: The style of the edges.
650
+ node_colors: The colors of the nodes.
653
651
  wrap_label_n_words: The number of words to wrap the node labels at.
654
- Defaults to 9.
655
- output_file_path: The path to save the image to. If None, the image
656
- is not saved. Defaults to None.
652
+ output_file_path: The path to save the image to. If `None`, the image
653
+ is not saved.
657
654
  draw_method: The method to use to draw the graph.
658
- Defaults to MermaidDrawMethod.API.
659
- background_color: The color of the background. Defaults to "white".
660
- padding: The padding around the graph. Defaults to 10.
661
- max_retries: The maximum number of retries (MermaidDrawMethod.API).
662
- Defaults to 1.
663
- retry_delay: The delay between retries (MermaidDrawMethod.API).
664
- Defaults to 1.0.
665
- frontmatter_config (dict[str, Any], optional): Mermaid frontmatter config.
655
+ background_color: The color of the background.
656
+ padding: The padding around the graph.
657
+ max_retries: The maximum number of retries (`MermaidDrawMethod.API`).
658
+ retry_delay: The delay between retries (`MermaidDrawMethod.API`).
659
+ frontmatter_config: Mermaid frontmatter config.
666
660
  Can be used to customize theme and styles. Will be converted to YAML and
667
- added to the beginning of the mermaid graph. Defaults to None.
661
+ added to the beginning of the mermaid graph.
668
662
 
669
663
  See more here: https://mermaid.js.org/config/configuration.html.
670
664
 
671
665
  Example config:
672
666
 
673
- .. code-block:: python
674
-
667
+ ```python
675
668
  {
676
669
  "config": {
677
670
  "theme": "neutral",
678
671
  "look": "handDrawn",
679
- "themeVariables": { "primaryColor": "#e2e2e2"},
672
+ "themeVariables": {"primaryColor": "#e2e2e2"},
680
673
  }
681
674
  }
675
+ ```
676
+ base_url: The base URL of the Mermaid server for rendering via API.
677
+
682
678
 
683
679
  Returns:
684
680
  The PNG image as bytes.
685
681
 
686
682
  """
687
- from langchain_core.runnables.graph_mermaid import draw_mermaid_png
683
+ # Import locally to prevent circular import
684
+ from langchain_core.runnables.graph_mermaid import ( # noqa: PLC0415
685
+ draw_mermaid_png,
686
+ )
688
687
 
689
688
  mermaid_syntax = self.draw_mermaid(
690
689
  curve_style=curve_style,
@@ -700,14 +699,15 @@ class Graph:
700
699
  padding=padding,
701
700
  max_retries=max_retries,
702
701
  retry_delay=retry_delay,
702
+ base_url=base_url,
703
703
  )
704
704
 
705
705
 
706
- def _first_node(graph: Graph, exclude: Sequence[str] = ()) -> Optional[Node]:
706
+ def _first_node(graph: Graph, exclude: Sequence[str] = ()) -> Node | None:
707
707
  """Find the single node that is not a target of any edge.
708
708
 
709
709
  Exclude nodes/sources with ids in the exclude list.
710
- If there is no such node, or there are multiple, return None.
710
+ If there is no such node, or there are multiple, return `None`.
711
711
  When drawing the graph, this node would be the origin.
712
712
  """
713
713
  targets = {edge.target for edge in graph.edges if edge.source not in exclude}
@@ -719,11 +719,11 @@ def _first_node(graph: Graph, exclude: Sequence[str] = ()) -> Optional[Node]:
719
719
  return found[0] if len(found) == 1 else None
720
720
 
721
721
 
722
- def _last_node(graph: Graph, exclude: Sequence[str] = ()) -> Optional[Node]:
722
+ def _last_node(graph: Graph, exclude: Sequence[str] = ()) -> Node | None:
723
723
  """Find the single node that is not a source of any edge.
724
724
 
725
725
  Exclude nodes/targets with ids in the exclude list.
726
- If there is no such node, or there are multiple, return None.
726
+ If there is no such node, or there are multiple, return `None`.
727
727
  When drawing the graph, this node would be the destination.
728
728
  """
729
729
  sources = {edge.source for edge in graph.edges if edge.target not in exclude}