summaryrefslogtreecommitdiff
path: root/backend/api/src/model.zig
diff options
context:
space:
mode:
Diffstat (limited to 'backend/api/src/model.zig')
-rw-r--r--backend/api/src/model.zig123
1 files changed, 123 insertions, 0 deletions
diff --git a/backend/api/src/model.zig b/backend/api/src/model.zig
new file mode 100644
index 0000000..b35104f
--- /dev/null
+++ b/backend/api/src/model.zig
@@ -0,0 +1,123 @@
+const z = @import( "std" );
+const zap = @import( "zap" );
+const net = @import( "net-util.zig" );
+const u = struct {
+ usingnamespace @import( "util.zig" );
+ usingnamespace @import( "user.zig" );
+ usingnamespace @import( "userdefs.zig" );
+};
+
+const alloc = z.heap.page_allocator;
+
+const ArrayList = z.ArrayList;
+const OkRes = net.OkResponse;
+const ErrRes = net.ErrorResponse;
+
+const memeql = z.mem.eql;
+
+threadlocal var modelcache: ?u.JsonResponse([]Model) = null;
+
+pub const routes = .{
+ .@"models" = models
+};
+
+pub const ModelCapabilities = struct {
+ vision: u32 = 0,
+ remind: u32 = 0,
+ notes: u32 = 0,
+ web: u32 = 0,
+ thinker: ?u32 = 0,
+
+ pub const @"getty.db" = u.@"json.ignore.unknown";
+};
+
+pub const Model = struct {
+ name: []const u8,
+ modelname: []const u8,
+ capabilities: ModelCapabilities = .{},
+ system: []const u8 = "",
+ description: []const u8 = "",
+ short_description: []const u8 = "",
+ free: u32 = 0,
+ license: []const u8 = "",
+};
+
+pub const UserResponse = struct {
+ name: []const u8,
+ capabilities: ModelCapabilities = .{},
+ description: struct {
+ full: []const u8 = "",
+ short: []const u8 = "",
+ },
+ license: []const u8 = "",
+ free: u32 = 0,
+
+ pub fn fromModel( model: Model ) UserResponse {
+ return UserResponse {
+ .name = model.name,
+ .capabilities = model.capabilities,
+ .description = .{
+ .full = model.description,
+ .short = model.short_description
+ },
+ .free = model.free,
+ .license = model.license
+ };
+ }
+};
+
+pub fn canBeUsedByUser( model: Model, user: *const u.UserEntry ) bool {
+ if( memeql( u8, user.subscription_data.plan, "free" ) ) {
+ return model.free == 1;
+ }
+
+ return true;
+}
+
+pub fn loadModels() !*u.JsonResponse([]Model) {
+ const modelmap = try u.readFileAlloc( "../data/modelmap.json", alloc );
+ defer alloc.free( modelmap );
+
+ if( modelcache ) |cache| {
+ cache.deinit();
+ }
+
+ modelcache = u.jsonParseAlloc( []Model, modelmap, alloc ) catch |e| {
+ return e;
+ };
+
+ return &(modelcache.?);
+}
+
+pub fn getModelByDisplayName( modelname: []const u8 ) !*const Model {
+ const modelmap = loadModels() catch |e| {
+ z.debug.print( "failed to load model map: {any} {any}", .{ e, @errorReturnTrace() } );
+ return e;
+ };
+
+ for( modelmap.v ) |*model| {
+ if( memeql( u8, model.name, modelname ) ) {
+ return model;
+ }
+ }
+
+ return error.ModelNotFound;
+}
+
+///assuming endpoint for models is supposed to be pub for support page use?
+///route @/models
+pub fn models( r: zap.Request ) void {
+ const modelmap = loadModels() catch |e| {
+ z.debug.print( "failed to load model map: {any} {any}", .{ e, @errorReturnTrace() } );
+ return net.sendJson( r, .internal_server_error, ErrRes{ .msg = "failed to load model info" } );
+ };
+
+ var list = ArrayList( UserResponse ).init( alloc );
+ defer list.deinit();
+
+ for( modelmap.v ) |model| {
+ list.append( UserResponse.fromModel( model ) ) catch {};
+ }
+
+ net.sendJson( r, .ok, OkRes( .{ .models = list.items } ) );
+}