models-dev.ts 3.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122
  1. import { DateTime, Effect, Scope, Stream } from "effect"
  2. import { Catalog } from "../catalog"
  3. import { EventV2 } from "../event"
  4. import { ModelV2 } from "../model"
  5. import { ModelsDev } from "../models-dev"
  6. import { PluginV2 } from "../plugin"
  7. import { ProviderV2 } from "../provider"
  8. function released(date: string) {
  9. const time = Date.parse(date)
  10. return DateTime.makeUnsafe(Number.isFinite(time) ? time : 0)
  11. }
  12. function cost(input: ModelsDev.Model["cost"]) {
  13. const base = {
  14. input: input?.input ?? 0,
  15. output: input?.output ?? 0,
  16. cache: {
  17. read: input?.cache_read ?? 0,
  18. write: input?.cache_write ?? 0,
  19. },
  20. }
  21. if (!input?.context_over_200k) return [base]
  22. return [
  23. base,
  24. {
  25. tier: {
  26. type: "context" as const,
  27. size: 200_000,
  28. },
  29. input: input.context_over_200k.input,
  30. output: input.context_over_200k.output,
  31. cache: {
  32. read: input.context_over_200k.cache_read ?? 0,
  33. write: input.context_over_200k.cache_write ?? 0,
  34. },
  35. },
  36. ]
  37. }
  38. function variants(model: ModelsDev.Model) {
  39. return Object.entries(model.experimental?.modes ?? {}).map(([id, item]) => ({
  40. id: ModelV2.VariantID.make(id),
  41. headers: { ...(item.provider?.headers ?? {}) },
  42. body: { ...(item.provider?.body ?? {}) },
  43. }))
  44. }
  45. export const ModelsDevPlugin = PluginV2.define({
  46. id: PluginV2.ID.make("models-dev"),
  47. effect: Effect.gen(function* () {
  48. const catalog = yield* Catalog.Service
  49. const modelsDev = yield* ModelsDev.Service
  50. const events = yield* EventV2.Service
  51. const scope = yield* Scope.Scope
  52. const transform = yield* catalog.transform()
  53. const refresh = Effect.fn("ModelsDevPlugin.refresh")(function* () {
  54. const data = yield* modelsDev.get()
  55. yield* transform((catalog) => {
  56. for (const item of Object.values(data)) {
  57. const providerID = ProviderV2.ID.make(item.id)
  58. catalog.provider.update(providerID, (provider) => {
  59. provider.name = item.name
  60. provider.env = [...item.env]
  61. provider.api = item.npm
  62. ? {
  63. type: "aisdk",
  64. package: item.npm,
  65. url: item.api,
  66. }
  67. : {
  68. type: "native",
  69. url: item.api,
  70. settings: {},
  71. }
  72. })
  73. for (const model of Object.values(item.models)) {
  74. const modelID = ModelV2.ID.make(model.id)
  75. catalog.model.update(providerID, modelID, (draft) => {
  76. draft.name = model.name
  77. draft.family = model.family ? ModelV2.Family.make(model.family) : undefined
  78. draft.api = model.provider?.npm
  79. ? {
  80. id: draft.api.id,
  81. type: "aisdk",
  82. package: model.provider?.npm,
  83. url: model.provider.api,
  84. }
  85. : {
  86. id: draft.api.id,
  87. type: "native",
  88. url: model.provider?.api,
  89. settings: {},
  90. }
  91. draft.capabilities = {
  92. tools: model.tool_call,
  93. input: [...(model.modalities?.input ?? [])],
  94. output: [...(model.modalities?.output ?? [])],
  95. }
  96. draft.variants = variants(model)
  97. draft.time.released = released(model.release_date)
  98. draft.cost = cost(model.cost)
  99. draft.status = model.status ?? "active"
  100. draft.enabled = true
  101. draft.limit = {
  102. context: model.limit.context,
  103. input: model.limit.input,
  104. output: model.limit.output,
  105. }
  106. })
  107. }
  108. }
  109. })
  110. })
  111. yield* refresh()
  112. yield* events.subscribe(ModelsDev.Event.Refreshed).pipe(
  113. Stream.runForEach(() => refresh()),
  114. Effect.forkScoped({ startImmediately: true }),
  115. )
  116. }),
  117. })