llms-py 3.0.0b2__py3-none-any.whl → 3.0.0b4__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.
Files changed (51) hide show
  1. llms/__pycache__/main.cpython-314.pyc +0 -0
  2. llms/index.html +2 -1
  3. llms/llms.json +50 -17
  4. llms/main.py +484 -544
  5. llms/providers/__pycache__/anthropic.cpython-314.pyc +0 -0
  6. llms/providers/__pycache__/chutes.cpython-314.pyc +0 -0
  7. llms/providers/__pycache__/google.cpython-314.pyc +0 -0
  8. llms/providers/__pycache__/nvidia.cpython-314.pyc +0 -0
  9. llms/providers/__pycache__/openai.cpython-314.pyc +0 -0
  10. llms/providers/__pycache__/openrouter.cpython-314.pyc +0 -0
  11. llms/providers/anthropic.py +189 -0
  12. llms/providers/chutes.py +152 -0
  13. llms/providers/google.py +306 -0
  14. llms/providers/nvidia.py +107 -0
  15. llms/providers/openai.py +159 -0
  16. llms/providers/openrouter.py +70 -0
  17. llms/providers-extra.json +356 -0
  18. llms/providers.json +1 -1
  19. llms/ui/App.mjs +132 -60
  20. llms/ui/ai.mjs +76 -10
  21. llms/ui/app.css +65 -28
  22. llms/ui/ctx.mjs +196 -0
  23. llms/ui/index.mjs +75 -171
  24. llms/ui/lib/charts.mjs +9 -13
  25. llms/ui/markdown.mjs +6 -0
  26. llms/ui/{Analytics.mjs → modules/analytics.mjs} +76 -64
  27. llms/ui/{Main.mjs → modules/chat/ChatBody.mjs} +59 -135
  28. llms/ui/{SettingsDialog.mjs → modules/chat/SettingsDialog.mjs} +8 -8
  29. llms/ui/{ChatPrompt.mjs → modules/chat/index.mjs} +242 -46
  30. llms/ui/modules/layout.mjs +267 -0
  31. llms/ui/modules/model-selector.mjs +851 -0
  32. llms/ui/{Recents.mjs → modules/threads/Recents.mjs} +0 -2
  33. llms/ui/{Sidebar.mjs → modules/threads/index.mjs} +46 -44
  34. llms/ui/{threadStore.mjs → modules/threads/threadStore.mjs} +10 -7
  35. llms/ui/utils.mjs +82 -123
  36. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/METADATA +1 -1
  37. llms_py-3.0.0b4.dist-info/RECORD +65 -0
  38. llms/ui/Avatar.mjs +0 -86
  39. llms/ui/Brand.mjs +0 -52
  40. llms/ui/OAuthSignIn.mjs +0 -61
  41. llms/ui/ProviderIcon.mjs +0 -36
  42. llms/ui/ProviderStatus.mjs +0 -104
  43. llms/ui/SignIn.mjs +0 -65
  44. llms/ui/Welcome.mjs +0 -8
  45. llms/ui/model-selector.mjs +0 -686
  46. llms/ui.json +0 -1069
  47. llms_py-3.0.0b2.dist-info/RECORD +0 -58
  48. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/WHEEL +0 -0
  49. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/entry_points.txt +0 -0
  50. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/licenses/LICENSE +0 -0
  51. {llms_py-3.0.0b2.dist-info → llms_py-3.0.0b4.dist-info}/top_level.txt +0 -0
