llms-py 3.0.0b6__py3-none-any.whl → 3.0.0b8__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.
- llms/__pycache__/main.cpython-314.pyc +0 -0
- llms/{ui/modules/analytics.mjs → extensions/analytics/ui/index.mjs} +55 -164
- llms/extensions/app/__init__.py +519 -0
- llms/extensions/app/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/app/__pycache__/db.cpython-314.pyc +0 -0
- llms/extensions/app/__pycache__/db_manager.cpython-314.pyc +0 -0
- llms/extensions/app/db.py +641 -0
- llms/extensions/app/db_manager.py +195 -0
- llms/extensions/app/requests.json +9073 -0
- llms/extensions/app/threads.json +15290 -0
- llms/{ui/modules/threads → extensions/app/ui}/Recents.mjs +82 -55
- llms/{ui/modules/threads → extensions/app/ui}/index.mjs +83 -20
- llms/extensions/app/ui/threadStore.mjs +407 -0
- llms/extensions/core_tools/__init__.py +598 -0
- llms/extensions/core_tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/closebrackets.js +201 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/closetag.js +185 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/continuelist.js +101 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchbrackets.js +160 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/matchtags.js +66 -0
- llms/extensions/core_tools/ui/codemirror/addon/edit/trailingspace.js +27 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/active-line.js +72 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/mark-selection.js +119 -0
- llms/extensions/core_tools/ui/codemirror/addon/selection/selection-pointer.js +98 -0
- llms/extensions/core_tools/ui/codemirror/doc/docs.css +225 -0
- llms/extensions/core_tools/ui/codemirror/doc/source_sans.woff +0 -0
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.css +344 -0
- llms/extensions/core_tools/ui/codemirror/lib/codemirror.js +9884 -0
- llms/extensions/core_tools/ui/codemirror/mode/clike/clike.js +942 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/index.html +118 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/javascript.js +962 -0
- llms/extensions/core_tools/ui/codemirror/mode/javascript/typescript.html +62 -0
- llms/extensions/core_tools/ui/codemirror/mode/python/python.js +402 -0
- llms/extensions/core_tools/ui/codemirror/theme/dracula.css +40 -0
- llms/extensions/core_tools/ui/codemirror/theme/mocha.css +135 -0
- llms/extensions/core_tools/ui/index.mjs +650 -0
- llms/extensions/gallery/__init__.py +61 -0
- llms/extensions/gallery/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/gallery/__pycache__/db.cpython-314.pyc +0 -0
- llms/extensions/gallery/db.py +298 -0
- llms/extensions/gallery/ui/index.mjs +481 -0
- llms/extensions/katex/__init__.py +6 -0
- llms/extensions/katex/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/katex/ui/README.md +125 -0
- llms/extensions/katex/ui/contrib/auto-render.js +338 -0
- llms/extensions/katex/ui/contrib/auto-render.min.js +1 -0
- llms/extensions/katex/ui/contrib/auto-render.mjs +244 -0
- llms/extensions/katex/ui/contrib/copy-tex.js +127 -0
- llms/extensions/katex/ui/contrib/copy-tex.min.js +1 -0
- llms/extensions/katex/ui/contrib/copy-tex.mjs +105 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.js +109 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.min.js +1 -0
- llms/extensions/katex/ui/contrib/mathtex-script-type.mjs +24 -0
- llms/extensions/katex/ui/contrib/mhchem.js +3213 -0
- llms/extensions/katex/ui/contrib/mhchem.min.js +1 -0
- llms/extensions/katex/ui/contrib/mhchem.mjs +3109 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.js +887 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.min.js +1 -0
- llms/extensions/katex/ui/contrib/render-a11y-string.mjs +800 -0
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_AMS-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Caligraphic-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Fraktur-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-BoldItalic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Main-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-BoldItalic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Math-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Bold.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Italic.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_SansSerif-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Script-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size1-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size2-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size3-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Size4-Regular.woff2 +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.ttf +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff +0 -0
- llms/extensions/katex/ui/fonts/KaTeX_Typewriter-Regular.woff2 +0 -0
- llms/extensions/katex/ui/index.mjs +92 -0
- llms/extensions/katex/ui/katex-swap.css +1230 -0
- llms/extensions/katex/ui/katex-swap.min.css +1 -0
- llms/extensions/katex/ui/katex.css +1230 -0
- llms/extensions/katex/ui/katex.js +19080 -0
- llms/extensions/katex/ui/katex.min.css +1 -0
- llms/extensions/katex/ui/katex.min.js +1 -0
- llms/extensions/katex/ui/katex.min.mjs +1 -0
- llms/extensions/katex/ui/katex.mjs +18547 -0
- llms/extensions/providers/__init__.py +18 -0
- llms/extensions/providers/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/chutes.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/google.cpython-314.pyc +0 -0
- llms/{providers → extensions/providers}/__pycache__/nvidia.cpython-314.pyc +0 -0
- llms/{providers → extensions/providers}/__pycache__/openai.cpython-314.pyc +0 -0
- llms/extensions/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
- llms/{providers → extensions/providers}/anthropic.py +45 -5
- llms/{providers → extensions/providers}/chutes.py +21 -18
- llms/{providers → extensions/providers}/google.py +99 -27
- llms/{providers → extensions/providers}/nvidia.py +6 -8
- llms/{providers → extensions/providers}/openai.py +3 -6
- llms/{providers → extensions/providers}/openrouter.py +12 -10
- llms/extensions/system_prompts/__init__.py +45 -0
- llms/extensions/system_prompts/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/extensions/system_prompts/ui/index.mjs +285 -0
- llms/extensions/system_prompts/ui/prompts.json +1067 -0
- llms/extensions/tools/__init__.py +5 -0
- llms/extensions/tools/__pycache__/__init__.cpython-314.pyc +0 -0
- llms/{ui/modules/tools.mjs → extensions/tools/ui/index.mjs} +12 -10
- llms/index.html +26 -38
- llms/llms.json +20 -1
- llms/main.py +845 -245
- llms/providers-extra.json +0 -32
- llms/ui/App.mjs +18 -20
- llms/ui/ai.mjs +38 -15
- llms/ui/app.css +1440 -59
- llms/ui/ctx.mjs +154 -18
- llms/ui/index.mjs +17 -14
- llms/ui/lib/vue.min.mjs +10 -9
- llms/ui/lib/vue.mjs +1796 -1635
- llms/ui/markdown.mjs +4 -2
- llms/ui/modules/chat/ChatBody.mjs +101 -334
- llms/ui/modules/chat/HomeTools.mjs +12 -0
- llms/ui/modules/chat/SettingsDialog.mjs +1 -1
- llms/ui/modules/chat/index.mjs +351 -314
- llms/ui/modules/layout.mjs +2 -26
- llms/ui/modules/model-selector.mjs +3 -3
- llms/ui/tailwind.input.css +35 -1
- llms/ui/utils.mjs +33 -3
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/METADATA +1 -1
- llms_py-3.0.0b8.dist-info/RECORD +198 -0
- llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
- llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
- llms/providers/__pycache__/google.cpython-314.pyc +0 -0
- llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
- llms/ui/modules/threads/threadStore.mjs +0 -586
- llms_py-3.0.0b6.dist-info/RECORD +0 -66
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/WHEEL +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/entry_points.txt +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/licenses/LICENSE +0 -0
- {llms_py-3.0.0b6.dist-info → llms_py-3.0.0b8.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
from .anthropic import install_anthropic
|
|
2
|
+
from .chutes import install_chutes
|
|
3
|
+
from .google import install_google
|
|
4
|
+
from .nvidia import install_nvidia
|
|
5
|
+
from .openai import install_openai
|
|
6
|
+
from .openrouter import install_openrouter
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
def install(ctx):
|
|
10
|
+
install_anthropic(ctx)
|
|
11
|
+
install_chutes(ctx)
|
|
12
|
+
install_google(ctx)
|
|
13
|
+
install_openai(ctx)
|
|
14
|
+
install_openrouter(ctx)
|
|
15
|
+
install_nvidia(ctx)
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
__install__ = install
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -4,7 +4,7 @@ import time
|
|
|
4
4
|
import aiohttp
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def install_anthropic(ctx):
|
|
8
8
|
from llms.main import OpenAiCompatible
|
|
9
9
|
|
|
10
10
|
class AnthropicProvider(OpenAiCompatible):
|
|
@@ -58,6 +58,23 @@ def install(ctx):
|
|
|
58
58
|
if message.get("role") == "system":
|
|
59
59
|
continue
|
|
60
60
|
|
|
61
|
+
if message.get("role") == "tool":
|
|
62
|
+
# Convert OpenAI tool response to Anthropic tool_result
|
|
63
|
+
tool_call_id = message.get("tool_call_id")
|
|
64
|
+
content = ctx.to_content(message.get("content", ""))
|
|
65
|
+
if not isinstance(content, (str, list)):
|
|
66
|
+
content = str(content)
|
|
67
|
+
|
|
68
|
+
tool_result = {"type": "tool_result", "tool_use_id": tool_call_id, "content": content}
|
|
69
|
+
|
|
70
|
+
# Anthropic requires tool results to be in a user message
|
|
71
|
+
# Check if the last message was a user message, if so append to it
|
|
72
|
+
if anthropic_request["messages"] and anthropic_request["messages"][-1]["role"] == "user":
|
|
73
|
+
anthropic_request["messages"][-1]["content"].append(tool_result)
|
|
74
|
+
else:
|
|
75
|
+
anthropic_request["messages"].append({"role": "user", "content": [tool_result]})
|
|
76
|
+
continue
|
|
77
|
+
|
|
61
78
|
anthropic_message = {"role": message.get("role"), "content": []}
|
|
62
79
|
|
|
63
80
|
content = message.get("content", "")
|
|
@@ -106,7 +123,18 @@ def install(ctx):
|
|
|
106
123
|
if "stream" in chat:
|
|
107
124
|
anthropic_request["stream"] = chat["stream"]
|
|
108
125
|
if "tools" in chat:
|
|
109
|
-
|
|
126
|
+
anthropic_tools = []
|
|
127
|
+
for tool in chat["tools"]:
|
|
128
|
+
if tool.get("type") == "function":
|
|
129
|
+
function = tool.get("function", {})
|
|
130
|
+
anthropic_tool = {
|
|
131
|
+
"name": function.get("name"),
|
|
132
|
+
"description": function.get("description"),
|
|
133
|
+
"input_schema": function.get("parameters"),
|
|
134
|
+
}
|
|
135
|
+
anthropic_tools.append(anthropic_tool)
|
|
136
|
+
if anthropic_tools:
|
|
137
|
+
anthropic_request["tools"] = anthropic_tools
|
|
110
138
|
if "tool_choice" in chat:
|
|
111
139
|
anthropic_request["tool_choice"] = chat["tool_choice"]
|
|
112
140
|
|
|
@@ -138,6 +166,7 @@ def install(ctx):
|
|
|
138
166
|
# Transform content blocks to message content
|
|
139
167
|
content_parts = []
|
|
140
168
|
thinking_parts = []
|
|
169
|
+
tool_calls = []
|
|
141
170
|
|
|
142
171
|
for block in response.get("content", []):
|
|
143
172
|
if block.get("type") == "text":
|
|
@@ -145,6 +174,16 @@ def install(ctx):
|
|
|
145
174
|
elif block.get("type") == "thinking":
|
|
146
175
|
# Store thinking blocks separately (some models include reasoning)
|
|
147
176
|
thinking_parts.append(block.get("thinking", ""))
|
|
177
|
+
elif block.get("type") == "tool_use":
|
|
178
|
+
tool_call = {
|
|
179
|
+
"id": block.get("id"),
|
|
180
|
+
"type": "function",
|
|
181
|
+
"function": {
|
|
182
|
+
"name": block.get("name"),
|
|
183
|
+
"arguments": json.dumps(block.get("input", {})),
|
|
184
|
+
},
|
|
185
|
+
}
|
|
186
|
+
tool_calls.append(tool_call)
|
|
148
187
|
|
|
149
188
|
# Combine all text content
|
|
150
189
|
message_content = "\n".join(content_parts) if content_parts else ""
|
|
@@ -160,6 +199,10 @@ def install(ctx):
|
|
|
160
199
|
if thinking_parts:
|
|
161
200
|
choice["message"]["thinking"] = "\n".join(thinking_parts)
|
|
162
201
|
|
|
202
|
+
# Add tool_calls if present
|
|
203
|
+
if tool_calls:
|
|
204
|
+
choice["message"]["tool_calls"] = tool_calls
|
|
205
|
+
|
|
163
206
|
ret["choices"].append(choice)
|
|
164
207
|
|
|
165
208
|
# Transform usage
|
|
@@ -184,6 +227,3 @@ def install(ctx):
|
|
|
184
227
|
return ret
|
|
185
228
|
|
|
186
229
|
ctx.add_provider(AnthropicProvider)
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
__install__ = install
|
|
@@ -5,7 +5,7 @@ import time
|
|
|
5
5
|
import aiohttp
|
|
6
6
|
|
|
7
7
|
|
|
8
|
-
def
|
|
8
|
+
def install_chutes(ctx):
|
|
9
9
|
from llms.main import GeneratorBase
|
|
10
10
|
|
|
11
11
|
class ChutesImage(GeneratorBase):
|
|
@@ -50,15 +50,18 @@ def install(ctx):
|
|
|
50
50
|
if "messages" in chat and len(chat["messages"]) > 0:
|
|
51
51
|
aspect_ratio = chat["messages"][0].get("aspect_ratio", "1:1")
|
|
52
52
|
cfg_scale = self.cfg_scale
|
|
53
|
+
steps = self.steps
|
|
54
|
+
width = self.width
|
|
55
|
+
height = self.height
|
|
53
56
|
if chat["model"] == "chutes-z-image-turbo":
|
|
54
57
|
cfg_scale = min(self.cfg_scale, 5)
|
|
55
58
|
payload = {
|
|
56
59
|
"model": chat["model"],
|
|
57
60
|
"prompt": ctx.last_user_prompt(chat),
|
|
58
61
|
"guidance_scale": cfg_scale,
|
|
59
|
-
"width":
|
|
60
|
-
"height":
|
|
61
|
-
"num_inference_steps":
|
|
62
|
+
"width": width,
|
|
63
|
+
"height": height,
|
|
64
|
+
"num_inference_steps": steps,
|
|
62
65
|
}
|
|
63
66
|
if chat["model"] in self.model_negative_prompt:
|
|
64
67
|
payload["negative_prompt"] = self.negative_prompt
|
|
@@ -68,9 +71,10 @@ def install(ctx):
|
|
|
68
71
|
if aspect_ratio:
|
|
69
72
|
dimension = ctx.app.aspect_ratios.get(aspect_ratio)
|
|
70
73
|
if dimension:
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
payload["
|
|
74
|
+
w, h = dimension.split("×")
|
|
75
|
+
width, height = int(w), int(h)
|
|
76
|
+
payload["width"] = width
|
|
77
|
+
payload["height"] = height
|
|
74
78
|
|
|
75
79
|
if chat["model"] in self.model_resolutions:
|
|
76
80
|
# if models use resolution, remove width and height
|
|
@@ -107,14 +111,16 @@ def install(ctx):
|
|
|
107
111
|
relative_url, info = ctx.save_image_to_cache(
|
|
108
112
|
image_data,
|
|
109
113
|
f"{chat['model']}.{ext}",
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
114
|
+
ctx.to_file_info(
|
|
115
|
+
chat,
|
|
116
|
+
{
|
|
117
|
+
"aspect_ratio": aspect_ratio,
|
|
118
|
+
"width": width,
|
|
119
|
+
"height": height,
|
|
120
|
+
"cfg_scale": cfg_scale,
|
|
121
|
+
"steps": steps,
|
|
122
|
+
},
|
|
123
|
+
),
|
|
118
124
|
)
|
|
119
125
|
return {
|
|
120
126
|
"choices": [
|
|
@@ -147,6 +153,3 @@ def install(ctx):
|
|
|
147
153
|
raise Exception(f"Failed to generate image {response.status}")
|
|
148
154
|
|
|
149
155
|
ctx.add_provider(ChutesImage)
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
__install__ = install
|
|
@@ -1,5 +1,8 @@
|
|
|
1
|
+
import base64
|
|
2
|
+
import io
|
|
1
3
|
import json
|
|
2
4
|
import time
|
|
5
|
+
import wave
|
|
3
6
|
|
|
4
7
|
import aiohttp
|
|
5
8
|
|
|
@@ -11,7 +14,7 @@ import aiohttp
|
|
|
11
14
|
# self.chat_url = "https://generativelanguage.googleapis.com/v1beta/chat/completions"
|
|
12
15
|
|
|
13
16
|
|
|
14
|
-
def
|
|
17
|
+
def install_google(ctx):
|
|
15
18
|
from llms.main import OpenAiCompatible
|
|
16
19
|
|
|
17
20
|
def gemini_chat_summary(gemini_chat):
|
|
@@ -68,6 +71,7 @@ def install(ctx):
|
|
|
68
71
|
super().__init__(**new_kwargs)
|
|
69
72
|
self.safety_settings = kwargs.get("safety_settings")
|
|
70
73
|
self.thinking_config = kwargs.get("thinking_config")
|
|
74
|
+
self.speech_config = kwargs.get("speech_config")
|
|
71
75
|
self.tools = kwargs.get("tools")
|
|
72
76
|
self.curl = kwargs.get("curl")
|
|
73
77
|
self.headers = kwargs.get("headers", {"Content-Type": "application/json"})
|
|
@@ -189,13 +193,15 @@ def install(ctx):
|
|
|
189
193
|
gemini_chat["generationConfig"] = generation_config
|
|
190
194
|
|
|
191
195
|
if "tools" in chat:
|
|
192
|
-
gemini_chat["tools"] = chat["tools"]
|
|
196
|
+
# gemini_chat["tools"] = chat["tools"]
|
|
197
|
+
ctx.log("Error: tools not supported in Gemini")
|
|
193
198
|
elif self.tools:
|
|
194
|
-
gemini_chat["tools"] = self.tools.copy()
|
|
199
|
+
# gemini_chat["tools"] = self.tools.copy()
|
|
200
|
+
ctx.log("Error: tools not supported in Gemini")
|
|
195
201
|
|
|
196
202
|
if "modalities" in chat:
|
|
197
203
|
generation_config["responseModalities"] = [modality.upper() for modality in chat["modalities"]]
|
|
198
|
-
if "image_config" in chat:
|
|
204
|
+
if "image" in chat["modalities"] and "image_config" in chat:
|
|
199
205
|
# delete thinkingConfig
|
|
200
206
|
del generation_config["thinkingConfig"]
|
|
201
207
|
config_map = {
|
|
@@ -205,6 +211,11 @@ def install(ctx):
|
|
|
205
211
|
generation_config["imageConfig"] = {
|
|
206
212
|
config_map[k]: v for k, v in chat["image_config"].items() if k in config_map
|
|
207
213
|
}
|
|
214
|
+
if "audio" in chat["modalities"] and self.speech_config:
|
|
215
|
+
del generation_config["thinkingConfig"]
|
|
216
|
+
generation_config["speechConfig"] = self.speech_config.copy()
|
|
217
|
+
# Currently Google Audio Models only accept AUDIO
|
|
218
|
+
generation_config["responseModalities"] = ["AUDIO"]
|
|
208
219
|
|
|
209
220
|
started_at = int(time.time() * 1000)
|
|
210
221
|
gemini_chat_url = f"https://generativelanguage.googleapis.com/v1beta/models/{chat['model']}:generateContent?key={self.api_key}"
|
|
@@ -218,13 +229,22 @@ def install(ctx):
|
|
|
218
229
|
with open(f"{ctx.MOCK_DIR}/gemini-image.json") as f:
|
|
219
230
|
obj = json.load(f)
|
|
220
231
|
else:
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
232
|
+
try:
|
|
233
|
+
async with session.post(
|
|
234
|
+
gemini_chat_url,
|
|
235
|
+
headers=self.headers,
|
|
236
|
+
data=json.dumps(gemini_chat),
|
|
237
|
+
timeout=aiohttp.ClientTimeout(total=120),
|
|
238
|
+
) as res:
|
|
239
|
+
obj = await self.response_json(res)
|
|
240
|
+
except Exception as e:
|
|
241
|
+
ctx.log(f"Error: {res.status} {res.reason}: {e}")
|
|
242
|
+
text = await res.text()
|
|
243
|
+
try:
|
|
244
|
+
obj = json.loads(text)
|
|
245
|
+
except:
|
|
246
|
+
ctx.log(text)
|
|
247
|
+
raise e
|
|
228
248
|
|
|
229
249
|
if "error" in obj:
|
|
230
250
|
ctx.log(f"Error: {obj['error']}")
|
|
@@ -233,6 +253,18 @@ def install(ctx):
|
|
|
233
253
|
if ctx.debug:
|
|
234
254
|
ctx.dbg(json.dumps(gemini_response_summary(obj), indent=2))
|
|
235
255
|
|
|
256
|
+
# calculate cost per generation
|
|
257
|
+
cost = None
|
|
258
|
+
token_costs = obj.get("metadata", {}).get("pricing", "")
|
|
259
|
+
if token_costs:
|
|
260
|
+
input_price, output_price = token_costs.split("/")
|
|
261
|
+
input_per_token = float(input_price) / 1000000
|
|
262
|
+
output_per_token = float(output_price) / 1000000
|
|
263
|
+
if "usageMetadata" in obj:
|
|
264
|
+
input_tokens = obj["usageMetadata"].get("promptTokenCount", 0)
|
|
265
|
+
output_tokens = obj["usageMetadata"].get("candidatesTokenCount", 0)
|
|
266
|
+
cost = (input_per_token * input_tokens) + (output_per_token * output_tokens)
|
|
267
|
+
|
|
236
268
|
response = {
|
|
237
269
|
"id": f"chatcmpl-{started_at}",
|
|
238
270
|
"created": started_at,
|
|
@@ -248,6 +280,7 @@ def install(ctx):
|
|
|
248
280
|
content = ""
|
|
249
281
|
reasoning = ""
|
|
250
282
|
images = []
|
|
283
|
+
audios = []
|
|
251
284
|
if "content" in candidate and "parts" in candidate["content"]:
|
|
252
285
|
text_parts = []
|
|
253
286
|
reasoning_parts = []
|
|
@@ -260,19 +293,59 @@ def install(ctx):
|
|
|
260
293
|
if "inlineData" in part:
|
|
261
294
|
inline_data = part["inlineData"]
|
|
262
295
|
mime_type = inline_data.get("mimeType", "image/png")
|
|
263
|
-
|
|
264
|
-
|
|
265
|
-
|
|
266
|
-
|
|
267
|
-
|
|
268
|
-
|
|
269
|
-
|
|
270
|
-
|
|
271
|
-
"
|
|
272
|
-
|
|
273
|
-
|
|
274
|
-
|
|
275
|
-
|
|
296
|
+
if mime_type.startswith("image"):
|
|
297
|
+
ext = mime_type.split("/")[1]
|
|
298
|
+
base64_data = inline_data["data"]
|
|
299
|
+
filename = f"{chat['model'].split('/')[-1]}-{len(images)}.{ext}"
|
|
300
|
+
ctx.log(f"inlineData {len(base64_data)} {mime_type} {filename}")
|
|
301
|
+
relative_url, info = ctx.save_image_to_cache(
|
|
302
|
+
base64_data,
|
|
303
|
+
filename,
|
|
304
|
+
ctx.to_file_info(chat, {"cost": cost}),
|
|
305
|
+
)
|
|
306
|
+
images.append(
|
|
307
|
+
{
|
|
308
|
+
"type": "image_url",
|
|
309
|
+
"index": len(images),
|
|
310
|
+
"image_url": {
|
|
311
|
+
"url": relative_url,
|
|
312
|
+
},
|
|
313
|
+
}
|
|
314
|
+
)
|
|
315
|
+
elif mime_type.startswith("audio"):
|
|
316
|
+
# mime_type audio/L16;codec=pcm;rate=24000
|
|
317
|
+
base64_data = inline_data["data"]
|
|
318
|
+
|
|
319
|
+
pcm = base64.b64decode(base64_data)
|
|
320
|
+
# Convert PCM to WAV
|
|
321
|
+
wav_io = io.BytesIO()
|
|
322
|
+
with wave.open(wav_io, "wb") as wf:
|
|
323
|
+
wf.setnchannels(1)
|
|
324
|
+
wf.setsampwidth(2)
|
|
325
|
+
wf.setframerate(24000)
|
|
326
|
+
wf.writeframes(pcm)
|
|
327
|
+
wav_data = wav_io.getvalue()
|
|
328
|
+
|
|
329
|
+
ext = mime_type.split("/")[1].split(";")[0]
|
|
330
|
+
pcm_filename = f"{chat['model'].split('/')[-1]}-{len(audios)}.{ext}"
|
|
331
|
+
filename = pcm_filename.replace(f".{ext}", ".wav")
|
|
332
|
+
ctx.log(f"inlineData {len(base64_data)} {mime_type} {filename}")
|
|
333
|
+
|
|
334
|
+
relative_url, info = ctx.save_bytes_to_cache(
|
|
335
|
+
wav_data,
|
|
336
|
+
filename,
|
|
337
|
+
ctx.to_file_info(chat, {"cost": cost}),
|
|
338
|
+
)
|
|
339
|
+
|
|
340
|
+
audios.append(
|
|
341
|
+
{
|
|
342
|
+
"type": "audio_url",
|
|
343
|
+
"index": len(audios),
|
|
344
|
+
"audio_url": {
|
|
345
|
+
"url": relative_url,
|
|
346
|
+
},
|
|
347
|
+
}
|
|
348
|
+
)
|
|
276
349
|
content = " ".join(text_parts)
|
|
277
350
|
reasoning = " ".join(reasoning_parts)
|
|
278
351
|
|
|
@@ -288,6 +361,8 @@ def install(ctx):
|
|
|
288
361
|
choice["message"]["reasoning"] = reasoning
|
|
289
362
|
if len(images) > 0:
|
|
290
363
|
choice["message"]["images"] = images
|
|
364
|
+
if len(audios) > 0:
|
|
365
|
+
choice["message"]["audios"] = audios
|
|
291
366
|
choices.append(choice)
|
|
292
367
|
response["choices"] = choices
|
|
293
368
|
if "usageMetadata" in obj:
|
|
@@ -301,6 +376,3 @@ def install(ctx):
|
|
|
301
376
|
return ctx.log_json(self.to_response(response, chat, started_at))
|
|
302
377
|
|
|
303
378
|
ctx.add_provider(GoogleProvider)
|
|
304
|
-
|
|
305
|
-
|
|
306
|
-
__install__ = install
|
|
@@ -4,7 +4,7 @@ import time
|
|
|
4
4
|
import aiohttp
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def install_nvidia(ctx):
|
|
8
8
|
from llms.main import GeneratorBase
|
|
9
9
|
|
|
10
10
|
class NvidiaGenAi(GeneratorBase):
|
|
@@ -29,10 +29,11 @@ def install(ctx):
|
|
|
29
29
|
last_model = "/" in chat["model"] and chat["model"].split("/")[-1] or chat["model"]
|
|
30
30
|
filename = f"{last_model}_{seed}.png"
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
32
|
+
relative_url, info = ctx.save_image_to_cache(
|
|
33
|
+
base64,
|
|
34
|
+
filename,
|
|
35
|
+
ctx.to_file_info(chat, {"seed": seed}),
|
|
36
|
+
)
|
|
36
37
|
return {
|
|
37
38
|
"choices": [
|
|
38
39
|
{
|
|
@@ -102,6 +103,3 @@ def install(ctx):
|
|
|
102
103
|
return self.to_response(await self.response_json(response), chat, started_at)
|
|
103
104
|
|
|
104
105
|
ctx.add_provider(NvidiaGenAi)
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
__install__ = install
|
|
@@ -6,7 +6,7 @@ import time
|
|
|
6
6
|
import aiohttp
|
|
7
7
|
|
|
8
8
|
|
|
9
|
-
def
|
|
9
|
+
def install_openai(ctx):
|
|
10
10
|
from llms.main import GeneratorBase, OpenAiCompatible
|
|
11
11
|
|
|
12
12
|
class OpenAiProvider(OpenAiCompatible):
|
|
@@ -83,10 +83,7 @@ def install(ctx):
|
|
|
83
83
|
relative_url, info = ctx.save_image_to_cache(
|
|
84
84
|
image_data,
|
|
85
85
|
f"{chat['model']}-{i}.{ext}",
|
|
86
|
-
|
|
87
|
-
"model": chat["model"],
|
|
88
|
-
"prompt": ctx.last_user_prompt(chat),
|
|
89
|
-
},
|
|
86
|
+
ctx.to_file_info(chat),
|
|
90
87
|
)
|
|
91
88
|
images.append(
|
|
92
89
|
{
|
|
@@ -156,4 +153,4 @@ def install(ctx):
|
|
|
156
153
|
ctx.add_provider(OpenAiGenerator)
|
|
157
154
|
|
|
158
155
|
|
|
159
|
-
__install__ =
|
|
156
|
+
__install__ = install_openai
|
|
@@ -4,7 +4,7 @@ import time
|
|
|
4
4
|
import aiohttp
|
|
5
5
|
|
|
6
6
|
|
|
7
|
-
def
|
|
7
|
+
def install_openrouter(ctx):
|
|
8
8
|
from llms.main import GeneratorBase
|
|
9
9
|
|
|
10
10
|
# https://openrouter.ai/docs/guides/overview/multimodal/image-generation
|
|
@@ -16,6 +16,9 @@ def install(ctx):
|
|
|
16
16
|
|
|
17
17
|
def to_response(self, response, chat, started_at):
|
|
18
18
|
# go through all image responses and save them to cache
|
|
19
|
+
cost = None
|
|
20
|
+
if "usage" in response and "cost" in response["usage"]:
|
|
21
|
+
cost = response["usage"]["cost"]
|
|
19
22
|
for choice in response["choices"]:
|
|
20
23
|
if "message" in choice and "images" in choice["message"]:
|
|
21
24
|
for image in choice["message"]["images"]:
|
|
@@ -29,11 +32,9 @@ def install(ctx):
|
|
|
29
32
|
base64_data = parts[1]
|
|
30
33
|
model = chat["model"].split("/")[-1]
|
|
31
34
|
filename = f"{model}-{choice['index']}.{ext}"
|
|
32
|
-
info =
|
|
33
|
-
"
|
|
34
|
-
|
|
35
|
-
}
|
|
36
|
-
relative_url, info = ctx.save_image_to_cache(base64_data, filename, info)
|
|
35
|
+
relative_url, info = ctx.save_image_to_cache(
|
|
36
|
+
base64_data, filename, ctx.to_file_info(chat, {"cost": cost})
|
|
37
|
+
)
|
|
37
38
|
image["image_url"]["url"] = relative_url
|
|
38
39
|
|
|
39
40
|
return response
|
|
@@ -50,11 +51,13 @@ def install(ctx):
|
|
|
50
51
|
return ctx.log_json(self.to_response(json.loads(text), chat, started_at))
|
|
51
52
|
else:
|
|
52
53
|
chat_url = provider.chat_url
|
|
54
|
+
# remove tools
|
|
55
|
+
chat.pop("tools", None)
|
|
53
56
|
chat = await self.process_chat(chat, provider_id=self.id)
|
|
54
57
|
ctx.log(f"POST {chat_url}")
|
|
55
58
|
ctx.log(provider.chat_summary(chat))
|
|
56
59
|
# remove metadata if any (conflicts with some providers, e.g. Z.ai)
|
|
57
|
-
chat.pop("metadata", None)
|
|
60
|
+
metadata = chat.pop("metadata", None)
|
|
58
61
|
|
|
59
62
|
async with aiohttp.ClientSession() as session, session.post(
|
|
60
63
|
chat_url,
|
|
@@ -62,9 +65,8 @@ def install(ctx):
|
|
|
62
65
|
data=json.dumps(chat),
|
|
63
66
|
timeout=aiohttp.ClientTimeout(total=300),
|
|
64
67
|
) as response:
|
|
68
|
+
if metadata:
|
|
69
|
+
chat["metadata"] = metadata
|
|
65
70
|
return ctx.log_json(self.to_response(await self.response_json(response), chat, started_at))
|
|
66
71
|
|
|
67
72
|
ctx.add_provider(OpenRouterGenerator)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
__install__ = install
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
import json
|
|
2
|
+
import os
|
|
3
|
+
|
|
4
|
+
from aiohttp import web
|
|
5
|
+
|
|
6
|
+
default_prompts = [
|
|
7
|
+
{"name": "Helpful Assistant", "prompt": "You are a helpful assistant."},
|
|
8
|
+
]
|
|
9
|
+
|
|
10
|
+
|
|
11
|
+
# runs after providers are configured but before server is run
|
|
12
|
+
def install(ctx):
|
|
13
|
+
# helper to get user or default prompts
|
|
14
|
+
def get_user_prompts(request):
|
|
15
|
+
candidate_paths = []
|
|
16
|
+
# check if user is signed in
|
|
17
|
+
username = ctx.get_username(request)
|
|
18
|
+
if username:
|
|
19
|
+
# if signed in (Github OAuth), return the prompts for this user if exists
|
|
20
|
+
candidate_paths.append(os.path.join(ctx.get_user_path(username), "system_prompts", "prompts.json"))
|
|
21
|
+
# return default prompts for all users if exists
|
|
22
|
+
candidate_paths.append(os.path.join(ctx.get_user_path(), "system_prompts", "prompts.json"))
|
|
23
|
+
# otherwise return the default prompts from this repo
|
|
24
|
+
candidate_paths.append(os.path.join(ctx.path, "ui", "prompts.json"))
|
|
25
|
+
|
|
26
|
+
# iterate all candidate paths and when exists return its json
|
|
27
|
+
for path in candidate_paths:
|
|
28
|
+
if os.path.exists(path):
|
|
29
|
+
with open(path, encoding="utf-8") as f:
|
|
30
|
+
txt = f.read()
|
|
31
|
+
return json.loads(txt)
|
|
32
|
+
return default_prompts
|
|
33
|
+
|
|
34
|
+
# API Handler to get prompts
|
|
35
|
+
async def get_prompts(request):
|
|
36
|
+
prompts_json = get_user_prompts(request)
|
|
37
|
+
return web.json_response(prompts_json)
|
|
38
|
+
|
|
39
|
+
ctx.add_get("prompts.json", get_prompts)
|
|
40
|
+
|
|
41
|
+
|
|
42
|
+
# register install extension handler
|
|
43
|
+
__install__ = install
|
|
44
|
+
|
|
45
|
+
__order__ = -10
|
|
Binary file
|