aiqtoolkit 1.2.0a20250617__py3-none-any.whl → 1.2.0a20250618__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 aiqtoolkit might be problematic. Click here for more details.

aiq/builder/context.py CHANGED
@@ -61,6 +61,7 @@ class ActiveFunctionContextManager:
61
61
  class AIQContextState(metaclass=Singleton):
62
62
 
63
63
  def __init__(self):
64
+ self.conversation_id: ContextVar[str | None] = ContextVar("conversation_id", default=None)
64
65
  self.input_message: ContextVar[typing.Any] = ContextVar("input_message", default=None)
65
66
  self.user_manager: ContextVar[typing.Any] = ContextVar("user_manager", default=None)
66
67
  self.metadata: ContextVar[RequestAttributes] = ContextVar("request_attributes", default=RequestAttributes())
@@ -148,6 +149,16 @@ class AIQContext:
148
149
  """
149
150
  return IntermediateStepManager(self._context_state)
150
151
 
152
+ @property
153
+ def conversation_id(self) -> str | None:
154
+ """
155
+ This property retrieves the conversation ID which is the unique identifier for the current chat conversation.
156
+
157
+ Returns:
158
+ str | None
159
+ """
160
+ return self._context_state.conversation_id.get()
161
+
151
162
  @contextmanager
152
163
  def push_active_function(self, function_name: str, input_data: typing.Any | None):
153
164
  """
@@ -392,7 +392,7 @@ class WebSocketUserMessage(BaseModel):
392
392
  type: typing.Literal[WebSocketMessageType.USER_MESSAGE]
393
393
  schema_type: WorkflowSchemaType
394
394
  id: str = "default"
395
- thread_id: str = "default"
395
+ conversation_id: str | None = None
396
396
  content: UserMessageContent
397
397
  user: User = User()
398
398
  security: Security = Security()
@@ -130,28 +130,29 @@ class MessageHandler:
130
130
 
131
131
  return None
132
132
 
133
- async def process_user_message(self, message_as_validated_type: WebSocketUserMessage) -> None:
133
+ async def process_user_message(self, user_message_as_validated_type: WebSocketUserMessage) -> None:
134
134
  """
135
135
  Process user messages and routes them appropriately.
136
136
 
137
- :param message_as_validated_type: A WebSocketUserMessage Data Model instance.
137
+ :param user_message_as_validated_type: A WebSocketUserMessage Data Model instance.
138
138
  """
139
139
 
140
140
  try:
141
- self._message_parent_id = message_as_validated_type.id
142
- self._workflow_schema_type = message_as_validated_type.schema_type
141
+ self._message_parent_id = user_message_as_validated_type.id
142
+ self._workflow_schema_type = user_message_as_validated_type.schema_type
143
+ conversation_id: str = user_message_as_validated_type.conversation_id
143
144
 
144
- content: BaseModel | None = await self.process_user_message_content(message_as_validated_type)
145
+ content: BaseModel | None = await self.process_user_message_content(user_message_as_validated_type)
145
146
 
146
147
  if content is None:
147
- raise ValueError(f"User message content could not be found: {message_as_validated_type}")
148
+ raise ValueError(f"User message content could not be found: {user_message_as_validated_type}")
148
149
 
149
150
  if isinstance(content, TextContent) and (self._background_task is None):
150
151
 
151
152
  await self._process_response()
152
153
  self._background_task = asyncio.create_task(
153
154
  self._websocket_reference.workflow_schema_type.get(self._workflow_schema_type)(
154
- content.text)).add_done_callback(
155
+ content.text, conversation_id)).add_done_callback(
155
156
  lambda task: asyncio.create_task(self._on_process_stream_task_done(task)))
156
157
 
157
158
  except ValueError as e:
@@ -110,10 +110,12 @@ class AIQWebSocket(WebSocketEndpoint):
110
110
 
111
111
  async def _process_message(self,
112
112
  payload: typing.Any,
113
+ conversation_id: str | None = None,
113
114
  result_type: type | None = None,
114
115
  output_type: type | None = None) -> None:
115
116
 
116
117
  async with self._session_manager.session(
118
+ conversation_id=conversation_id,
117
119
  user_input_callback=self._message_handler.human_interaction) as session:
118
120
 