llms/ui/ctx.mjs ADDED
@@ -0,0 +1,196 @@
1
+
2
+ import { reactive } from 'vue'
3
+ import { EventBus, humanize, combinePaths } from "@servicestack/client"
4
+ import { storageObject } from './utils.mjs'
5
+
6
+ export class ExtensionScope {
7
+ constructor(ctx, id) {
8
+ /**@type {AppContext} */
9
+ this.ctx = ctx
10
+ this.id = id
11
+ this.baseUrl = `${ctx.ai.base}/ext/${this.id}`
12
+ this.storageKey = `llms.${this.id}`
13
+ this.state = reactive({})
14
+ }
15
+ getPrefs() {
16
+ return storageObject(this.storageKey)
17
+ }
18
+ setPrefs(o) {
19
+ storageObject(this.storageKey, Object.assign(this.getPrefs(), o))
20
+ }
21
+ get(url, options) {
22
+ return this.ctx.ai.get(combinePaths(this.baseUrl, url), options)
23
+ }
24
+ async getJson(url, options) {
25
+ return this.ctx.ai.getJson(combinePaths(this.baseUrl, url), options)
26
+ }
27
+ post(url, options) {
28
+ return this.ctx.ai.post(combinePaths(this.baseUrl, url), options)
29
+ }
30
+ async postJson(url, options) {
31
+ return this.ctx.ai.postJson(combinePaths(this.baseUrl, url), options)
32
+ }
33
+ }
34
+
35
+ export class AppContext {
36
+ constructor({ app, routes, ai, fmt, utils }) {
37
+ this.app = app
38
+ this.routes = routes
39
+ this.ai = ai
40
+ this.fmt = fmt
41
+ this.utils = utils
42
+ this._components = {}
43
+
44
+ this.state = reactive({})
45
+ this.events = new EventBus()
46
+ this.modalComponents = {}
47
+ this.extensions = []
48
+ this.layout = reactive(storageObject(`llms.layout`))
49
+ this.chatRequestFilters = []
50
+ this.chatResponseFilters = []
51
+ this.chatErrorFilters = []
52
+ this.createThreadFilters = []
53
+ this.updateThreadFilters = []
54
+ this.top = {}
55
+ this.left = {}
56
+
57
+ if (!Array.isArray(this.layout.hide)) {
58
+ this.layout.hide = []
59
+ }
60
+ Object.assign(app.config.globalProperties, {
61
+ $ctx: this,
62
+ $state: this.state,
63
+ $layout: this.layout,
64
+ $ai: ai,
65
+ $fmt: fmt,
66
+ $utils: utils,
67
+ })
68
+ Object.keys(app.config.globalProperties).forEach(key => {
69
+ globalThis[key] = app.config.globalProperties[key]
70
+ })
71
+ document.addEventListener('keydown', (e) => this.handleKeydown(e))
72
+ }
73
+ async init() {
74
+ Object.assign(this.state, await this.ai.init(this))
75
+ }
76
+ setGlobals(globals) {
77
+ Object.entries(globals).forEach(([name, global]) => {
78
+ const globalName = '$' + name
79
+ globalThis[globalName] = this.app.config.globalProperties[globalName] = global
80
+ this[name] = global
81
+ })
82
+ }
83
+ _validateIcons(icons) {
84
+ Object.entries(icons).forEach(([id, icon]) => {
85
+ if (!icon.component) {
86
+ console.error(`Icon ${id} is missing component property`)
87
+ }
88
+ icon.id = id
89
+ if (!icon.name) {
90
+ icon.name = humanize(id)
91
+ }
92
+ if (typeof icon.isActive != 'function') {
93
+ icon.isActive = () => false
94
+ }
95
+ })
96
+ return icons
97
+ }
98
+ setTopIcons(icons) {
99
+ Object.assign(this.top, this._validateIcons(icons))
100
+ }
101
+ setLeftIcons(icons) {
102
+ Object.assign(this.left, this._validateIcons(icons))
103
+ }
104
+ component(name, component) {
105
+ if (!name) return name
106
+ if (component) {
107
+ this._components[name] = component
108
+ }
109
+ return component || this._components[name] || this.app.component(name)
110
+ }
111
+ components(components) {
112
+ if (components) {
113
+ Object.keys(components).forEach(name => {
114
+ this._components[name] = components[name]
115
+ })
116
+ }
117
+ return this._components
118
+ }
119
+ scope(extension) {
120
+ return new ExtensionScope(this, extension)
121
+ }
122
+ modals(modals) {
123
+ Object.keys(modals).forEach(name => {
124
+ this.modalComponents[name] = modals[name]
125
+ this.component(name, modals[name])
126
+ })
127
+ }
128
+ openModal(name) {
129
+ const component = this.modalComponents[name]
130
+ if (!component) {
131
+ console.error(`Modal ${name} not found`)
132
+ return
133
+ }
134
+ console.debug('openModal', name)
135
+ this.router.push({ query: { open: name } })
136
+ this.events.publish('modal:open', name)
137
+ return component
138
+ }
139
+ closeModal(name) {
140
+ console.debug('closeModal', name)
141
+ this.router.push({ query: { open: undefined } })
142
+ this.events.publish('modal:close', name)
143
+ }
144
+ handleKeydown(e) {
145
+ if (e.key === 'Escape') {
146
+ const modal = this.router.currentRoute.value?.query?.open
147
+ if (modal) {
148
+ this.closeModal(modal)
149
+ }
150
+ this.events.publish(`keydown:Escape`, e)
151
+ }
152
+ }
153
+ setState(o) {
154
+ Object.assign(this.state, o)
155
+ //this.events.publish('update:state', this.state)
156
+ }
157
+ setLayout(o) {
158
+ Object.assign(this.layout, o)
159
+ storageObject(`llms.layout`, this.layout)
160
+ }
161
+ toggleLayout(key, toggle = undefined) {
162
+ const hide = toggle == undefined
163
+ ? !this.layout.hide.includes(key)
164
+ : !toggle
165
+ console.log('toggleLayout', key, hide)
166
+ if (hide) {
167
+ this.layout.hide.push(key)
168
+ } else {
169
+ this.layout.hide = this.layout.hide.filter(k => k != key)
170
+ }
171
+ storageObject(`llms.layout`, this.layout)
172
+ }
173
+ layoutVisible(key) {
174
+ return !this.layout.hide.includes(key)
175
+ }
176
+ getPrefs() {
177
+ return storageObject(this.ai.prefsKey)
178
+ }
179
+ setPrefs(o) {
180
+ storageObject(this.ai.prefsKey, Object.assign(this.getPrefs(), o))
181
+ }
182
+ toggleTop(name) {
183
+ console.log('toggleTop', name)
184
+ this.layout.top = this.layout.top == name ? undefined : name
185
+ storageObject(`llms.layout`, this.layout)
186
+ }
187
+ togglePath(path) {
188
+ const currentPath = this.router.currentRoute.value?.path
189
+ console.log('togglePath', path, currentPath)
190
+ if (currentPath == path) {
191
+ this.toggleLayout('left')
192
+ } else {
193
+ this.router.push({ path })
194
+ }
195
+ }
196
+ }
llms/ui/index.mjs CHANGED
@@ -1,176 +1,49 @@
1
1
 
