yaicli 0.6.2__py3-none-any.whl → 0.6.4__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.
- pyproject.toml +23 -3
- yaicli/cli.py +2 -9
- yaicli/config.py +1 -1
- yaicli/const.py +1 -1
- yaicli/llms/__init__.py +0 -9
- yaicli/llms/provider.py +5 -0
- yaicli/llms/providers/chatglm_provider.py +9 -5
- yaicli/llms/providers/cohere_provider.py +6 -3
- yaicli/llms/providers/deepseek_provider.py +2 -1
- yaicli/llms/providers/gemini_provider.py +193 -0
- yaicli/llms/providers/huggingface_provider.py +40 -0
- yaicli/llms/providers/infiniai_provider.py +4 -2
- yaicli/llms/providers/modelscope_provider.py +2 -1
- yaicli/llms/providers/openai_provider.py +17 -10
- yaicli/llms/providers/siliconflow_provider.py +2 -1
- yaicli/llms/providers/vertexai_provider.py +18 -0
- {yaicli-0.6.2.dist-info → yaicli-0.6.4.dist-info}/METADATA +147 -19
- {yaicli-0.6.2.dist-info → yaicli-0.6.4.dist-info}/RECORD +21 -18
- {yaicli-0.6.2.dist-info → yaicli-0.6.4.dist-info}/WHEEL +0 -0
- {yaicli-0.6.2.dist-info → yaicli-0.6.4.dist-info}/entry_points.txt +0 -0
- {yaicli-0.6.2.dist-info → yaicli-0.6.4.dist-info}/licenses/LICENSE +0 -0
pyproject.toml
CHANGED
@@ -1,10 +1,10 @@
|
|
1
1
|
[project]
|
2
2
|
name = "yaicli"
|
3
|
-
version = "0.6.
|
3
|
+
version = "0.6.4"
|
4
4
|
description = "A simple CLI tool to interact with LLM"
|
5
5
|
authors = [{ name = "belingud", email = "im.victor@qq.com" }]
|
6
6
|
readme = "README.md"
|
7
|
-
requires-python = ">=3.
|
7
|
+
requires-python = ">=3.10"
|
8
8
|
license = { file = "LICENSE" }
|
9
9
|
classifiers = [
|
10
10
|
"Programming Language :: Python :: 3",
|
@@ -42,6 +42,15 @@ keywords = [
|
|
42
42
|
"anthropic",
|
43
43
|
"groq",
|
44
44
|
"cohere",
|
45
|
+
"huggingface",
|
46
|
+
"chatglm",
|
47
|
+
"sambanova",
|
48
|
+
"siliconflow",
|
49
|
+
"xai",
|
50
|
+
"vertexai",
|
51
|
+
"deepseek",
|
52
|
+
"modelscope",
|
53
|
+
"ollama",
|
45
54
|
]
|
46
55
|
dependencies = [
|
47
56
|
"click>=8.1.8",
|
@@ -65,10 +74,20 @@ ai = "yaicli.entry:app"
|
|
65
74
|
yaicli = "yaicli.entry:app"
|
66
75
|
|
67
76
|
[project.optional-dependencies]
|
77
|
+
all = [
|
78
|
+
"volcengine-python-sdk>=3.0.15",
|
79
|
+
"ollama>=0.5.1",
|
80
|
+
"cohere>=5.15.0",
|
81
|
+
"google-genai>=1.20.0",
|
82
|
+
"huggingface-hub>=0.33.0",
|
83
|
+
]
|
68
84
|
doubao = ["volcengine-python-sdk>=3.0.15"]
|
69
85
|
ollama = ["ollama>=0.5.1"]
|
70
86
|
cohere = ["cohere>=5.15.0"]
|
71
|
-
|
87
|
+
gemini = ["google-genai>=1.20.0"]
|
88
|
+
huggingface = [
|
89
|
+
"huggingface-hub>=0.33.0",
|
90
|
+
]
|
72
91
|
|
73
92
|
[tool.pytest.ini_options]
|
74
93
|
testpaths = ["tests"]
|
@@ -91,6 +110,7 @@ dev = [
|
|
91
110
|
"pytest>=8.3.5",
|
92
111
|
"pytest-cov>=6.1.1",
|
93
112
|
"ruff>=0.11.2",
|
113
|
+
"tox>=4.27.0",
|
94
114
|
]
|
95
115
|
|
96
116
|
[tool.isort]
|
yaicli/cli.py
CHANGED
@@ -267,7 +267,7 @@ class CLI:
|
|
267
267
|
assistant_msg = self.chat.history[i + 1] if (i + 1) < len(self.chat.history) else None
|
268
268
|
self.console.print(f"[dim]{i // 2 + 1}[/dim] [bold blue]User:[/bold blue] {user_msg.content}")
|
269
269
|
if assistant_msg:
|
270
|
-
md = Markdown(assistant_msg.content, code_theme=cfg["CODE_THEME"])
|
270
|
+
md = Markdown(assistant_msg.content or "", code_theme=cfg["CODE_THEME"])
|
271
271
|
padded_md = Padding(md, (0, 0, 0, 4))
|
272
272
|
self.console.print(" Assistant:", style="bold green")
|
273
273
|
self.console.print(padded_md)
|
@@ -384,14 +384,7 @@ class CLI:
|
|
384
384
|
self._check_history_len()
|
385
385
|
|
386
386
|
if self.current_mode == EXEC_MODE:
|
387
|
-
|
388
|
-
# in case of tool use.
|
389
|
-
final_content = ""
|
390
|
-
if self.chat.history:
|
391
|
-
last_message = self.chat.history[-1]
|
392
|
-
if last_message.role == "assistant":
|
393
|
-
final_content = last_message.content or ""
|
394
|
-
self._confirm_and_execute(final_content)
|
387
|
+
self._confirm_and_execute(content or "")
|
395
388
|
return True
|
396
389
|
|
397
390
|
def _confirm_and_execute(self, raw_content: str) -> None:
|
yaicli/config.py
CHANGED
@@ -142,7 +142,7 @@ class Config(dict):
|
|
142
142
|
if target_type is bool:
|
143
143
|
converted_value = str2bool(raw_value)
|
144
144
|
elif target_type in (int, float, str):
|
145
|
-
converted_value = target_type(raw_value)
|
145
|
+
converted_value = target_type(raw_value) if raw_value else raw_value
|
146
146
|
elif target_type is dict and raw_value:
|
147
147
|
converted_value = json.loads(raw_value)
|
148
148
|
except (ValueError, TypeError, json.JSONDecodeError) as e:
|
yaicli/const.py
CHANGED
yaicli/llms/__init__.py
CHANGED
@@ -1,13 +1,4 @@
|
|
1
|
-
from ..config import cfg
|
2
1
|
from .client import LLMClient
|
3
2
|
from .provider import Provider, ProviderFactory
|
4
3
|
|
5
4
|
__all__ = ["LLMClient", "Provider", "ProviderFactory"]
|
6
|
-
|
7
|
-
|
8
|
-
class BaseProvider:
|
9
|
-
def __init__(self) -> None:
|
10
|
-
self.api_key = cfg["API_KEY"]
|
11
|
-
self.model = cfg["MODEL"]
|
12
|
-
self.base_url = cfg["BASE_URL"]
|
13
|
-
self.timeout = cfg["TIMEOUT"]
|
yaicli/llms/provider.py
CHANGED
@@ -43,9 +43,13 @@ class ProviderFactory:
|
|
43
43
|
"chatglm": (".providers.chatglm_provider", "ChatglmProvider"),
|
44
44
|
"chutes": (".providers.chutes_provider", "ChutesProvider"),
|
45
45
|
"cohere": (".providers.cohere_provider", "CohereProvider"),
|
46
|
+
"cohere-bedrock": (".providers.cohere_provider", "CohereBadrockProvider"),
|
47
|
+
"cohere-sagemaker": (".providers.cohere_provider", "CohereSagemakerProvider"),
|
46
48
|
"deepseek": (".providers.deepseek_provider", "DeepSeekProvider"),
|
47
49
|
"doubao": (".providers.doubao_provider", "DoubaoProvider"),
|
50
|
+
"gemini": (".providers.gemini_provider", "GeminiProvider"),
|
48
51
|
"groq": (".providers.groq_provider", "GroqProvider"),
|
52
|
+
"huggingface": (".providers.huggingface_provider", "HuggingFaceProvider"),
|
49
53
|
"infini-ai": (".providers.infiniai_provider", "InfiniAIProvider"),
|
50
54
|
"minimax": (".providers.minimax_provider", "MinimaxProvider"),
|
51
55
|
"modelscope": (".providers.modelscope_provider", "ModelScopeProvider"),
|
@@ -55,6 +59,7 @@ class ProviderFactory:
|
|
55
59
|
"sambanova": (".providers.sambanova_provider", "SambanovaProvider"),
|
56
60
|
"siliconflow": (".providers.siliconflow_provider", "SiliconFlowProvider"),
|
57
61
|
"targon": (".providers.targon_provider", "TargonProvider"),
|
62
|
+
"vertexai": (".providers.vertexai_provider", "VertexAIProvider"),
|
58
63
|
"xai": (".providers.xai_provider", "XaiProvider"),
|
59
64
|
"yi": (".providers.yi_provider", "YiProvider"),
|
60
65
|
}
|
@@ -1,5 +1,5 @@
|
|
1
1
|
import json
|
2
|
-
from typing import
|
2
|
+
from typing import Generator, Optional
|
3
3
|
|
4
4
|
from openai._streaming import Stream
|
5
5
|
from openai.types.chat.chat_completion import ChatCompletion, Choice
|
@@ -14,10 +14,14 @@ class ChatglmProvider(OpenAIProvider):
|
|
14
14
|
|
15
15
|
DEFAULT_BASE_URL = "https://open.bigmodel.cn/api/paas/v4/"
|
16
16
|
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
17
|
+
COMPLETION_PARAMS_KEYS = {
|
18
|
+
"model": "MODEL",
|
19
|
+
"temperature": "TEMPERATURE",
|
20
|
+
"top_p": "TOP_P",
|
21
|
+
"max_tokens": "MAX_TOKENS",
|
22
|
+
"do_sample": "DO_SAMPLE",
|
23
|
+
"extra_body": "EXTRA_BODY",
|
24
|
+
}
|
21
25
|
|
22
26
|
def _handle_normal_response(self, response: ChatCompletion) -> Generator[LLMResponse, None, None]:
|
23
27
|
"""Handle normal (non-streaming) response
|
@@ -10,7 +10,8 @@ This module implements Cohere provider classes for different deployment options:
|
|
10
10
|
from typing import Any, Dict, Generator, List, Optional
|
11
11
|
|
12
12
|
from cohere import BedrockClientV2, ClientV2, SagemakerClientV2
|
13
|
-
from cohere.types.tool_call_v2 import ToolCallV2
|
13
|
+
from cohere.types.tool_call_v2 import ToolCallV2
|
14
|
+
from cohere.types.tool_call_v2function import ToolCallV2Function
|
14
15
|
|
15
16
|
from ...config import cfg
|
16
17
|
from ...console import get_console
|
@@ -179,7 +180,9 @@ class CohereProvider(Provider):
|
|
179
180
|
continue
|
180
181
|
elif chunk.type == "tool-call-delta":
|
181
182
|
# Tool call arguments being generated: cohere.types.chat_tool_call_delta_event_delta_message.ChatToolCallDeltaEventDeltaMessage
|
182
|
-
|
183
|
+
if not tool_call:
|
184
|
+
continue
|
185
|
+
tool_call.arguments += chunk.delta.message.tool_calls.function.arguments or ""
|
183
186
|
# Waiting for tool-call-end event
|
184
187
|
continue
|
185
188
|
|
@@ -292,7 +295,7 @@ class CohereBadrockProvider(CohereProvider):
|
|
292
295
|
return self.CLIENT_CLS(**self.client_params)
|
293
296
|
|
294
297
|
|
295
|
-
class
|
298
|
+
class CohereSagemakerProvider(CohereBadrockProvider):
|
296
299
|
"""Cohere provider for AWS Sagemaker integration"""
|
297
300
|
|
298
301
|
CLIENT_CLS = SagemakerClientV2
|
@@ -10,5 +10,6 @@ class DeepSeekProvider(OpenAIProvider):
|
|
10
10
|
|
11
11
|
def get_completion_params(self) -> Dict[str, Any]:
|
12
12
|
params = super().get_completion_params()
|
13
|
-
|
13
|
+
if "max_completion_tokens" in params:
|
14
|
+
params["max_tokens"] = params.pop("max_completion_tokens")
|
14
15
|
return params
|
@@ -0,0 +1,193 @@
|
|
1
|
+
import json
|
2
|
+
from functools import wraps
|
3
|
+
from typing import Any, Callable, Dict, Generator, List
|
4
|
+
|
5
|
+
import google.genai as genai
|
6
|
+
from google.genai import types
|
7
|
+
|
8
|
+
from ...config import cfg
|
9
|
+
from ...console import get_console
|
10
|
+
from ...schemas import ChatMessage, LLMResponse
|
11
|
+
from ...tools import get_func_name_map
|
12
|
+
from ..provider import Provider
|
13
|
+
|
14
|
+
|
15
|
+
def wrap_function(func):
|
16
|
+
@wraps(func)
|
17
|
+
def wrapper(*args, **kwargs):
|
18
|
+
return func(*args, **kwargs)
|
19
|
+
|
20
|
+
return wrapper
|
21
|
+
|
22
|
+
|
23
|
+
class GeminiProvider(Provider):
|
24
|
+
"""Gemini provider implementation based on google-genai library"""
|
25
|
+
|
26
|
+
DEFAULT_BASE_URL = "https://generativelanguage.googleapis.com/v1beta"
|
27
|
+
|
28
|
+
def __init__(self, config: dict = cfg, verbose: bool = False, **kwargs):
|
29
|
+
self.config = config
|
30
|
+
self.enable_function = self.config["ENABLE_FUNCTIONS"]
|
31
|
+
self.verbose = verbose
|
32
|
+
|
33
|
+
# Initialize client
|
34
|
+
self.client_params = self.get_client_params()
|
35
|
+
self.client = genai.Client(**self.client_params)
|
36
|
+
self.console = get_console()
|
37
|
+
|
38
|
+
def get_client_params(self) -> Dict[str, Any]:
|
39
|
+
"""Get the client parameters"""
|
40
|
+
# Initialize client params
|
41
|
+
return {
|
42
|
+
"api_key": self.config["API_KEY"],
|
43
|
+
}
|
44
|
+
|
45
|
+
def get_chat_config(self):
|
46
|
+
http_options_map = {
|
47
|
+
"timeout": self.config["TIMEOUT"] * 1000, # Timeout for the request in milliseconds.
|
48
|
+
"headers": {**self.config["EXTRA_HEADERS"], "X-Client": self.APP_NAME, "Referer": self.APP_REFERER},
|
49
|
+
}
|
50
|
+
if self.config.get("BASE_URL"):
|
51
|
+
http_options_map["base_url"] = self.config["BASE_URL"]
|
52
|
+
if self.config.get("API_VERSION"):
|
53
|
+
# Specifies the version of the API to use.
|
54
|
+
http_options_map["api_version"] = self.config["API_VERSION"]
|
55
|
+
http_options = types.HttpOptions(**http_options_map)
|
56
|
+
config_map = {
|
57
|
+
"max_output_tokens": self.config["MAX_TOKENS"],
|
58
|
+
"temperature": self.config["TEMPERATURE"],
|
59
|
+
"top_p": self.config["TOP_P"],
|
60
|
+
"http_options": http_options,
|
61
|
+
}
|
62
|
+
if self.config.get("TOP_K"):
|
63
|
+
config_map["top_k"] = self.config["TOP_K"]
|
64
|
+
if self.config.get("PRESENCE_PENALTY"):
|
65
|
+
config_map["presence_penalty"] = self.config["PRESENCE_PENALTY"]
|
66
|
+
if self.config.get("FREQUENCY_PENALTY"):
|
67
|
+
config_map["frequency_penalty"] = self.config["FREQUENCY_PENALTY"]
|
68
|
+
if self.config.get("SEED"):
|
69
|
+
config_map["seed"] = self.config["SEED"]
|
70
|
+
# Indicates whether to include thoughts in the response. If true, thoughts are returned only if the model supports thought and thoughts are available.
|
71
|
+
thinking_config_map = {"include_thoughts": self.config.get("INCLUDE_THOUGHTS", True)}
|
72
|
+
if self.config.get("THINKING_BUDGET"):
|
73
|
+
thinking_config_map["thinking_budget"] = int(self.config["THINKING_BUDGET"])
|
74
|
+
config_map["thinking_config"] = types.ThinkingConfig(**thinking_config_map)
|
75
|
+
config = types.GenerateContentConfig(**config_map)
|
76
|
+
if self.enable_function:
|
77
|
+
# TODO: support disable automatic function calling
|
78
|
+
# config.automatic_function_calling = types.AutomaticFunctionCallingConfig(disable=False)
|
79
|
+
config.tools = self.gen_gemini_functions()
|
80
|
+
return config
|
81
|
+
|
82
|
+
def _convert_messages(self, messages: List[ChatMessage]) -> List[types.Content]:
|
83
|
+
"""Convert a list of ChatMessage objects to a list of Gemini Content objects."""
|
84
|
+
converted_messages = []
|
85
|
+
for msg in messages:
|
86
|
+
if msg.role == "system":
|
87
|
+
continue
|
88
|
+
content = types.Content(role=self._map_role(msg.role), parts=[types.Part(text=msg.content)])
|
89
|
+
if msg.role == "tool":
|
90
|
+
content.role = "user"
|
91
|
+
content.parts = [
|
92
|
+
types.Part.from_function_response(name=msg.name or "", response={"result": msg.content})
|
93
|
+
]
|
94
|
+
converted_messages.append(content)
|
95
|
+
return converted_messages
|
96
|
+
|
97
|
+
def _map_role(self, role: str) -> str:
|
98
|
+
"""Map OpenAI roles to Gemini roles"""
|
99
|
+
# Gemini uses "user", "model" instead of "user", "assistant"
|
100
|
+
if role == "assistant":
|
101
|
+
return "model"
|
102
|
+
return role
|
103
|
+
|
104
|
+
def gen_gemini_functions(self) -> List[Callable[..., Any]]:
|
105
|
+
"""Wrap Gemini functions from OpenAI functions for automatic function calling"""
|
106
|
+
func_name_map = get_func_name_map()
|
107
|
+
if not func_name_map:
|
108
|
+
return []
|
109
|
+
funcs = []
|
110
|
+
for func_name, func in func_name_map.items():
|
111
|
+
wrapped_func = wrap_function(func.execute)
|
112
|
+
wrapped_func.__name__ = func_name
|
113
|
+
wrapped_func.__doc__ = func.__doc__
|
114
|
+
funcs.append(wrapped_func)
|
115
|
+
return funcs
|
116
|
+
|
117
|
+
def completion(
|
118
|
+
self,
|
119
|
+
messages: List[ChatMessage],
|
120
|
+
stream: bool = False,
|
121
|
+
) -> Generator[LLMResponse, None, None]:
|
122
|
+
"""
|
123
|
+
Send completion request to Gemini and return responses.
|
124
|
+
|
125
|
+
Args:
|
126
|
+
messages: List of chat messages to send
|
127
|
+
stream: Whether to stream the response
|
128
|
+
|
129
|
+
Yields:
|
130
|
+
LLMResponse: Response objects containing content, tool calls, etc.
|
131
|
+
|
132
|
+
Raises:
|
133
|
+
ValueError: If messages is empty or invalid
|
134
|
+
APIError: If API request fails
|
135
|
+
"""
|
136
|
+
gemini_messages = self._convert_messages(messages)
|
137
|
+
if self.verbose:
|
138
|
+
self.console.print("Messages:")
|
139
|
+
self.console.print(gemini_messages)
|
140
|
+
chat_config = self.get_chat_config()
|
141
|
+
chat_config.system_instruction = messages[0].content
|
142
|
+
chat = self.client.chats.create(model=self.config["MODEL"], history=gemini_messages, config=chat_config) # type: ignore
|
143
|
+
message = messages[-1].content
|
144
|
+
|
145
|
+
if stream:
|
146
|
+
response = chat.send_message_stream(message=message) # type: ignore
|
147
|
+
yield from self._handle_stream_response(response)
|
148
|
+
else:
|
149
|
+
response = chat.send_message(message=message) # type: ignore
|
150
|
+
yield from self._handle_normal_response(response)
|
151
|
+
|
152
|
+
def _handle_normal_response(self, response) -> Generator[LLMResponse, None, None]:
|
153
|
+
"""Handle normal (non-streaming) response"""
|
154
|
+
# TODO: support disable automatic function calling
|
155
|
+
if not response or not response.candidates:
|
156
|
+
yield LLMResponse(
|
157
|
+
content=json.dumps(response.to_json_dict()),
|
158
|
+
finish_reason="stop",
|
159
|
+
)
|
160
|
+
return
|
161
|
+
for part in response.candidates[0].content.parts:
|
162
|
+
if part.thought:
|
163
|
+
yield LLMResponse(reasoning=part.text, finish_reason="stop")
|
164
|
+
else:
|
165
|
+
yield LLMResponse(reasoning=None, content=part.text, finish_reason="stop")
|
166
|
+
|
167
|
+
def _handle_stream_response(self, response) -> Generator[LLMResponse, None, None]:
|
168
|
+
"""Handle streaming response from Gemini API"""
|
169
|
+
# Initialize tool call object to accumulate tool call data across chunks
|
170
|
+
# TODO: support disable automatic function calling
|
171
|
+
tool_call = None
|
172
|
+
for chunk in response:
|
173
|
+
if not chunk.candidates:
|
174
|
+
continue
|
175
|
+
candidate = chunk.candidates[0]
|
176
|
+
finish_reason = candidate.finish_reason
|
177
|
+
for part in chunk.candidates[0].content.parts:
|
178
|
+
if part.thought:
|
179
|
+
reasoning = part.text
|
180
|
+
content = None
|
181
|
+
else:
|
182
|
+
content = part.text
|
183
|
+
reasoning = None
|
184
|
+
yield LLMResponse(
|
185
|
+
reasoning=reasoning,
|
186
|
+
content=content or "",
|
187
|
+
tool_call=tool_call if finish_reason == "tool_calls" else None,
|
188
|
+
finish_reason=finish_reason or None,
|
189
|
+
)
|
190
|
+
|
191
|
+
def detect_tool_role(self) -> str:
|
192
|
+
"""Return the role that should be used for tool responses"""
|
193
|
+
return "user"
|
@@ -0,0 +1,40 @@
|
|
1
|
+
from typing import Any, Dict
|
2
|
+
|
3
|
+
from huggingface_hub import InferenceClient
|
4
|
+
|
5
|
+
from .chatglm_provider import ChatglmProvider
|
6
|
+
|
7
|
+
|
8
|
+
class HuggingFaceProvider(ChatglmProvider):
|
9
|
+
"""
|
10
|
+
HuggingFaceProvider is a provider for the HuggingFace API.
|
11
|
+
"""
|
12
|
+
|
13
|
+
CLIENT_CLS = InferenceClient
|
14
|
+
DEFAULT_PROVIDER = "hf-inference"
|
15
|
+
|
16
|
+
COMPLETION_PARAMS_KEYS = {
|
17
|
+
"model": "MODEL",
|
18
|
+
"temperature": "TEMPERATURE",
|
19
|
+
"top_p": "TOP_P",
|
20
|
+
"max_tokens": "MAX_TOKENS",
|
21
|
+
"extra_body": "EXTRA_BODY",
|
22
|
+
}
|
23
|
+
|
24
|
+
def get_client_params(self) -> Dict[str, Any]:
|
25
|
+
client_params = {
|
26
|
+
"api_key": self.config["API_KEY"],
|
27
|
+
"timeout": self.config["TIMEOUT"],
|
28
|
+
"provider": self.config.get("HF_PROVIDER") or self.DEFAULT_PROVIDER,
|
29
|
+
}
|
30
|
+
if self.config["BASE_URL"]:
|
31
|
+
client_params["base_url"] = self.config["BASE_URL"]
|
32
|
+
if self.config["EXTRA_HEADERS"]:
|
33
|
+
client_params["headers"] = {
|
34
|
+
**self.config["EXTRA_HEADERS"],
|
35
|
+
"X-Title": self.APP_NAME,
|
36
|
+
"HTTP-Referer": self.APP_REFERER,
|
37
|
+
}
|
38
|
+
if self.config.get("BILL_TO"):
|
39
|
+
client_params["bill_to"] = self.config["BILL_TO"]
|
40
|
+
return client_params
|
@@ -1,5 +1,6 @@
|
|
1
1
|
from typing import Any, Dict
|
2
2
|
|
3
|
+
from ...config import cfg
|
3
4
|
from .openai_provider import OpenAIProvider
|
4
5
|
|
5
6
|
|
@@ -8,7 +9,7 @@ class InfiniAIProvider(OpenAIProvider):
|
|
8
9
|
|
9
10
|
DEFAULT_BASE_URL = "https://cloud.infini-ai.com/maas/v1"
|
10
11
|
|
11
|
-
def __init__(self, config: dict =
|
12
|
+
def __init__(self, config: dict = cfg, **kwargs):
|
12
13
|
super().__init__(config, **kwargs)
|
13
14
|
if self.enable_function:
|
14
15
|
self.console.print("InfiniAI does not support functions, disabled", style="yellow")
|
@@ -16,5 +17,6 @@ class InfiniAIProvider(OpenAIProvider):
|
|
16
17
|
|
17
18
|
def get_completion_params(self) -> Dict[str, Any]:
|
18
19
|
params = super().get_completion_params()
|
19
|
-
|
20
|
+
if "max_completion_tokens" in params:
|
21
|
+
params["max_tokens"] = params.pop("max_completion_tokens")
|
20
22
|
return params
|
@@ -10,5 +10,6 @@ class ModelScopeProvider(OpenAIProvider):
|
|
10
10
|
|
11
11
|
def get_completion_params(self) -> Dict[str, Any]:
|
12
12
|
params = super().get_completion_params()
|
13
|
-
|
13
|
+
if "max_completion_tokens" in params:
|
14
|
+
params["max_tokens"] = params.pop("max_completion_tokens")
|
14
15
|
return params
|
@@ -19,7 +19,7 @@ class OpenAIProvider(Provider):
|
|
19
19
|
DEFAULT_BASE_URL = "https://api.openai.com/v1"
|
20
20
|
CLIENT_CLS = openai.OpenAI
|
21
21
|
# Base mapping between config keys and API parameter names
|
22
|
-
|
22
|
+
COMPLETION_PARAMS_KEYS = {
|
23
23
|
"model": "MODEL",
|
24
24
|
"temperature": "TEMPERATURE",
|
25
25
|
"top_p": "TOP_P",
|
@@ -69,7 +69,7 @@ class OpenAIProvider(Provider):
|
|
69
69
|
Returns:
|
70
70
|
Dict[str, str]: Mapping from API parameter names to config keys
|
71
71
|
"""
|
72
|
-
return self.
|
72
|
+
return self.COMPLETION_PARAMS_KEYS.copy()
|
73
73
|
|
74
74
|
def get_completion_params(self) -> Dict[str, Any]:
|
75
75
|
"""
|
@@ -81,7 +81,7 @@ class OpenAIProvider(Provider):
|
|
81
81
|
completion_params = {}
|
82
82
|
params_keys = self.get_completion_params_keys()
|
83
83
|
for api_key, config_key in params_keys.items():
|
84
|
-
if self.config.get(config_key, None) is not None:
|
84
|
+
if self.config.get(config_key, None) is not None and self.config[config_key] != "":
|
85
85
|
completion_params[api_key] = self.config[config_key]
|
86
86
|
return completion_params
|
87
87
|
|
@@ -89,7 +89,7 @@ class OpenAIProvider(Provider):
|
|
89
89
|
"""Convert a list of ChatMessage objects to a list of OpenAI message dicts."""
|
90
90
|
converted_messages = []
|
91
91
|
for msg in messages:
|
92
|
-
message = {"role": msg.role, "content": msg.content or ""}
|
92
|
+
message: Dict[str, Any] = {"role": msg.role, "content": msg.content or ""}
|
93
93
|
|
94
94
|
if msg.name:
|
95
95
|
message["name"] = msg.name
|
@@ -140,12 +140,19 @@ class OpenAIProvider(Provider):
|
|
140
140
|
if tools:
|
141
141
|
params["tools"] = tools
|
142
142
|
|
143
|
-
|
144
|
-
|
145
|
-
|
146
|
-
|
147
|
-
|
148
|
-
|
143
|
+
try:
|
144
|
+
if stream:
|
145
|
+
response = self.client.chat.completions.create(**params)
|
146
|
+
yield from self._handle_stream_response(response)
|
147
|
+
else:
|
148
|
+
response = self.client.chat.completions.create(**params)
|
149
|
+
yield from self._handle_normal_response(response)
|
150
|
+
except (openai.APIStatusError, openai.APIResponseValidationError) as e:
|
151
|
+
try:
|
152
|
+
body = e.response.json()
|
153
|
+
except Exception:
|
154
|
+
body = e.response.text
|
155
|
+
self.console.print(f"Error Response: {body}")
|
149
156
|
|
150
157
|
def _handle_normal_response(self, response: ChatCompletion) -> Generator[LLMResponse, None, None]:
|
151
158
|
"""Handle normal (non-streaming) response"""
|
@@ -10,5 +10,6 @@ class SiliconFlowProvider(OpenAIProvider):
|
|
10
10
|
|
11
11
|
def get_completion_params(self) -> Dict[str, Any]:
|
12
12
|
params = super().get_completion_params()
|
13
|
-
|
13
|
+
if "max_completion_tokens" in params:
|
14
|
+
params["max_tokens"] = params.pop("max_completion_tokens")
|
14
15
|
return params
|
@@ -0,0 +1,18 @@
|
|
1
|
+
from typing import Any, Dict
|
2
|
+
|
3
|
+
from .gemini_provider import GeminiProvider
|
4
|
+
|
5
|
+
|
6
|
+
class VertexAIProvider(GeminiProvider):
|
7
|
+
"""Vertex AI provider implementation based on google-genai library"""
|
8
|
+
|
9
|
+
def get_client_params(self) -> Dict[str, Any]:
|
10
|
+
"""Get the client parameters"""
|
11
|
+
# Initialize client params
|
12
|
+
if not self.config.get("PROJECT") or not self.config.get("LOCATION"):
|
13
|
+
raise ValueError("PROJECT and LOCATION are required for Vertex AI")
|
14
|
+
return {
|
15
|
+
"vertexai": True,
|
16
|
+
"project": self.config.get("PROJECT"),
|
17
|
+
"location": self.config.get("LOCATION"),
|
18
|
+
}
|
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.4
|
2
2
|
Name: yaicli
|
3
|
-
Version: 0.6.
|
3
|
+
Version: 0.6.4
|
4
4
|
Summary: A simple CLI tool to interact with LLM
|
5
5
|
Project-URL: Homepage, https://github.com/belingud/yaicli
|
6
6
|
Project-URL: Repository, https://github.com/belingud/yaicli
|
@@ -208,11 +208,11 @@ License: Apache License
|
|
208
208
|
See the License for the specific language governing permissions and
|
209
209
|
limitations under the License.
|
210
210
|
License-File: LICENSE
|
211
|
-
Keywords: ai,ai-assistant,ai-chat,ai-interaction,anthropic,chatgpt,claude,cli,cohere,command-line,completion,console-application,conversation,gemini,gpt,groq,inference,interactive,language-model,llm,llms,mistral,nlp,openai,prompt,python-tool,shell-integration,terminal,terminal-interface,text-generation
|
211
|
+
Keywords: ai,ai-assistant,ai-chat,ai-interaction,anthropic,chatglm,chatgpt,claude,cli,cohere,command-line,completion,console-application,conversation,deepseek,gemini,gpt,groq,huggingface,inference,interactive,language-model,llm,llms,mistral,modelscope,nlp,ollama,openai,prompt,python-tool,sambanova,shell-integration,siliconflow,terminal,terminal-interface,text-generation,vertexai,xai
|
212
212
|
Classifier: License :: OSI Approved :: Apache Software License
|
213
213
|
Classifier: Operating System :: OS Independent
|
214
214
|
Classifier: Programming Language :: Python :: 3
|
215
|
-
Requires-Python: >=3.
|
215
|
+
Requires-Python: >=3.10
|
216
216
|
Requires-Dist: click>=8.1.8
|
217
217
|
Requires-Dist: distro>=1.9.0
|
218
218
|
Requires-Dist: httpx>=0.28.1
|
@@ -225,12 +225,18 @@ Requires-Dist: socksio>=1.0.0
|
|
225
225
|
Requires-Dist: typer>=0.16.0
|
226
226
|
Provides-Extra: all
|
227
227
|
Requires-Dist: cohere>=5.15.0; extra == 'all'
|
228
|
+
Requires-Dist: google-genai>=1.20.0; extra == 'all'
|
229
|
+
Requires-Dist: huggingface-hub>=0.33.0; extra == 'all'
|
228
230
|
Requires-Dist: ollama>=0.5.1; extra == 'all'
|
229
231
|
Requires-Dist: volcengine-python-sdk>=3.0.15; extra == 'all'
|
230
232
|
Provides-Extra: cohere
|
231
233
|
Requires-Dist: cohere>=5.15.0; extra == 'cohere'
|
232
234
|
Provides-Extra: doubao
|
233
235
|
Requires-Dist: volcengine-python-sdk>=3.0.15; extra == 'doubao'
|
236
|
+
Provides-Extra: gemini
|
237
|
+
Requires-Dist: google-genai>=1.20.0; extra == 'gemini'
|
238
|
+
Provides-Extra: huggingface
|
239
|
+
Requires-Dist: huggingface-hub>=0.33.0; extra == 'huggingface'
|
234
240
|
Provides-Extra: ollama
|
235
241
|
Requires-Dist: ollama>=0.5.1; extra == 'ollama'
|
236
242
|
Description-Content-Type: text/markdown
|
@@ -323,14 +329,8 @@ Yaicli has several optional dependencies group, you can copy below commands to i
|
|
323
329
|
# install all denpendencies
|
324
330
|
pip install 'yaicli[all]'
|
325
331
|
|
326
|
-
# install with
|
327
|
-
pip instsall 'yaicli[ollama]'
|
328
|
-
|
329
|
-
# install with cohere support
|
330
|
-
pip install 'yaicli[cohere]'
|
331
|
-
|
332
|
-
# install with doubao support
|
333
|
-
pip install 'yaicli[doubao]'
|
332
|
+
# install with specific provider support
|
333
|
+
pip instsall 'yaicli[ollama,cohere,doubao,huggingface,gemini]'
|
334
334
|
```
|
335
335
|
|
336
336
|
Install by `uv`.
|
@@ -339,14 +339,8 @@ Install by `uv`.
|
|
339
339
|
# install all denpendencies
|
340
340
|
uv tool install 'yaicli[all]'
|
341
341
|
|
342
|
-
# install with
|
343
|
-
uv tool instsall 'yaicli[ollama]'
|
344
|
-
|
345
|
-
# install with cohere support
|
346
|
-
uv tool install 'yaicli[cohere]'
|
347
|
-
|
348
|
-
# install with doubao support
|
349
|
-
uv tool install 'yaicli[doubao]'
|
342
|
+
# install with specific provider support
|
343
|
+
uv tool instsall 'yaicli[ollama,cohere,doubao,huggingface,gemini]'
|
350
344
|
```
|
351
345
|
|
352
346
|
### Install from Source
|
@@ -357,6 +351,31 @@ cd yaicli
|
|
357
351
|
pip install .
|
358
352
|
```
|
359
353
|
|
354
|
+
## Buildin Supported Providers
|
355
|
+
|
356
|
+
- AI21
|
357
|
+
- Chatglm
|
358
|
+
- Chuts
|
359
|
+
- Cohere
|
360
|
+
- Cohere Badrock
|
361
|
+
- Cohere Sagemaker
|
362
|
+
- Deepseek
|
363
|
+
- Doubao
|
364
|
+
- Gemini
|
365
|
+
- Vertex AI
|
366
|
+
- Groq
|
367
|
+
- Huggingface
|
368
|
+
- Minimax
|
369
|
+
- ModelScope
|
370
|
+
- Ollama
|
371
|
+
- Openai
|
372
|
+
- Sambanova
|
373
|
+
- Siliconflow
|
374
|
+
- Targon
|
375
|
+
- X AI
|
376
|
+
- Yi
|
377
|
+
- Unlimited OpenAI-compatible providers
|
378
|
+
|
360
379
|
## ⚙️ Configuration
|
361
380
|
|
362
381
|
YAICLI uses a simple configuration file to store your preferences and API keys.
|
@@ -494,6 +513,15 @@ API_KEY=
|
|
494
513
|
MODEL=gpt-4o
|
495
514
|
```
|
496
515
|
|
516
|
+
Extra params:
|
517
|
+
|
518
|
+
```ini
|
519
|
+
# REASONING_EFFORT: [high, midium, low]
|
520
|
+
REASONING_EFFORT=
|
521
|
+
```
|
522
|
+
|
523
|
+
See official for more details: https://platform.openai.com/docs/guides/reasoning?api-mode=chat
|
524
|
+
|
497
525
|
#### Deepseek
|
498
526
|
|
499
527
|
```ini
|
@@ -510,6 +538,48 @@ API_KEY=
|
|
510
538
|
MODEL=deepseek/deepseek-chat-v3-0324
|
511
539
|
```
|
512
540
|
|
541
|
+
#### Gemini
|
542
|
+
|
543
|
+
Basic config:
|
544
|
+
|
545
|
+
```ini
|
546
|
+
PROVIDER=gemini
|
547
|
+
API_KEY=
|
548
|
+
MODEL=gemini-2.5-flash
|
549
|
+
```
|
550
|
+
|
551
|
+
Extra params:
|
552
|
+
|
553
|
+
```ini
|
554
|
+
TOP_K=
|
555
|
+
PRESENCE_PENALTY=
|
556
|
+
FREQUENCY_PENALTY=
|
557
|
+
SEED=
|
558
|
+
THINKING_BUDGET=
|
559
|
+
API_VERSION=
|
560
|
+
BASE_URL=
|
561
|
+
```
|
562
|
+
|
563
|
+
#### Vertex AI
|
564
|
+
|
565
|
+
```ini
|
566
|
+
PROVIDER=vertexai
|
567
|
+
MODEL=gemini-2.5-flash
|
568
|
+
PROJECT=
|
569
|
+
LOCATION=
|
570
|
+
```
|
571
|
+
|
572
|
+
#### Huggingface
|
573
|
+
|
574
|
+
```ini
|
575
|
+
HF_PROVIDER=sambanova
|
576
|
+
PROVIDER=huggingface
|
577
|
+
API_KEY=
|
578
|
+
MODEL=deepseek-ai/DeepSeek-R1-0528
|
579
|
+
```
|
580
|
+
|
581
|
+
See official docs for `HF_PROVIDER`: https://huggingface.co/docs/inference-providers/index
|
582
|
+
|
513
583
|
#### Groq
|
514
584
|
|
515
585
|
```ini
|
@@ -534,6 +604,15 @@ API_KEY=
|
|
534
604
|
MODEL=glm-4-plus
|
535
605
|
```
|
536
606
|
|
607
|
+
Extra params:
|
608
|
+
|
609
|
+
Check offcial docs: https://bigmodel.cn/dev/api/normal-model/glm-4
|
610
|
+
|
611
|
+
```ini
|
612
|
+
# true or false
|
613
|
+
DO_SAMPLE=
|
614
|
+
```
|
615
|
+
|
537
616
|
#### Chutes
|
538
617
|
|
539
618
|
```ini
|
@@ -558,6 +637,16 @@ API_KEY=
|
|
558
637
|
MODEL=DeepSeek-V3-0324
|
559
638
|
```
|
560
639
|
|
640
|
+
Only a few models support tool call as below:
|
641
|
+
|
642
|
+
- Meta-Llama-3.1-8B-Instruct
|
643
|
+
- Meta-Llama-3.1-405B-Instruct
|
644
|
+
- Meta-Llama-3.3-70B-Instruct
|
645
|
+
- Llama-4-Scout-17B-16E-Instruct
|
646
|
+
- DeepSeek-V3-0324
|
647
|
+
|
648
|
+
See official docs for more detail: https://docs.sambanova.ai/cloud/docs/capabilities/function-calling
|
649
|
+
|
561
650
|
#### ModelScope
|
562
651
|
|
563
652
|
```ini
|
@@ -601,6 +690,45 @@ API_KEY=
|
|
601
690
|
MODEL=command-a-03-2025
|
602
691
|
```
|
603
692
|
|
693
|
+
Check official docs: https://docs.cohere.com/docs/text-gen-quickstart
|
694
|
+
|
695
|
+
Support keys:
|
696
|
+
|
697
|
+
```ini
|
698
|
+
ENVIRONMENT=
|
699
|
+
```
|
700
|
+
|
701
|
+
For private deploy and Azure api, you need to set BASE_URL.
|
702
|
+
|
703
|
+
```ini
|
704
|
+
PROVIDER=cohere
|
705
|
+
API_KEY=
|
706
|
+
MODEL=command-a-03-2025
|
707
|
+
BASE_URL=<YOUR_ENDPOINT>
|
708
|
+
```
|
709
|
+
|
710
|
+
For Bedrock and Sagemaker cohere api, you have to set below keys:
|
711
|
+
|
712
|
+
See https://docs.cohere.com/docs/text-gen-quickstart.
|
713
|
+
|
714
|
+
```ini
|
715
|
+
PROVIDER=cohere-bedrock
|
716
|
+
; PROVIDER=cohere-sagemaker
|
717
|
+
API_KEY=
|
718
|
+
MODEL=command-a-03-2025
|
719
|
+
|
720
|
+
AWS_REGION=xx
|
721
|
+
AWS_ACCESS_KEY_ID=xx
|
722
|
+
AWS_SECRET_ACCESS_KEY=xx
|
723
|
+
AWS_SESSION_TOKEN=xx
|
724
|
+
```
|
725
|
+
|
726
|
+
Note `MODEL` for Sagemaker should be endpoint name
|
727
|
+
|
728
|
+
```ini
|
729
|
+
MODEL=<YOUR_ENDPOINT_NAME>
|
730
|
+
```
|
731
|
+
|
604
732
|
#### Doubao
|
605
733
|
|
606
734
|
You have to install doubao dependencies, `pip install 'yaicli[doubao]'`
|
@@ -1,10 +1,10 @@
|
|
1
|
-
pyproject.toml,sha256=
|
1
|
+
pyproject.toml,sha256=LQv7NHuPZjn7h03OWDzftK8V0G_OG0626EkpVEUh4IA,2756
|
2
2
|
yaicli/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
3
3
|
yaicli/chat.py,sha256=_emvZEdgMBth2nQGaNWPf0P45oW2k3bpuIwqsxFcM5A,13676
|
4
|
-
yaicli/cli.py,sha256=
|
5
|
-
yaicli/config.py,sha256=
|
4
|
+
yaicli/cli.py,sha256=s8Bj4MSQmLblh4fHBPKS-DvJoAdMmp64KC7e7BwzmOs,23322
|
5
|
+
yaicli/config.py,sha256=_xLHgyW5dDg76bL1SyTcrQCnVs4dFpXafIS3sClshK0,6563
|
6
6
|
yaicli/console.py,sha256=vARPJd-3lafutsQWrGntQVjLrYqaJD3qisN82pmuhjU,1973
|
7
|
-
yaicli/const.py,sha256=
|
7
|
+
yaicli/const.py,sha256=G-EhMsSfOjKQLBhpOAc3pRtjvKmmWrwyyuyuGKHt7wk,8194
|
8
8
|
yaicli/entry.py,sha256=Q1eqLE7tcHide7ooyPO7OCJpKE2YVuxR-NNFA2Pt2Hw,8693
|
9
9
|
yaicli/exceptions.py,sha256=WBYg8OTJJzaj7lt6HE7ZyBoe5T6A3yZRNCRfWd4iN0c,372
|
10
10
|
yaicli/history.py,sha256=s-57X9FMsaQHF7XySq1gGH_jpd_cHHTYafYu2ECuG6M,2472
|
@@ -16,29 +16,32 @@ yaicli/tools.py,sha256=xw8KEs_xlSf79A2Aq1rAsUWahS6A_e5QMLt7QDXL5bs,5086
|
|
16
16
|
yaicli/utils.py,sha256=bpo3Xhozpxsaci3FtEIKZ32l4ZdyWMsrHjYGX0tB4J4,4541
|
17
17
|
yaicli/functions/__init__.py,sha256=_FJooQ9GkijG8xLwuU0cr5GBrGnC9Nc6bnCeUjrsT0k,1271
|
18
18
|
yaicli/functions/buildin/execute_shell_command.py,sha256=unl1-F8p6QZajeHdA0u5UpURMJM0WhdWMUWCCCHVRcI,1320
|
19
|
-
yaicli/llms/__init__.py,sha256=
|
19
|
+
yaicli/llms/__init__.py,sha256=x78cJujrJkelXPnzHS6pzHkITZdgLYZqJMnrMHbptoc,134
|
20
20
|
yaicli/llms/client.py,sha256=mkE9KHSuPcJfpNQXbzF2YXGkel3jrOW8KfQ3YYpaK4M,4453
|
21
|
-
yaicli/llms/provider.py,sha256=
|
21
|
+
yaicli/llms/provider.py,sha256=jF15kmY_tZVOjlw0fbHQkEvlmOX57-HBhILzG0KvXyo,3412
|
22
22
|
yaicli/llms/providers/ai21_provider.py,sha256=SvgGj9_87KEqmxCMLbtsSkT8J3rUD7Mb21UF7pMWsks,3035
|
23
|
-
yaicli/llms/providers/chatglm_provider.py,sha256=
|
23
|
+
yaicli/llms/providers/chatglm_provider.py,sha256=QEzALvY5FBhuDCx6rHjLi7GSRTwTHNUwo8gg4FEdrxs,6466
|
24
24
|
yaicli/llms/providers/chutes_provider.py,sha256=mtvWvRRfHPH3JFfzym87wXtPNiMpLnur3805N9acx7E,882
|
25
|
-
yaicli/llms/providers/cohere_provider.py,sha256=
|
26
|
-
yaicli/llms/providers/deepseek_provider.py,sha256=
|
25
|
+
yaicli/llms/providers/cohere_provider.py,sha256=1UPzNqNOwM4_dsP4kvUaL9O6_bKjxm1lO6A0lM7hgS4,10959
|
26
|
+
yaicli/llms/providers/deepseek_provider.py,sha256=iIV97x2ZCcwhGkshc8wpRi-YAnAnmo0n-YRegPlaOwQ,488
|
27
27
|
yaicli/llms/providers/doubao_provider.py,sha256=4eOdE91ITUn3uo3mvYAzdrHsuFIIBwZWib21mtZn8OY,1938
|
28
|
+
yaicli/llms/providers/gemini_provider.py,sha256=k_6JFmqiYPz5K8IioFic5tp8KAHgeeakjkPyqJVz8BI,8007
|
28
29
|
yaicli/llms/providers/groq_provider.py,sha256=EiS1Yxw5jbAUBFCRYsJ57KYgZPk6oH-_gD72OfW8Oik,1358
|
29
|
-
yaicli/llms/providers/
|
30
|
+
yaicli/llms/providers/huggingface_provider.py,sha256=vDJyyK_aOlvktNvs-cji6pDtmKEp61vuVJ783BZw4pc,1247
|
31
|
+
yaicli/llms/providers/infiniai_provider.py,sha256=8-nU6QE58PRoZL9b_HzbPp4yi6OGm7rXtfi9z7bJMOg,786
|
30
32
|
yaicli/llms/providers/minimax_provider.py,sha256=W-j3dzrYMEv14bYt2pCPvPUxvxsUs-iMAcGB9yXakFs,744
|
31
|
-
yaicli/llms/providers/modelscope_provider.py,sha256=
|
33
|
+
yaicli/llms/providers/modelscope_provider.py,sha256=qWM0T7r0Zf8k3pLzjj7_IFdnmnx7S3rJO0f9rRm8-_A,504
|
32
34
|
yaicli/llms/providers/ollama_provider.py,sha256=pjpYjfnHWnExweZi1KGbT07JGkcxzKPhqICo8dD82D0,6967
|
33
|
-
yaicli/llms/providers/openai_provider.py,sha256=
|
35
|
+
yaicli/llms/providers/openai_provider.py,sha256=ENn21QacP2iTcmbxuW7dgiw3_fUr8EGWhNSFR2yxjis,10079
|
34
36
|
yaicli/llms/providers/openrouter_provider.py,sha256=R-7FrUrCAKPZ3gbnuo0M6rPlVw1mvSBjbLGs_FtZWM0,732
|
35
37
|
yaicli/llms/providers/sambanova_provider.py,sha256=FFLrsvARt1UPAFWWgiuB6zvGzGKdtehKL58HdE1fo_M,2254
|
36
|
-
yaicli/llms/providers/siliconflow_provider.py,sha256=
|
38
|
+
yaicli/llms/providers/siliconflow_provider.py,sha256=CW2VSt6evUyFy21vN84Nvmw1P0JpmHBLznsgiXMnHM0,496
|
37
39
|
yaicli/llms/providers/targon_provider.py,sha256=RQ808eS9lvsyvlzyKaQYcN0NimbpoNWgjHUzY1gLNs4,717
|
40
|
+
yaicli/llms/providers/vertexai_provider.py,sha256=_ddrse1LfXRChTgkvxUlexyfJlfr0sVJH-Rmno3djSI,636
|
38
41
|
yaicli/llms/providers/xai_provider.py,sha256=Q6iOvJZOXIAwRiiHMKEBgq8-W6SGVZ9QD1_532bNYfo,199
|
39
42
|
yaicli/llms/providers/yi_provider.py,sha256=EnTm9qTxHPnzERsKqgGnzRIVhXFcAEdYqtOra65pGmY,719
|
40
|
-
yaicli-0.6.
|
41
|
-
yaicli-0.6.
|
42
|
-
yaicli-0.6.
|
43
|
-
yaicli-0.6.
|
44
|
-
yaicli-0.6.
|
43
|
+
yaicli-0.6.4.dist-info/METADATA,sha256=q1r4B-AADLIC9gAYEDd4BDHnAMnbjqDXrrOG3QNxbGc,55786
|
44
|
+
yaicli-0.6.4.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
45
|
+
yaicli-0.6.4.dist-info/entry_points.txt,sha256=iYVyQP0PJIm9tQnlQheqT435kK_xdGoi5j9aswGV9hA,66
|
46
|
+
yaicli-0.6.4.dist-info/licenses/LICENSE,sha256=xx0jnfkXJvxRnG63LTGOxlggYnIysveWIZ6H3PNdCrQ,11357
|
47
|
+
yaicli-0.6.4.dist-info/RECORD,,
|
File without changes
|
File without changes
|
File without changes
|