File size: 2,174 Bytes
60faa09
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
/**
 * Gradio Server provider adapter — uses @gradio/client to call any
 * deployed Gradio app (e.g. a HuggingFace Space).
 *
 * Model ID format:  gradio:<space-url>::<api-name>
 *   e.g.  gradio:https://my-user-my-space.hf.space::/chat
 *
 * Reference: https://huggingface.co/blog/introducing-gradio-server
 */
import { client } from "@gradio/client";

export async function callGradio({
  model, prompt, systemPrompt = "", history = [], apiKey,
}) {
  const spec = model.replace(/^gradio:/, "");
  const [url, apiName] = spec.split("::");
  if (!url) throw new Error("Gradio model spec must include a URL");

  const app = await client(url, {
    hfToken: apiKey?.startsWith("hf_") ? apiKey : undefined,
  });

  const firstEndpoint = apiName || "/predict";

  const gradioHistory = history.map((m) => [
    m.role === "user" ? m.content : null,
    m.role === "assistant" ? m.content : null,
  ]);

  const attempts = [
    { fn_index_or_api_name: firstEndpoint, data: [prompt, gradioHistory, systemPrompt] },
    { fn_index_or_api_name: firstEndpoint, data: [prompt, gradioHistory] },
    { fn_index_or_api_name: firstEndpoint, data: [{ text: prompt, history: gradioHistory, system: systemPrompt }] },
    { fn_index_or_api_name: firstEndpoint, data: [prompt] },
  ];

  let result = null;
  let lastErr = null;
  for (const attempt of attempts) {
    try {
      result = await app.predict(attempt.fn_index_or_api_name, attempt.data);
      break;
    } catch (e) {
      lastErr = e;
    }
  }
  if (!result) {
    throw new Error(`Gradio call failed. Last error: ${lastErr?.message || "unknown"}`);
  }

  const data = result?.data || result;
  let text = "";
  if (Array.isArray(data)) {
    const first = data[0];
    if (typeof first === "string") {
      text = first;
    } else if (first?.text) {
      text = first.text;
    } else if (Array.isArray(first)) {
      const lastAssistant = [...first].reverse().find((pair) => pair?.[1]);
      text = lastAssistant?.[1] || "";
    } else if (typeof first === "object") {
      text = JSON.stringify(first);
    }
  } else if (typeof data === "string") {
    text = data;
  }

  return { text, usage: null };
}