2
- import { createApp, reactive, defineAsyncComponent } from 'vue'
2
+ import { createApp } from 'vue'
3
3
  import { createWebHistory, createRouter } from "vue-router"
4
- import { EventBus, humanize } from "@servicestack/client"
5
- import ServiceStackVue from "@servicestack/vue"
6
- import App from '/ui/App.mjs'
7
- import ai from '/ui/ai.mjs'
8
- import threadStore, { useThreadStore } from './threadStore.mjs'
9
- import SettingsDialog from '/ui/SettingsDialog.mjs'
10
- import ModelSelectorInstaller from '/ui/model-selector.mjs'
11
- import { storageObject } from './utils.mjs'
12
-
13
- const { config, models } = await ai.init()
14
- const MainComponent = defineAsyncComponent(() => import(ai.base + '/ui/Main.mjs'))
15
- const RecentsComponent = defineAsyncComponent(() => import(ai.base + '/ui/Recents.mjs'))
16
- const AnalyticsComponent = defineAsyncComponent(() => import(ai.base + '/ui/Analytics.mjs'))
4
+ import ServiceStackVue, { useFormatters } from "@servicestack/vue"
5
+ import App from './App.mjs'
6
+ import ai from './ai.mjs'
7
+ import LayoutModule from './modules/layout.mjs'
8
+ import ChatModule from './modules/chat/index.mjs'
9
+ import ThreadsModule from './modules/threads/index.mjs'
10
+ import ModelSelectorModule from './modules/model-selector.mjs'
11
+ import AnalyticsModule from './modules/analytics.mjs'
12
+ import { utilsFunctions, utilsFormatters } from './utils.mjs'
13
+ import { markdownFormatters } from './markdown.mjs'
14
+ import { AppContext } from './ctx.mjs'
17
15
 
