summaryrefslogtreecommitdiffhomepage
path: root/packages/app/src/components/model-tooltip.tsx
blob: 14b4ba799bd4d119f337db09f4ef8a69daad7666 (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
import { Show, type Component } from "solid-js"

type InputKey = "text" | "image" | "audio" | "video" | "pdf"
type InputMap = Record<InputKey, boolean>

type ModelInfo = {
  id: string
  name: string
  provider: {
    name: string
  }
  capabilities?: {
    reasoning: boolean
    input: InputMap
  }
  modalities?: {
    input: Array<string>
  }
  reasoning?: boolean
  limit: {
    context: number
  }
}

function sourceName(model: ModelInfo) {
  const value = `${model.id} ${model.name}`.toLowerCase()

  if (/claude|anthropic/.test(value)) return "Anthropic"
  if (/gpt|o[1-4]|codex|openai/.test(value)) return "OpenAI"
  if (/gemini|palm|bard|google/.test(value)) return "Google"
  if (/grok|xai/.test(value)) return "xAI"
  if (/llama|meta/.test(value)) return "Meta"

  return model.provider.name
}

export const ModelTooltip: Component<{ model: ModelInfo; latest?: boolean; free?: boolean }> = (props) => {
  const title = () => {
    const tags: Array<string> = []
    if (props.latest) tags.push("Latest")
    if (props.free) tags.push("Free")
    const suffix = tags.length ? ` (${tags.join(", ")})` : ""
    return `${sourceName(props.model)} ${props.model.name}${suffix}`
  }
  const inputs = () => {
    if (props.model.capabilities) {
      const input = props.model.capabilities.input
      const order: Array<InputKey> = ["text", "image", "audio", "video", "pdf"]
      const entries = order.filter((key) => input[key])
      return entries.length ? entries.join(", ") : undefined
    }
    return props.model.modalities?.input?.join(", ")
  }
  const reasoning = () => {
    if (props.model.capabilities) return props.model.capabilities.reasoning ? "Allows reasoning" : "No reasoning"
    return props.model.reasoning ? "Allows reasoning" : "No reasoning"
  }
  const context = () => `Context limit ${props.model.limit.context.toLocaleString()}`

  return (
    <div class="flex flex-col gap-1 py-1">
      <div class="text-13-medium">{title()}</div>
      <Show when={inputs()}>
        {(value) => <div class="text-12-regular text-text-invert-base">Allows: {value()}</div>}
      </Show>
      <div class="text-12-regular text-text-invert-base">{reasoning()}</div>
      <div class="text-12-regular text-text-invert-base">{context()}</div>
    </div>
  )
}