119
121
  async for value in generate_streaming_response(payload,
@@ -131,18 +133,21 @@ class AIQWebSocket(WebSocketEndpoint):
131
133
  await self._message_handler.create_websocket_message(data_model=value,
132
134
  status=WebSocketMessageStatus.IN_PROGRESS)
133
135
 
134
- async def process_generate_stream(self, payload: str):
136
+ async def process_generate_stream(self, payload: str, conversation_id: str) -> None:
135
137
 
136
- return await self._process_message(payload, result_type=None, output_type=None)
138
+ return await self._process_message(payload, conversation_id=conversation_id, result_type=None, output_type=None)
137
139
 
138
- async def process_chat_stream(self, payload: AIQChatRequest):
140
+ async def process_chat_stream(self, payload: AIQChatRequest, conversation_id: str):
139
141
 
140
- return await self._process_message(payload, result_type=AIQChatResponse, output_type=AIQChatResponseChunk)
142
+ return await self._process_message(payload,
143
+ conversation_id=conversation_id,
144
+ result_type=AIQChatResponse,
145
+ output_type=AIQChatResponseChunk)
141
146
 
142
- async def process_generate(self, payload: typing.Any):
147
+ async def process_generate(self, payload: typing.Any, conversation_id: str):
143
148
 
144
- return await self._process_message(payload)
149
+ return await self._process_message(payload, conversation_id=conversation_id)
145
150
 
146
- async def process_chat(self, payload: AIQChatRequest):
151
+ async def process_chat(self, payload: AIQChatRequest, conversation_id: str):
147
152
 
148
- return await self._process_message(payload, result_type=AIQChatResponse)
153
+ return await self._process_message(payload, conversation_id=conversation_id, result_type=AIQChatResponse)
aiq/runtime/session.py CHANGED
@@ -86,7 +86,8 @@ class AIQSessionManager:
86
86
  @asynccontextmanager
87
87
  async def session(self,
88
88
  user_manager=None,
89
- request: Request = None,
89
+ request: Request | None = None,
90
+ conversation_id: str | None = None,
90
91
  user_input_callback: Callable[[InteractionPrompt], Awaitable[HumanResponse]] = None):
91
92
 
92
93
  token_user_input = None
@@ -97,7 +98,10 @@ class AIQSessionManager:
97
98
  if user_manager is not None:
98
99
  token_user_manager = self._context_state.user_manager.set(user_manager)
99
100
 
100
- self.set_request_attributes(request)
101
+ if conversation_id is not None and request is None:
102
+ self._context_state.conversation_id.set(conversation_id)
103
+
104
+ self.set_metadata_from_http_request(request)
101
105
 
102
106
  try:
103
107
  yield self
@@ -120,9 +124,9 @@ class AIQSessionManager:
120
124
  async with self._workflow.run(message) as runner:
121
125
  yield runner
122
126
 
123
- def set_request_attributes(self, request: Request) -> None:
127
+ def set_metadata_from_http_request(self, request: Request | None) -> None:
124
128
  """
125
- Extracts and sets request attributes from an HTTP request.
129
+ Extracts and sets user metadata request attributes from a HTTP request.
126
130
  If request is None, no attributes are set.
127
131
  """
128
132
  if request is None:
@@ -138,3 +142,6 @@ class AIQSessionManager:
138
142
  self._context.metadata._request.client_host = request.client.host
139
143
  self._context.metadata._request.client_port = request.client.port
140
144
  self._context.metadata._request.cookies = request.cookies
145
+
146
+ if request.headers.get("conversation-id"):
147
+ self._context_state.conversation_id.set(request.headers["conversation-id"])
@@ -21,9 +21,8 @@ from aiq.data_models.api_server import Request
21
21
 
22
22
  class RequestAttributes:
23
23
  """
24
- The RequestAttributes class is responsible for managing user-defined
25
- metadata and attributes. It provides a way to store and
26
- expose user-defined attributes to workflow tools.
24
+ The RequestAttributes class is responsible for managing user http and webscoket session
25
+ metadata. It provides a way to store and expose session attributes to workflow tools.
27
26
  """
28
27
 
29
28
  def __init__(self) -> None:
aiq/tool/server_tools.py CHANGED
@@ -39,6 +39,7 @@ async def current_request_attributes(config: RequestAttributesTool, builder: Bui
39
39
 
40
40
  from aiq.builder.context import AIQContext
41
41
  aiq_context = AIQContext.get()
42
+
42
43
  method: str | None = aiq_context.metadata.method
43
44
  url_path: str | None = aiq_context.metadata.url_path
44
45
  url_scheme: str | None = aiq_context.metadata.url_scheme
@@ -48,6 +49,7 @@ async def current_request_attributes(config: RequestAttributesTool, builder: Bui
48
49
  client_host: str | None = aiq_context.metadata.client_host
49
50
  client_port: int | None = aiq_context.metadata.client_port
50
51
  cookies: dict[str, str] | None = aiq_context.metadata.cookies
52
+ conversation_id: str | None = aiq_context.conversation_id
51
53
 
52
54
  return (f"Method: {method}, "
53
55
  f"URL Path: {url_path}, "
@@ -57,7 +59,8 @@ async def current_request_attributes(config: RequestAttributesTool, builder: Bui
57
59
  f"Path Params: {path_params}, "
58
60
  f"Client Host: {client_host}, "
59
61
  f"Client Port: {client_port}, "
60
- f"Cookies: {cookies}")
62
+ f"Cookies: {cookies}, "
63
+ f"Conversation Id: {conversation_id}")
61
64
 
62
65
  yield FunctionInfo.from_fn(_get_request_attributes,
63
66
  description="Returns the acquired user defined request attriubutes.")
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: aiqtoolkit
3
- Version: 1.2.0a20250617
3
+ Version: 1.2.0a20250618
4
4
  Summary: NVIDIA Agent Intelligence toolkit
5
5
  Author: NVIDIA Corporation
6
6
  Maintainer: NVIDIA Corporation
@@ -19,7 +19,7 @@ aiq/agent/tool_calling_agent/register.py,sha256=kqcN2uovVBQxrIx5MszBS65opbhBrCRl
19
19
  aiq/builder/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
20
20
  aiq/builder/builder.py,sha256=JE3uCw6qTmWX2akUfS-Ga5WSiJVTzBjDQPniiONMjy4,7448
21
21
  aiq/builder/component_utils.py,sha256=2jIXWSLIlKxDKAO7kdXz_4BHqQNWw4t9GmcQfw0ER4g,12923
22
- aiq/builder/context.py,sha256=f-kw7JfsIFW83V3ZJFv2OU8LcvNVAg-vRVZ9qtbVESo,9173
22
+ aiq/builder/context.py,sha256=34laVLvpsHxvj5sm_3zpXVA7IgxZE1ZDNXjXAi_74KE,9572
23
23
  aiq/builder/embedder.py,sha256=M-n2oXSlwE7u-nmpzRbPq6UVWtFtMvrEdKqqsbKQZLk,965
24
24
  aiq/builder/eval_builder.py,sha256=UnNgtQiDAUfT3yuwjZQVerenI09-4q0Cse9uwLjk3Fg,4657
25
25
  aiq/builder/evaluator.py,sha256=O6Gu0cUwQkrPxPX29Vf_-RopgijxPnhy7mhg_j-9A84,1162
@@ -74,7 +74,7 @@ aiq/cli/commands/workflow/templates/pyproject.toml.j2,sha256=tDV7-vbt8Of82OEdSOi
74
74
  aiq/cli/commands/workflow/templates/register.py.j2,sha256=SlOFmIZakPDu_E6DbIhUZ3yP8KhTrAQCFGBuhy9Fyg4,170
75
75
  aiq/cli/commands/workflow/templates/workflow.py.j2,sha256=NRp0MP8GtZByk7lrHp2Y5_6iEopRK2Wyrt0v0_2qQeo,1226
76
76
  aiq/data_models/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
77
- aiq/data_models/api_server.py,sha256=B7PS9u3k2gD23tq5Hrmtji6LhL_hPsz8O-zVHbe0IEQ,18950
77
+ aiq/data_models/api_server.py,sha256=EWeFo4TvPt3VC6s21VjcE5Pc13XnwL2_YEhA5LLSg_k,18958
78
78
  aiq/data_models/common.py,sha256=G63rUXvDAtK6p1SrRyH0VlHGqrDgCZVVjbnzgGSl2Ic,4213
79
79
  aiq/data_models/component.py,sha256=x6jm1Fhn1k1hGu-5AjM0ywuyvs6ztaZfapD8bLUXSqc,1469
80
80
  aiq/data_models/component_ref.py,sha256=GyyIf4k80aUIn6LV9r84m5imbiVhpdaY7uKMMpYpbzU,3872
@@ -148,12 +148,12 @@ aiq/front_ends/fastapi/fastapi_front_end_plugin_worker.py,sha256=ZbAM3qZFUQJDp2s
148
148
  aiq/front_ends/fastapi/intermediate_steps_subscriber.py,sha256=2Y3ZXfiu8d85qJRWbT3-ex6iFDuXO6TnNtjQ6Cjl-tc,3131
149
149
  aiq/front_ends/fastapi/job_store.py,sha256=AZC0a8miKqSI9YbW19-AA_GPITVY9bYHXn9H8saNrfQ,6389
150
150
  aiq/front_ends/fastapi/main.py,sha256=ftLYy8YEyiY38kxReRwAVKwQsTa7QrKjnBU8V1omXaU,2789
151
- aiq/front_ends/fastapi/message_handler.py,sha256=3rFDXG633Upom1taW3ab_sC3KKxN8Y_WoM_kXtJ3K6o,12640
151
+ aiq/front_ends/fastapi/message_handler.py,sha256=6511eexUf53h5YKi9Zz6ERP2kCpl9NSAN2ZmDbKNFb4,12769
152
152
  aiq/front_ends/fastapi/message_validator.py,sha256=NqjeIG0InGAS6yooEnTaYwjfy3qtQHNgmdJ4zZlxgSQ,17407
153
153
  aiq/front_ends/fastapi/register.py,sha256=-Vr6HEDy7L1IIBQZy6VFKZWWKYNtSI-cxk3l4ZPPLko,1159
154
154
  aiq/front_ends/fastapi/response_helpers.py,sha256=JnOOvurlkhh6akpzkKDNh1xCi5ClQTePyW_ScEY1pLo,9111
155
155
  aiq/front_ends/fastapi/step_adaptor.py,sha256=2ps136GzZ7EFgNrN0rPCUSJllvO-GNZPtADrGYseCNc,12551
156
- aiq/front_ends/fastapi/websocket.py,sha256=upRuFSceWRZcjBcjWG7l6Tl6fxY4NnMroSq372bdkpw,6569
156
+ aiq/front_ends/fastapi/websocket.py,sha256=a7at8v7Yg_c-KVrdahU920tLYxZIWpSLeSjFdU0VSVI,7042
157
157
  aiq/front_ends/mcp/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
158
158
  aiq/front_ends/mcp/mcp_front_end_config.py,sha256=Mp2mgCh1pJkegih5DEJ3t0OKEiCiCg8-rM5vnLpLS6U,1470
159
159
  aiq/front_ends/mcp/mcp_front_end_plugin.py,sha256=XXyu5A5zWLH-eZgLDGcdCELXkwC1YPb94z6wddadH8I,3677
@@ -248,8 +248,8 @@ aiq/retriever/nemo_retriever/retriever.py,sha256=IvScUr9XuDLiMR__I3QsboLaM52N5D5
248
248
  aiq/runtime/__init__.py,sha256=Xs1JQ16L9btwreh4pdGKwskffAw1YFO48jKrU4ib_7c,685
249
249
  aiq/runtime/loader.py,sha256=4K96mko9BfSEdYg2cLZ6a5G8j-6PAkl6JSigSOshg1A,6823
250
250
  aiq/runtime/runner.py,sha256=WUAiliqI5Se9OgRmimpeFdrl38d9gRTJQ8uf59lvk7U,5836
251
- aiq/runtime/session.py,sha256=Hd92_MjYkPNdjbuoxQVV5EOJ0d_X2re449O6XHDlJZI,5039
252
- aiq/runtime/user_metadata.py,sha256=d7K5CFdOvaXpP2NCUIFBY2lHxB1FnjqV4yOlT4C7fuU,3697
251
+ aiq/runtime/session.py,sha256=A7o3uPRznRQMfVX3LID6R30D3COTkMIQQOX6UGfk4BA,5410
252
+ aiq/runtime/user_metadata.py,sha256=9EiBc-EEJzOdpf3Q1obHqAdY_kRlJ1T0TVvY0Jonk6o,3692
253
253
  aiq/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
254
254
  aiq/settings/global_settings.py,sha256=Utm7GEiZTYTBZsxJt2TLp4bNWWMscU4b47MAEJehIrU,12036
255
255
  aiq/test/.namespace,sha256=Gace0pOC3ETEJf-TBVuNw0TQV6J_KtOPpEiSzMH-odo,215
@@ -259,7 +259,7 @@ aiq/tool/document_search.py,sha256=w3D3r5ZBS2jYmVAZZ7lC7xCoi25bA1RePoFjjlV1Zog,6
259
259
  aiq/tool/nvidia_rag.py,sha256=9mS3igONo1RywxXNj_ITh2-qD91x1R0f7uhOWMZQX3o,4178
260
260
  aiq/tool/register.py,sha256=l9TbCf9T7IXvvXCidzjYPDygBx_E5as5okN2kIZtieE,1461
261
261
  aiq/tool/retriever.py,sha256=DnuU4khpJkd4epDBGQsowDOqDBKFiLQrnyKXgU6IRW8,3724
262
- aiq/tool/server_tools.py,sha256=e_HCYleB64KqAzT7HZ-i__mZ3QsNXEZzBTGtDOYMLvw,3063
262
+ aiq/tool/server_tools.py,sha256=AiopRoJx0IztsHPGfsDywfecKYAMGSKPYJCYNYS1RtU,3186
263
263
  aiq/tool/code_execution/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
264
264
  aiq/tool/code_execution/code_sandbox.py,sha256=ha0IVHmWsEp0U5A0XywG6hp42pFdj5esM19CRS94_30,5986
265
265
  aiq/tool/code_execution/register.py,sha256=H-4eZwu6f5jANEBnyONcDdeBrivkHjw-aZU-V7CLMRs,3143
@@ -309,10 +309,10 @@ aiq/utils/reactive/base/observer_base.py,sha256=UAlyAY_ky4q2t0P81RVFo2Bs_R7z5Nde
309
309
  aiq/utils/reactive/base/subject_base.py,sha256=Ed-AC6P7cT3qkW1EXjzbd5M9WpVoeN_9KCe3OM3FLU4,2521
310
310
  aiq/utils/settings/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
311
311
  aiq/utils/settings/global_settings.py,sha256=U9TCLdoZsKq5qOVGjREipGVv9e-FlStzqy5zv82_VYk,7454
312
- aiqtoolkit-1.2.0a20250617.dist-info/licenses/LICENSE-3rd-party.txt,sha256=8o7aySJa9CBvFshPcsRdJbczzdNyDGJ8b0J67WRUQ2k,183936
313
- aiqtoolkit-1.2.0a20250617.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
314
- aiqtoolkit-1.2.0a20250617.dist-info/METADATA,sha256=7U1QTdteJlIPEhjypLhDj_VsNOp3dcGC5GyK4sPecD8,20274
315
- aiqtoolkit-1.2.0a20250617.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
316
- aiqtoolkit-1.2.0a20250617.dist-info/entry_points.txt,sha256=gRlPfR5g21t328WNEQ4CcEz80S1sJNS8A7rMDYnzl4A,452
317
- aiqtoolkit-1.2.0a20250617.dist-info/top_level.txt,sha256=fo7AzYcNhZ_tRWrhGumtxwnxMew4xrT1iwouDy_f0Kc,4
318
- aiqtoolkit-1.2.0a20250617.dist-info/RECORD,,
312
+ aiqtoolkit-1.2.0a20250618.dist-info/licenses/LICENSE-3rd-party.txt,sha256=8o7aySJa9CBvFshPcsRdJbczzdNyDGJ8b0J67WRUQ2k,183936
313
+ aiqtoolkit-1.2.0a20250618.dist-info/licenses/LICENSE.md,sha256=QwcOLU5TJoTeUhuIXzhdCEEDDvorGiC6-3YTOl4TecE,11356
314
+ aiqtoolkit-1.2.0a20250618.dist-info/METADATA,sha256=jVXfiZS96SmSPFu4lK1gpcF3ZdTCuujLw08gmCtGGSw,20274
315
+ aiqtoolkit-1.2.0a20250618.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
316
+ aiqtoolkit-1.2.0a20250618.dist-info/entry_points.txt,sha256=gRlPfR5g21t328WNEQ4CcEz80S1sJNS8A7rMDYnzl4A,452
317
+ aiqtoolkit-1.2.0a20250618.dist-info/top_level.txt,sha256=fo7AzYcNhZ_tRWrhGumtxwnxMew4xrT1iwouDy_f0Kc,4
318
+ aiqtoolkit-1.2.0a20250618.dist-info/RECORD,,