18
16
  const Components = {
19
- SettingsDialog,
20
17
  }
21
18
 
22
- const BuiltInModules = [
23
- ModelSelectorInstaller,
24
- threadStore,
25
- ]
26
-
27
- const routes = [
28
- { path: '/', component: MainComponent },
29
- { path: '/c/:id', component: MainComponent },
30
- { path: '/recents', component: RecentsComponent },
31
- { path: '/analytics', component: AnalyticsComponent },
32
- { path: '/:fallback(.*)*', component: MainComponent }
33
- ]
34
- routes.forEach(r => r.path = ai.base + r.path)
35
- const router = createRouter({
36
- history: createWebHistory(),
37
- routes,
38
- })
39
-
40
-
41
- class AppExtension {
42
- constructor(ctx, ext) {
43
- this.ctx = ctx
44
- Object.assign(this, ext)
45
- this.baseUrl = `${ctx.ai.base}/ext/${this.id}`
46
- this.storageKey = `llms.${this.id}`
47
- if (!this.name) {
48
- this.name = humanize(this.id)
49
- }
50
- }
51
- storageObject(o) {
52
- return storageObject(this.storageKey, o)
53
- }
19
+ const BuiltInModules = {
20
+ LayoutModule,
21
+ ChatModule,
22
+ ThreadsModule,
23
+ ModelSelectorModule,
24
+ AnalyticsModule,
54
25
  }
55
26
 
56
- class AppContext {
57
- constructor({ app, config, models, extensions, routes, ai, router, threadStore, modules }) {
58
- this.app = app
59
- this.state = reactive({
60
- config,
61
- models,
62
- extensions,
63
- })
64
- this.routes = routes
65
- this.ai = ai
66
- this.router = router
67
- this.threadStore = threadStore
68
- this.modules = modules
69
- this.events = new EventBus()
70
- this.modalComponents = {}
71
- this.extensions = []
72
- this.layout = reactive(storageObject(`llms.layout`))
73
- this.chatRequestFilters = []
74
- this.chatResponseFilters = []
75
- this.chatErrorFilters = []
76
- this.createThreadFilters = []
77
- this.updateThreadFilters = []
78
-
79
- app.config.globalProperties.$ctx = this
80
- app.config.globalProperties.$state = this.state
81
- app.config.globalProperties.$layout = this.layout
82
- document.addEventListener('keydown', (e) => this.handleKeydown(e))
83
- }
84
- component(name, component) {
85
- if (!name) return name
86
- if (component) {
87
- this.app.component(name, component)
88
- }
89
- return component || this.app.component(name)
90
- }
91
- components(components) {
92
- Object.keys(components).forEach(name => {
93
- this.app.component(name, components[name])
94
- })
95
- }
96
- extension(extension) {
97
- const ext = new AppExtension(this, extension)
98
- this.extensions.push(ext)
99
- return ext
100
- }
101
- modals(modals) {
102
- Object.keys(modals).forEach(name => {
103
- this.modalComponents[name] = modals[name]
104
- this.component(name, modals[name])
105
- })
106
- }
107
- openModal(name) {
108
- const component = this.modalComponents[name]
109
- if (!component) {
110
- console.error(`Modal ${name} not found`)
111
- return
112
- }
113
- console.debug('openModal', name)
114
- this.router.push({ query: { open: name } })
115
- this.events.publish('modal:open', name)
116
- return component
117
- }
118
- closeModal(name) {
119
- console.debug('closeModal', name)
120
- this.router.push({ query: { open: undefined } })
121
- this.events.publish('modal:close', name)
122
- }
123
- handleKeydown(e) {
124
- if (e.key === 'Escape') {
125
- const modal = this.router.currentRoute.value?.query?.open
126
- if (modal) {
127
- this.closeModal(modal)
128
- }
129
- }
130
- }
131
- setState(o) {
132
- Object.assign(this.state, o)
133
- //this.events.publish('update:state', this.state)
134
- }
135
- setLayout(o) {
136
- Object.assign(this.layout, o)
137
- storageObject(`llms.layout`, this.layout)
138
- }
139
- getPrefs() {
140
- return storageObject(this.ai.prefsKey)
141
- }
142
- setPrefs(o) {
143
- storageObject(this.ai.prefsKey, o)
144
- }
145
- toggleLayout(o) {
146
- Object.keys(o).forEach(key => {
147
- this.layout[key] = this.layout[key] == o[key] ? undefined : o[key]
148
- })
149
- storageObject(`llms.layout`, this.layout)
150
- }
151
- getCurrentThread() {
152
- return this.threadStore.currentThread.value
153
- }
154
- }
155
27
 
156
28
  export async function createContext() {
157
- const app = createApp(App, { config, models })
29
+ const app = createApp(App)
158
30
 
159
- app.use(router)
160
31
  app.use(ServiceStackVue)
161
32
  Object.keys(Components).forEach(name => {
162
33
  app.component(name, Components[name])
163
34
  })
164
35
 
36
+ const fmt = Object.assign({}, useFormatters(), utilsFormatters(), markdownFormatters())
37
+ const utils = Object.assign({}, utilsFunctions())
38
+ const routes = []
165
39
 
166
- window.ai = app.config.globalProperties.$ai = ai
167
-
168
- // Load Extensions
169
- const exts = await (await fetch("/ext")).json()
40
+ const ctx = new AppContext({ app, routes, ai, fmt, utils })
41
+ app.provide('ctx', ctx)
42
+ await ctx.init()
170
43
 
171
44
  // Load modules in parallel
172
- const validExtensions = exts.filter(x => x.path);
173
- const modules = await Promise.all(validExtensions.map(async extension => {
45
+ const validExtensions = ctx.state.extensions.filter(x => x.path);
46
+ ctx.modules = await Promise.all(validExtensions.map(async extension => {
174
47
  try {
175
48
  const module = await import(extension.path)
176
49
  return { extension, module }
@@ -180,25 +53,18 @@ export async function createContext() {
180
53
  }
181
54
  }))
182
55
 
183
- const threadStore = useThreadStore()
184
-
185
- const ctx = new AppContext({
186
- app,
187
- config,
188
- models,
189
- routes,
190
- ai,
191
- router,
192
- threadStore,
193
- exts,
194
- modules,
56
+ // Install built-in modules sequentially
57
+ Object.entries(BuiltInModules).forEach(([name, module]) => {
58
+ try {
59
+ module.install(ctx)
60
+ console.log(`Installed built-in: ${name}`)
61
+ } catch (e) {
62
+ console.error(`Failed to install built-in ${name}:`, e)
63
+ }
195
64
  })
196
- app.provide('ctx', ctx)
197
-
198
- BuiltInModules.forEach(ext => ext.install(ctx))
199
65
 
200
- // Install sequentially
201
- for (const result of modules) {
66
+ // Install extensions sequentially
67
+ for (const result of ctx.modules) {
202
68
  if (result && result.module.default && result.module.default.install) {
203
69
  try {
204
70
  result.module.default.install(ctx)
@@ -209,5 +75,43 @@ export async function createContext() {
209
75
  }
210
76
  }
211
77
 
78
+ // Register all components with Vue
79
+ Object.entries(ctx._components).forEach(([name, component]) => {
80
+ app.component(name, component)
81
+ })
82
+
83
+ // Add fallback route and create router
84
+ routes.push({ path: '/:fallback(.*)*', component: ctx.component('Home') })
85
+ routes.forEach(r => r.path = ai.base + r.path)
86
+ ctx.router = createRouter({
87
+ history: createWebHistory(),
88
+ routes,
89
+ })
90
+ app.use(ctx.router)
91
+
92
+ ctx.router.beforeEach((to, from) => {
93
+ const title = to.meta.title || 'Chat'
94
+ console.log('beforeEach', to.path, title)
95
+ ctx.setLayout({ path: to.path })
96
+ ctx.setState({ title })
97
+ document.title = title
98
+ return true
99
+ })
100
+
101
+ if (ctx.layout.path && location.pathname === '/' && !location.search) {
102
+ console.log('redirecting to saved path: ', ctx.layout.path)
103
+ ctx.router.push({ path: ctx.layout.path })
104
+ }
105
+
106
+ // Load all extensions in parallel
107
+ await Promise.all(ctx.modules.filter(x => x.module.default && x.module.default.load).map(async result => {
108
+ try {
109
+ await result.module.default.load(ctx)
110
+ console.log(`Loaded extension: ${result.extension.id}`)
111
+ } catch (e) {
112
+ console.error(`Failed to load extension ${result.extension.id}:`, e)
113
+ }
114
+ }))
115
+
212
116
  return ctx
213
117
  }
llms/ui/lib/charts.mjs CHANGED
@@ -1,20 +1,16 @@
1
- import { useFormatters, useUtils } from "@servicestack/vue"
2
1
  import { Chart, registerables } from "chart.js"
3
2
  Chart.register(...registerables)
4
3
 
5
- const { humanifyMs, humanifyNumber, formatDate } = useFormatters()
6
- const { delay } = useUtils()
7
-
8
- export const resultLimits = [5,10,25,50,100]
4
+ export const resultLimits = [5, 10, 25, 50, 100]
9
5
  export const colors = [
10
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
11
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
6
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' }, //blue
7
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
12
8
  { background: 'rgba(153, 102, 255, 0.2)', border: 'rgb(153, 102, 255)' },
13
- { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
14
- { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
15
- { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
16
- { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
17
- { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
18
- { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
9
+ { background: 'rgba(54, 162, 235, 0.2)', border: 'rgb(54, 162, 235)' },
10
+ { background: 'rgba(255, 159, 64, 0.2)', border: 'rgb(255, 159, 64)' },
11
+ { background: 'rgba(67, 56, 202, 0.2)', border: 'rgb(67, 56, 202)' },
12
+ { background: 'rgba(255, 99, 132, 0.2)', border: 'rgb(255, 99, 132)' },
13
+ { background: 'rgba(14, 116, 144, 0.2)', border: 'rgb(14, 116, 144)' },
14
+ { background: 'rgba(162, 28, 175, 0.2)', border: 'rgb(162, 28, 175)' },
19
15
  { background: 'rgba(201, 203, 207, 0.2)', border: 'rgb(201, 203, 207)' },
20
16
  ]
llms/ui/markdown.mjs CHANGED
@@ -198,3 +198,9 @@ function toggleThink(id) {
198
198
  icon.classList.remove('rotate-180')
199
199
  }
200
200
  }
201
+
202
+ export function markdownFormatters() {
203
+ return {
204
+ markdown: renderMarkdown
205
+ }
206
+ }