Spaces:
Runtime error
Runtime error
Mishig
commited on
Bypass spaces tools rate limit (#1167)
Browse files* Bypass spaces tools rate limit
* DRY
* optimize
* use `context` for userId & ip
* lint
* user `userName`
* fix merge conflict
* rn `userName` -> `username`
- chart/env/prod.yaml +1 -0
- package-lock.json +12 -3
- package.json +1 -0
- src/lib/server/textGeneration/tools.ts +5 -9
- src/lib/server/textGeneration/types.ts +2 -0
- src/lib/server/tools/documentParser.ts +6 -3
- src/lib/server/tools/images/editing.ts +6 -3
- src/lib/server/tools/images/generation.ts +6 -3
- src/lib/server/tools/index.ts +5 -9
- src/lib/server/tools/utils.ts +27 -2
- src/routes/conversation/[id]/+server.ts +2 -0
chart/env/prod.yaml
CHANGED
|
@@ -356,6 +356,7 @@ externalSecrets:
|
|
| 356 |
ADMIN_API_SECRET: "hub-prod-chat-ui-admin-api-secret"
|
| 357 |
USAGE_LIMITS: "hub-prod-chat-ui-usage-limits"
|
| 358 |
MESSAGES_BEFORE_LOGIN: "hub-prod-chat-ui-messages-before-login"
|
|
|
|
| 359 |
|
| 360 |
autoscaling:
|
| 361 |
enabled: true
|
|
|
|
| 356 |
ADMIN_API_SECRET: "hub-prod-chat-ui-admin-api-secret"
|
| 357 |
USAGE_LIMITS: "hub-prod-chat-ui-usage-limits"
|
| 358 |
MESSAGES_BEFORE_LOGIN: "hub-prod-chat-ui-messages-before-login"
|
| 359 |
+
IP_TOKEN_SECRET: "hub-prod-chat-ui-ip-token-secret"
|
| 360 |
|
| 361 |
autoscaling:
|
| 362 |
enabled: true
|
package-lock.json
CHANGED
|
@@ -26,6 +26,7 @@
|
|
| 26 |
"highlight.js": "^11.7.0",
|
| 27 |
"image-size": "^1.0.2",
|
| 28 |
"ip-address": "^9.0.5",
|
|
|
|
| 29 |
"jsdom": "^22.0.0",
|
| 30 |
"json5": "^2.2.3",
|
| 31 |
"marked": "^12.0.1",
|
|
@@ -5725,9 +5726,9 @@
|
|
| 5725 |
}
|
| 5726 |
},
|
| 5727 |
"node_modules/jose": {
|
| 5728 |
-
"version": "
|
| 5729 |
-
"resolved": "https://registry.npmjs.org/jose/-/jose-
|
| 5730 |
-
"integrity": "sha512-
|
| 5731 |
"funding": {
|
| 5732 |
"url": "https://github.com/sponsors/panva"
|
| 5733 |
}
|
|
@@ -6803,6 +6804,14 @@
|
|
| 6803 |
"url": "https://github.com/sponsors/panva"
|
| 6804 |
}
|
| 6805 |
},
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 6806 |
"node_modules/openid-client/node_modules/object-hash": {
|
| 6807 |
"version": "2.2.0",
|
| 6808 |
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
|
|
|
| 26 |
"highlight.js": "^11.7.0",
|
| 27 |
"image-size": "^1.0.2",
|
| 28 |
"ip-address": "^9.0.5",
|
| 29 |
+
"jose": "^5.3.0",
|
| 30 |
"jsdom": "^22.0.0",
|
| 31 |
"json5": "^2.2.3",
|
| 32 |
"marked": "^12.0.1",
|
|
|
|
| 5726 |
}
|
| 5727 |
},
|
| 5728 |
"node_modules/jose": {
|
| 5729 |
+
"version": "5.3.0",
|
| 5730 |
+
"resolved": "https://registry.npmjs.org/jose/-/jose-5.3.0.tgz",
|
| 5731 |
+
"integrity": "sha512-IChe9AtAE79ru084ow8jzkN2lNrG3Ntfiv65Cvj9uOCE2m5LNsdHG+9EbxWxAoWRF9TgDOqLN5jm08++owDVRg==",
|
| 5732 |
"funding": {
|
| 5733 |
"url": "https://github.com/sponsors/panva"
|
| 5734 |
}
|
|
|
|
| 6804 |
"url": "https://github.com/sponsors/panva"
|
| 6805 |
}
|
| 6806 |
},
|
| 6807 |
+
"node_modules/openid-client/node_modules/jose": {
|
| 6808 |
+
"version": "4.15.5",
|
| 6809 |
+
"resolved": "https://registry.npmjs.org/jose/-/jose-4.15.5.tgz",
|
| 6810 |
+
"integrity": "sha512-jc7BFxgKPKi94uOvEmzlSWFFe2+vASyXaKUpdQKatWAESU2MWjDfFf0fdfc83CDKcA5QecabZeNLyfhe3yKNkg==",
|
| 6811 |
+
"funding": {
|
| 6812 |
+
"url": "https://github.com/sponsors/panva"
|
| 6813 |
+
}
|
| 6814 |
+
},
|
| 6815 |
"node_modules/openid-client/node_modules/object-hash": {
|
| 6816 |
"version": "2.2.0",
|
| 6817 |
"resolved": "https://registry.npmjs.org/object-hash/-/object-hash-2.2.0.tgz",
|
package.json
CHANGED
|
@@ -71,6 +71,7 @@
|
|
| 71 |
"highlight.js": "^11.7.0",
|
| 72 |
"image-size": "^1.0.2",
|
| 73 |
"ip-address": "^9.0.5",
|
|
|
|
| 74 |
"jsdom": "^22.0.0",
|
| 75 |
"json5": "^2.2.3",
|
| 76 |
"marked": "^12.0.1",
|
|
|
|
| 71 |
"highlight.js": "^11.7.0",
|
| 72 |
"image-size": "^1.0.2",
|
| 73 |
"ip-address": "^9.0.5",
|
| 74 |
+
"jose": "^5.3.0",
|
| 75 |
"jsdom": "^22.0.0",
|
| 76 |
"json5": "^2.2.3",
|
| 77 |
"marked": "^12.0.1",
|
src/lib/server/textGeneration/tools.ts
CHANGED
|
@@ -49,7 +49,7 @@ export function pickTools(
|
|
| 49 |
}
|
| 50 |
|
| 51 |
async function* runTool(
|
| 52 |
-
|
| 53 |
tools: BackendTool[],
|
| 54 |
call: ToolCall
|
| 55 |
): AsyncGenerator<MessageUpdate, ToolResult | undefined, undefined> {
|
|
@@ -74,12 +74,7 @@ async function* runTool(
|
|
| 74 |
};
|
| 75 |
try {
|
| 76 |
try {
|
| 77 |
-
const toolResult = yield* tool.call(call.parameters,
|
| 78 |
-
conv,
|
| 79 |
-
messages,
|
| 80 |
-
preprompt,
|
| 81 |
-
assistant,
|
| 82 |
-
});
|
| 83 |
if (toolResult.status === ToolResultStatus.Error) {
|
| 84 |
yield {
|
| 85 |
type: MessageUpdateType.Tool,
|
|
@@ -123,10 +118,11 @@ async function* runTool(
|
|
| 123 |
}
|
| 124 |
|
| 125 |
export async function* runTools(
|
| 126 |
-
|
| 127 |
tools: BackendTool[],
|
| 128 |
preprompt?: string
|
| 129 |
): AsyncGenerator<MessageUpdate, ToolResult[], undefined> {
|
|
|
|
| 130 |
const calls: ToolCall[] = [];
|
| 131 |
|
| 132 |
const messagesWithFilesPrompt = messages.map((message, idx) => {
|
|
@@ -181,7 +177,7 @@ export async function* runTools(
|
|
| 181 |
Date.now() - pickToolStartTime
|
| 182 |
);
|
| 183 |
|
| 184 |
-
const toolContext: BackendToolContext = { conv, messages, preprompt, assistant };
|
| 185 |
const toolResults: (ToolResult | undefined)[] = yield* mergeAsyncGenerators(
|
| 186 |
calls.map((call) => runTool(toolContext, tools, call))
|
| 187 |
);
|
|
|
|
| 49 |
}
|
| 50 |
|
| 51 |
async function* runTool(
|
| 52 |
+
ctx: BackendToolContext,
|
| 53 |
tools: BackendTool[],
|
| 54 |
call: ToolCall
|
| 55 |
): AsyncGenerator<MessageUpdate, ToolResult | undefined, undefined> {
|
|
|
|
| 74 |
};
|
| 75 |
try {
|
| 76 |
try {
|
| 77 |
+
const toolResult = yield* tool.call(call.parameters, ctx);
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 78 |
if (toolResult.status === ToolResultStatus.Error) {
|
| 79 |
yield {
|
| 80 |
type: MessageUpdateType.Tool,
|
|
|
|
| 118 |
}
|
| 119 |
|
| 120 |
export async function* runTools(
|
| 121 |
+
ctx: TextGenerationContext,
|
| 122 |
tools: BackendTool[],
|
| 123 |
preprompt?: string
|
| 124 |
): AsyncGenerator<MessageUpdate, ToolResult[], undefined> {
|
| 125 |
+
const { endpoint, conv, messages, assistant, ip, username } = ctx;
|
| 126 |
const calls: ToolCall[] = [];
|
| 127 |
|
| 128 |
const messagesWithFilesPrompt = messages.map((message, idx) => {
|
|
|
|
| 177 |
Date.now() - pickToolStartTime
|
| 178 |
);
|
| 179 |
|
| 180 |
+
const toolContext: BackendToolContext = { conv, messages, preprompt, assistant, ip, username };
|
| 181 |
const toolResults: (ToolResult | undefined)[] = yield* mergeAsyncGenerators(
|
| 182 |
calls.map((call) => runTool(toolContext, tools, call))
|
| 183 |
);
|
src/lib/server/textGeneration/types.ts
CHANGED
|
@@ -14,4 +14,6 @@ export interface TextGenerationContext {
|
|
| 14 |
webSearch: boolean;
|
| 15 |
toolsPreference: Record<string, boolean>;
|
| 16 |
promptedAt: Date;
|
|
|
|
|
|
|
| 17 |
}
|
|
|
|
| 14 |
webSearch: boolean;
|
| 15 |
toolsPreference: Record<string, boolean>;
|
| 16 |
promptedAt: Date;
|
| 17 |
+
ip: string;
|
| 18 |
+
username?: string;
|
| 19 |
}
|
src/lib/server/tools/documentParser.ts
CHANGED
|
@@ -1,6 +1,6 @@
|
|
| 1 |
import type { BackendTool } from ".";
|
| 2 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 3 |
-
import { callSpace } from "./utils";
|
| 4 |
import { downloadFile } from "$lib/server/files/downloadFile";
|
| 5 |
|
| 6 |
type PdfParserInput = [Blob /* pdf */, string /* filename */];
|
|
@@ -23,7 +23,7 @@ const documentParser: BackendTool = {
|
|
| 23 |
required: true,
|
| 24 |
},
|
| 25 |
},
|
| 26 |
-
async *call({ fileMessageIndex, fileIndex }, { conv, messages }) {
|
| 27 |
fileMessageIndex = Number(fileMessageIndex);
|
| 28 |
fileIndex = Number(fileIndex);
|
| 29 |
|
|
@@ -47,10 +47,13 @@ const documentParser: BackendTool = {
|
|
| 47 |
.then((file) => fetch(`data:${file.mime};base64,${file.value}`))
|
| 48 |
.then((res) => res.blob());
|
| 49 |
|
|
|
|
|
|
|
| 50 |
const outputs = await callSpace<PdfParserInput, PdfParserOutput>(
|
| 51 |
"huggingchat/document-parser",
|
| 52 |
"predict",
|
| 53 |
-
[fileBlob, file.name]
|
|
|
|
| 54 |
);
|
| 55 |
|
| 56 |
let documentMarkdown = outputs[0];
|
|
|
|
| 1 |
import type { BackendTool } from ".";
|
| 2 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 3 |
+
import { callSpace, getIpToken } from "./utils";
|
| 4 |
import { downloadFile } from "$lib/server/files/downloadFile";
|
| 5 |
|
| 6 |
type PdfParserInput = [Blob /* pdf */, string /* filename */];
|
|
|
|
| 23 |
required: true,
|
| 24 |
},
|
| 25 |
},
|
| 26 |
+
async *call({ fileMessageIndex, fileIndex }, { conv, messages, ip, username }) {
|
| 27 |
fileMessageIndex = Number(fileMessageIndex);
|
| 28 |
fileIndex = Number(fileIndex);
|
| 29 |
|
|
|
|
| 47 |
.then((file) => fetch(`data:${file.mime};base64,${file.value}`))
|
| 48 |
.then((res) => res.blob());
|
| 49 |
|
| 50 |
+
const ipToken = await getIpToken(ip, username);
|
| 51 |
+
|
| 52 |
const outputs = await callSpace<PdfParserInput, PdfParserOutput>(
|
| 53 |
"huggingchat/document-parser",
|
| 54 |
"predict",
|
| 55 |
+
[fileBlob, file.name],
|
| 56 |
+
ipToken
|
| 57 |
);
|
| 58 |
|
| 59 |
let documentMarkdown = outputs[0];
|
src/lib/server/tools/images/editing.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { BackendTool } from "..";
|
|
| 2 |
import { uploadFile } from "../../files/uploadFile";
|
| 3 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 4 |
import { MessageUpdateType } from "$lib/types/MessageUpdate";
|
| 5 |
-
import { callSpace, type GradioImage } from "../utils";
|
| 6 |
import { downloadFile } from "$lib/server/files/downloadFile";
|
| 7 |
|
| 8 |
type ImageEditingInput = [
|
|
@@ -37,7 +37,7 @@ const imageEditing: BackendTool = {
|
|
| 37 |
required: true,
|
| 38 |
},
|
| 39 |
},
|
| 40 |
-
async *call({ prompt, fileMessageIndex, fileIndex }, { conv, messages }) {
|
| 41 |
prompt = String(prompt);
|
| 42 |
fileMessageIndex = Number(fileMessageIndex);
|
| 43 |
fileIndex = Number(fileIndex);
|
|
@@ -68,6 +68,8 @@ const imageEditing: BackendTool = {
|
|
| 68 |
.then((file) => fetch(`data:${file.mime};base64,${file.value}`))
|
| 69 |
.then((res) => res.blob());
|
| 70 |
|
|
|
|
|
|
|
| 71 |
const outputs = await callSpace<ImageEditingInput, ImageEditingOutput>(
|
| 72 |
"multimodalart/cosxl",
|
| 73 |
"run_edit",
|
|
@@ -77,7 +79,8 @@ const imageEditing: BackendTool = {
|
|
| 77 |
"", // negative prompt
|
| 78 |
7, // guidance scale
|
| 79 |
20, // steps
|
| 80 |
-
]
|
|
|
|
| 81 |
);
|
| 82 |
|
| 83 |
const outputImage = await fetch(outputs[0].url)
|
|
|
|
| 2 |
import { uploadFile } from "../../files/uploadFile";
|
| 3 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 4 |
import { MessageUpdateType } from "$lib/types/MessageUpdate";
|
| 5 |
+
import { callSpace, getIpToken, type GradioImage } from "../utils";
|
| 6 |
import { downloadFile } from "$lib/server/files/downloadFile";
|
| 7 |
|
| 8 |
type ImageEditingInput = [
|
|
|
|
| 37 |
required: true,
|
| 38 |
},
|
| 39 |
},
|
| 40 |
+
async *call({ prompt, fileMessageIndex, fileIndex }, { conv, messages, ip, username }) {
|
| 41 |
prompt = String(prompt);
|
| 42 |
fileMessageIndex = Number(fileMessageIndex);
|
| 43 |
fileIndex = Number(fileIndex);
|
|
|
|
| 68 |
.then((file) => fetch(`data:${file.mime};base64,${file.value}`))
|
| 69 |
.then((res) => res.blob());
|
| 70 |
|
| 71 |
+
const ipToken = await getIpToken(ip, username);
|
| 72 |
+
|
| 73 |
const outputs = await callSpace<ImageEditingInput, ImageEditingOutput>(
|
| 74 |
"multimodalart/cosxl",
|
| 75 |
"run_edit",
|
|
|
|
| 79 |
"", // negative prompt
|
| 80 |
7, // guidance scale
|
| 81 |
20, // steps
|
| 82 |
+
],
|
| 83 |
+
ipToken
|
| 84 |
);
|
| 85 |
|
| 86 |
const outputImage = await fetch(outputs[0].url)
|
src/lib/server/tools/images/generation.ts
CHANGED
|
@@ -2,7 +2,7 @@ import type { BackendTool } from "..";
|
|
| 2 |
import { uploadFile } from "../../files/uploadFile";
|
| 3 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 4 |
import { MessageUpdateType } from "$lib/types/MessageUpdate";
|
| 5 |
-
import { callSpace, type GradioImage } from "../utils";
|
| 6 |
|
| 7 |
type ImageGenerationInput = [
|
| 8 |
number /* number (numeric value between 1 and 8) in 'Number of Images' Slider component */,
|
|
@@ -44,7 +44,9 @@ const imageGeneration: BackendTool = {
|
|
| 44 |
default: 1024,
|
| 45 |
},
|
| 46 |
},
|
| 47 |
-
async *call({ prompt, numberOfImages }, { conv }) {
|
|
|
|
|
|
|
| 48 |
const outputs = await callSpace<ImageGenerationInput, ImageGenerationOutput>(
|
| 49 |
"ByteDance/Hyper-SDXL-1Step-T2I",
|
| 50 |
"/process_image",
|
|
@@ -54,7 +56,8 @@ const imageGeneration: BackendTool = {
|
|
| 54 |
512, // number in 'Image Width' Number component
|
| 55 |
String(prompt), // prompt
|
| 56 |
Math.floor(Math.random() * 1000), // seed random
|
| 57 |
-
]
|
|
|
|
| 58 |
);
|
| 59 |
const imageBlobs = await Promise.all(
|
| 60 |
outputs[0].map((output) =>
|
|
|
|
| 2 |
import { uploadFile } from "../../files/uploadFile";
|
| 3 |
import { ToolResultStatus } from "$lib/types/Tool";
|
| 4 |
import { MessageUpdateType } from "$lib/types/MessageUpdate";
|
| 5 |
+
import { callSpace, getIpToken, type GradioImage } from "../utils";
|
| 6 |
|
| 7 |
type ImageGenerationInput = [
|
| 8 |
number /* number (numeric value between 1 and 8) in 'Number of Images' Slider component */,
|
|
|
|
| 44 |
default: 1024,
|
| 45 |
},
|
| 46 |
},
|
| 47 |
+
async *call({ prompt, numberOfImages }, { conv, ip, username }) {
|
| 48 |
+
const ipToken = await getIpToken(ip, username);
|
| 49 |
+
|
| 50 |
const outputs = await callSpace<ImageGenerationInput, ImageGenerationOutput>(
|
| 51 |
"ByteDance/Hyper-SDXL-1Step-T2I",
|
| 52 |
"/process_image",
|
|
|
|
| 56 |
512, // number in 'Image Width' Number component
|
| 57 |
String(prompt), // prompt
|
| 58 |
Math.floor(Math.random() * 1000), // seed random
|
| 59 |
+
],
|
| 60 |
+
ipToken
|
| 61 |
);
|
| 62 |
const imageBlobs = await Promise.all(
|
| 63 |
outputs[0].map((output) =>
|
src/lib/server/tools/index.ts
CHANGED
|
@@ -1,6 +1,3 @@
|
|
| 1 |
-
import type { Assistant } from "$lib/types/Assistant";
|
| 2 |
-
import type { Conversation } from "$lib/types/Conversation";
|
| 3 |
-
import type { Message } from "$lib/types/Message";
|
| 4 |
import type { MessageUpdate } from "$lib/types/MessageUpdate";
|
| 5 |
import type { Tool, ToolResultError, ToolResultSuccess } from "$lib/types/Tool";
|
| 6 |
|
|
@@ -11,13 +8,12 @@ import imageGeneration from "./images/generation";
|
|
| 11 |
import documentParser from "./documentParser";
|
| 12 |
import fetchUrl from "./web/url";
|
| 13 |
import websearch from "./web/search";
|
|
|
|
| 14 |
|
| 15 |
-
export
|
| 16 |
-
|
| 17 |
-
messages
|
| 18 |
-
|
| 19 |
-
assistant?: Pick<Assistant, "rag" | "dynamicPrompt" | "generateSettings">;
|
| 20 |
-
}
|
| 21 |
|
| 22 |
// typescript can't narrow a discriminated union after applying a generic like Omit to it
|
| 23 |
// so we have to define the omitted types and create a new union
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
import type { MessageUpdate } from "$lib/types/MessageUpdate";
|
| 2 |
import type { Tool, ToolResultError, ToolResultSuccess } from "$lib/types/Tool";
|
| 3 |
|
|
|
|
| 8 |
import documentParser from "./documentParser";
|
| 9 |
import fetchUrl from "./web/url";
|
| 10 |
import websearch from "./web/search";
|
| 11 |
+
import type { TextGenerationContext } from "../textGeneration/types";
|
| 12 |
|
| 13 |
+
export type BackendToolContext = Pick<
|
| 14 |
+
TextGenerationContext,
|
| 15 |
+
"conv" | "messages" | "assistant" | "ip" | "username"
|
| 16 |
+
> & { preprompt?: string };
|
|
|
|
|
|
|
| 17 |
|
| 18 |
// typescript can't narrow a discriminated union after applying a generic like Omit to it
|
| 19 |
// so we have to define the omitted types and create a new union
|
src/lib/server/tools/utils.ts
CHANGED
|
@@ -1,5 +1,6 @@
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { Client } from "@gradio/client";
|
|
|
|
| 3 |
|
| 4 |
export type GradioImage = {
|
| 5 |
path: string;
|
|
@@ -16,9 +17,21 @@ type GradioResponse = {
|
|
| 16 |
export async function callSpace<TInput extends unknown[], TOutput extends unknown[]>(
|
| 17 |
name: string,
|
| 18 |
func: string,
|
| 19 |
-
parameters: TInput
|
|
|
|
| 20 |
): Promise<TOutput> {
|
| 21 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 22 |
hf_token: (env.HF_TOKEN ?? env.HF_ACCESS_TOKEN) as unknown as `hf_${string}`,
|
| 23 |
});
|
| 24 |
return await client
|
|
@@ -26,4 +39,16 @@ export async function callSpace<TInput extends unknown[], TOutput extends unknow
|
|
| 26 |
.then((res) => (res as unknown as GradioResponse).data as TOutput);
|
| 27 |
}
|
| 28 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 29 |
export { toolHasName } from "$lib/utils/tools";
|
|
|
|
| 1 |
import { env } from "$env/dynamic/private";
|
| 2 |
import { Client } from "@gradio/client";
|
| 3 |
+
import { SignJWT } from "jose";
|
| 4 |
|
| 5 |
export type GradioImage = {
|
| 6 |
path: string;
|
|
|
|
| 17 |
export async function callSpace<TInput extends unknown[], TOutput extends unknown[]>(
|
| 18 |
name: string,
|
| 19 |
func: string,
|
| 20 |
+
parameters: TInput,
|
| 21 |
+
ipToken: string | undefined
|
| 22 |
): Promise<TOutput> {
|
| 23 |
+
class CustomClient extends Client {
|
| 24 |
+
fetch(input: RequestInfo | URL, init?: RequestInit): Promise<Response> {
|
| 25 |
+
init = init || {};
|
| 26 |
+
init.headers = {
|
| 27 |
+
...(init.headers || {}),
|
| 28 |
+
...(ipToken ? { "X-IP-Token": ipToken } : {}),
|
| 29 |
+
};
|
| 30 |
+
return super.fetch(input, init);
|
| 31 |
+
}
|
| 32 |
+
}
|
| 33 |
+
|
| 34 |
+
const client = await CustomClient.connect(name, {
|
| 35 |
hf_token: (env.HF_TOKEN ?? env.HF_ACCESS_TOKEN) as unknown as `hf_${string}`,
|
| 36 |
});
|
| 37 |
return await client
|
|
|
|
| 39 |
.then((res) => (res as unknown as GradioResponse).data as TOutput);
|
| 40 |
}
|
| 41 |
|
| 42 |
+
export async function getIpToken(ip: string, username?: string) {
|
| 43 |
+
const ipTokenSecret = env.IP_TOKEN_SECRET;
|
| 44 |
+
if (!ipTokenSecret) {
|
| 45 |
+
return;
|
| 46 |
+
}
|
| 47 |
+
return await new SignJWT({ ip, user: username })
|
| 48 |
+
.setProtectedHeader({ alg: "HS256" })
|
| 49 |
+
.setIssuedAt()
|
| 50 |
+
.setExpirationTime("1m")
|
| 51 |
+
.sign(new TextEncoder().encode(ipTokenSecret));
|
| 52 |
+
}
|
| 53 |
+
|
| 54 |
export { toolHasName } from "$lib/utils/tools";
|
src/routes/conversation/[id]/+server.ts
CHANGED
|
@@ -407,6 +407,8 @@ export async function POST({ request, locals, params, getClientAddress }) {
|
|
| 407 |
webSearch: webSearch ?? false,
|
| 408 |
toolsPreference: toolsPreferences ?? {},
|
| 409 |
promptedAt,
|
|
|
|
|
|
|
| 410 |
};
|
| 411 |
// run the text generation and send updates to the client
|
| 412 |
for await (const event of textGeneration(ctx)) await update(event);
|
|
|
|
| 407 |
webSearch: webSearch ?? false,
|
| 408 |
toolsPreference: toolsPreferences ?? {},
|
| 409 |
promptedAt,
|
| 410 |
+
ip: getClientAddress(),
|
| 411 |
+
username: locals.user?.username,
|
| 412 |
};
|
| 413 |
// run the text generation and send updates to the client
|
| 414 |
for await (const event of textGeneration(ctx)) await update(event);
|