summaryrefslogtreecommitdiff
path: root/backend/api/src/model.zig
blob: b35104f10d11e968a50f0ea213732062ec9e30e6 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
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 } ) );
}