vectorvein 0.1.81__tar.gz → 0.1.83__tar.gz
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.
- {vectorvein-0.1.81 → vectorvein-0.1.83}/PKG-INFO +1 -1
- {vectorvein-0.1.81 → vectorvein-0.1.83}/pyproject.toml +1 -1
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/openai_compatible_client.py +120 -12
- {vectorvein-0.1.81 → vectorvein-0.1.83}/README.md +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/__init__.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/__init__.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/anthropic_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/baichuan_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/base_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/deepseek_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/gemini_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/groq_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/local_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/minimax_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/mistral_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/moonshot_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/openai_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/py.typed +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/qwen_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/stepfun_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/utils.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/xai_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/yi_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/zhipuai_client.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/py.typed +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/server/token_server.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/settings/__init__.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/settings/py.typed +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/types/defaults.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/types/enums.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/types/exception.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/types/llm_parameters.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/types/py.typed +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/utilities/media_processing.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/utilities/retry.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/graph/edge.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/graph/node.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/graph/port.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/graph/workflow.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/__init__.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/audio_generation.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/control_flows.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/file_processing.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/image_generation.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/llms.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/media_editing.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/media_processing.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/output.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/relational_db.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/text_processing.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/tools.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/triggers.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/vector_db.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/video_generation.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/nodes/web_crawlers.py +0 -0
- {vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/workflow/utils/json_to_code.py +0 -0
{vectorvein-0.1.81 → vectorvein-0.1.83}/src/vectorvein/chat_clients/openai_compatible_client.py
RENAMED
@@ -3,6 +3,7 @@
|
|
3
3
|
import json
|
4
4
|
from functools import cached_property
|
5
5
|
from typing import overload, Generator, AsyncGenerator, Any, Literal, Iterable
|
6
|
+
import re
|
6
7
|
|
7
8
|
import httpx
|
8
9
|
from openai import OpenAI, AsyncOpenAI, AzureOpenAI, AsyncAzureOpenAI
|
@@ -229,6 +230,11 @@ class OpenAICompatibleChatClient(BaseChatClient):
|
|
229
230
|
full_content = ""
|
230
231
|
result = {}
|
231
232
|
usage = None
|
233
|
+
buffer = ""
|
234
|
+
in_reasoning = False
|
235
|
+
current_reasoning = []
|
236
|
+
current_content = []
|
237
|
+
|
232
238
|
for chunk in stream_response:
|
233
239
|
if chunk.usage and chunk.usage.total_tokens:
|
234
240
|
usage = Usage(
|
@@ -239,14 +245,11 @@ class OpenAICompatibleChatClient(BaseChatClient):
|
|
239
245
|
completion_tokens_details=chunk.usage.completion_tokens_details,
|
240
246
|
)
|
241
247
|
|
242
|
-
if len(chunk.choices) == 0:
|
243
|
-
if usage:
|
244
|
-
yield ChatCompletionDeltaMessage(usage=usage)
|
245
|
-
continue
|
246
|
-
if not chunk.choices[0].delta:
|
248
|
+
if len(chunk.choices) == 0 or not chunk.choices[0].delta:
|
247
249
|
if usage:
|
248
250
|
yield ChatCompletionDeltaMessage(usage=usage)
|
249
251
|
continue
|
252
|
+
|
250
253
|
if self.model_setting.function_call_available:
|
251
254
|
if chunk.choices[0].delta.tool_calls:
|
252
255
|
for index, tool_call in enumerate(chunk.choices[0].delta.tool_calls):
|
@@ -254,16 +257,61 @@ class OpenAICompatibleChatClient(BaseChatClient):
|
|
254
257
|
yield ChatCompletionDeltaMessage(**chunk.choices[0].delta.model_dump(), usage=usage)
|
255
258
|
else:
|
256
259
|
message = chunk.choices[0].delta.model_dump()
|
257
|
-
|
260
|
+
delta_content = message.get("content", "")
|
261
|
+
buffer += delta_content or ""
|
262
|
+
|
263
|
+
while True:
|
264
|
+
if not in_reasoning:
|
265
|
+
start_pos = buffer.find("<think>")
|
266
|
+
if start_pos != -1:
|
267
|
+
current_content.append(buffer[:start_pos])
|
268
|
+
buffer = buffer[start_pos + 7 :]
|
269
|
+
in_reasoning = True
|
270
|
+
else:
|
271
|
+
current_content.append(buffer)
|
272
|
+
buffer = ""
|
273
|
+
break
|
274
|
+
else:
|
275
|
+
end_pos = buffer.find("</think>")
|
276
|
+
if end_pos != -1:
|
277
|
+
current_reasoning.append(buffer[:end_pos])
|
278
|
+
buffer = buffer[end_pos + 8 :]
|
279
|
+
in_reasoning = False
|
280
|
+
else:
|
281
|
+
current_reasoning.append(buffer)
|
282
|
+
buffer = ""
|
283
|
+
break
|
284
|
+
|
285
|
+
message["content"] = "".join(current_content).strip()
|
286
|
+
if current_reasoning:
|
287
|
+
message["reasoning_content"] = "".join(current_reasoning).strip()
|
288
|
+
current_content.clear()
|
289
|
+
current_reasoning.clear()
|
290
|
+
|
258
291
|
if tools:
|
292
|
+
full_content += message["content"]
|
259
293
|
tool_call_data = ToolCallContentProcessor(full_content).tool_calls
|
260
294
|
if tool_call_data:
|
261
295
|
message["tool_calls"] = tool_call_data["tool_calls"]
|
296
|
+
|
262
297
|
if full_content in ("<", "<|", "<|▶", "<|▶|") or full_content.startswith("<|▶|>"):
|
263
298
|
message["content"] = ""
|
264
299
|
result = message
|
265
300
|
continue
|
301
|
+
|
266
302
|
yield ChatCompletionDeltaMessage(**message, usage=usage)
|
303
|
+
|
304
|
+
if buffer:
|
305
|
+
if in_reasoning:
|
306
|
+
current_reasoning.append(buffer)
|
307
|
+
else:
|
308
|
+
current_content.append(buffer)
|
309
|
+
final_message = {
|
310
|
+
"content": "".join(current_content).strip(),
|
311
|
+
"reasoning_content": "".join(current_reasoning).strip() if current_reasoning else None,
|
312
|
+
}
|
313
|
+
yield ChatCompletionDeltaMessage(**final_message, usage=usage)
|
314
|
+
|
267
315
|
if result:
|
268
316
|
yield ChatCompletionDeltaMessage(**result, usage=usage)
|
269
317
|
|
@@ -286,6 +334,13 @@ class OpenAICompatibleChatClient(BaseChatClient):
|
|
286
334
|
"reasoning_content": getattr(response.choices[0].message, "reasoning_content", None),
|
287
335
|
"usage": response.usage.model_dump() if response.usage else None,
|
288
336
|
}
|
337
|
+
|
338
|
+
if not result["reasoning_content"] and result["content"]:
|
339
|
+
think_match = re.search(r"<think>(.*?)</think>", result["content"], re.DOTALL)
|
340
|
+
if think_match:
|
341
|
+
result["reasoning_content"] = think_match.group(1).strip()
|
342
|
+
result["content"] = result["content"].replace(think_match.group(0), "", 1).strip()
|
343
|
+
|
289
344
|
if tools:
|
290
345
|
if self.model_setting.function_call_available and response.choices[0].message.tool_calls:
|
291
346
|
result["tool_calls"] = [
|
@@ -501,6 +556,11 @@ class AsyncOpenAICompatibleChatClient(BaseAsyncChatClient):
|
|
501
556
|
full_content = ""
|
502
557
|
result = {}
|
503
558
|
usage = None
|
559
|
+
buffer = ""
|
560
|
+
in_reasoning = False
|
561
|
+
current_reasoning = []
|
562
|
+
current_content = []
|
563
|
+
|
504
564
|
async for chunk in stream_response:
|
505
565
|
if chunk.usage and chunk.usage.total_tokens:
|
506
566
|
usage = Usage(
|
@@ -511,11 +571,7 @@ class AsyncOpenAICompatibleChatClient(BaseAsyncChatClient):
|
|
511
571
|
prompt_tokens_details=chunk.usage.prompt_tokens_details,
|
512
572
|
)
|
513
573
|
|
514
|
-
if len(chunk.choices) == 0:
|
515
|
-
if usage:
|
516
|
-
yield ChatCompletionDeltaMessage(usage=usage)
|
517
|
-
continue
|
518
|
-
if not chunk.choices[0].delta:
|
574
|
+
if len(chunk.choices) == 0 or not chunk.choices[0].delta:
|
519
575
|
if usage:
|
520
576
|
yield ChatCompletionDeltaMessage(usage=usage)
|
521
577
|
continue
|
@@ -527,16 +583,61 @@ class AsyncOpenAICompatibleChatClient(BaseAsyncChatClient):
|
|
527
583
|
yield ChatCompletionDeltaMessage(**chunk.choices[0].delta.model_dump(), usage=usage)
|
528
584
|
else:
|
529
585
|
message = chunk.choices[0].delta.model_dump()
|
530
|
-
|
586
|
+
delta_content = message.get("content", "")
|
587
|
+
buffer += delta_content or ""
|
588
|
+
|
589
|
+
while True:
|
590
|
+
if not in_reasoning:
|
591
|
+
start_pos = buffer.find("<think>")
|
592
|
+
if start_pos != -1:
|
593
|
+
current_content.append(buffer[:start_pos])
|
594
|
+
buffer = buffer[start_pos + 7 :]
|
595
|
+
in_reasoning = True
|
596
|
+
else:
|
597
|
+
current_content.append(buffer)
|
598
|
+
buffer = ""
|
599
|
+
break
|
600
|
+
else:
|
601
|
+
end_pos = buffer.find("</think>")
|
602
|
+
if end_pos != -1:
|
603
|
+
current_reasoning.append(buffer[:end_pos])
|
604
|
+
buffer = buffer[end_pos + 8 :]
|
605
|
+
in_reasoning = False
|
606
|
+
else:
|
607
|
+
current_reasoning.append(buffer)
|
608
|
+
buffer = ""
|
609
|
+
break
|
610
|
+
|
611
|
+
message["content"] = "".join(current_content).strip()
|
612
|
+
if current_reasoning:
|
613
|
+
message["reasoning_content"] = "".join(current_reasoning).strip()
|
614
|
+
current_content.clear()
|
615
|
+
current_reasoning.clear()
|
616
|
+
|
531
617
|
if tools:
|
618
|
+
full_content += message["content"]
|
532
619
|
tool_call_data = ToolCallContentProcessor(full_content).tool_calls
|
533
620
|
if tool_call_data:
|
534
621
|
message["tool_calls"] = tool_call_data["tool_calls"]
|
622
|
+
|
535
623
|
if full_content in ("<", "<|", "<|▶", "<|▶|") or full_content.startswith("<|▶|>"):
|
536
624
|
message["content"] = ""
|
537
625
|
result = message
|
538
626
|
continue
|
627
|
+
|
539
628
|
yield ChatCompletionDeltaMessage(**message, usage=usage)
|
629
|
+
|
630
|
+
if buffer:
|
631
|
+
if in_reasoning:
|
632
|
+
current_reasoning.append(buffer)
|
633
|
+
else:
|
634
|
+
current_content.append(buffer)
|
635
|
+
final_message = {
|
636
|
+
"content": "".join(current_content).strip(),
|
637
|
+
"reasoning_content": "".join(current_reasoning).strip() if current_reasoning else None,
|
638
|
+
}
|
639
|
+
yield ChatCompletionDeltaMessage(**final_message, usage=usage)
|
640
|
+
|
540
641
|
if result:
|
541
642
|
yield ChatCompletionDeltaMessage(**result, usage=usage)
|
542
643
|
|
@@ -558,6 +659,13 @@ class AsyncOpenAICompatibleChatClient(BaseAsyncChatClient):
|
|
558
659
|
"reasoning_content": getattr(response.choices[0].message, "reasoning_content", None),
|
559
660
|
"usage": response.usage.model_dump() if response.usage else None,
|
560
661
|
}
|
662
|
+
|
663
|
+
if not result["reasoning_content"] and result["content"]:
|
664
|
+
think_match = re.search(r"<think>(.*?)</think>", result["content"], re.DOTALL)
|
665
|
+
if think_match:
|
666
|
+
result["reasoning_content"] = think_match.group(1).strip()
|
667
|
+
result["content"] = result["content"].replace(think_match.group(0), "", 1).strip()
|
668
|
+
|
561
669
|
if tools:
|
562
670
|
if self.model_setting.function_call_available and response.choices[0].message.tool_calls:
|
563
671
|
result["tool_calls"] = [
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|