├── .github
└── workflows
│ ├── deploy.yml
│ └── deployNew.yml
├── .gitignore
├── LICENSE
├── README.md
├── docs.json
├── docs
├── audio
│ ├── music
│ │ └── index.mdx
│ ├── stt
│ │ └── index.mdx
│ └── tts
│ │ └── index.mdx
├── image
│ ├── anything
│ │ └── index.mdx
│ ├── controlnet
│ │ └── index.mdx
│ ├── dall-e
│ │ └── index.mdx
│ ├── fast_sdxl
│ │ └── index.mdx
│ ├── fasts-sdxl
│ │ └── index.mdx
│ ├── kandinsky
│ │ └── index.mdx
│ ├── sdxl
│ │ └── index.mdx
│ ├── sh
│ │ └── index.mdx
│ ├── upscale
│ │ └── index.mdx
│ └── vision
│ │ └── index.mdx
├── index.mdx
├── text
│ ├── alan
│ │ └── index.mdx
│ ├── anthropic
│ │ └── index.mdx
│ ├── filter
│ │ └── index.mdx
│ ├── google
│ │ └── index.mdx
│ ├── gpt-new
│ │ └── index.mdx
│ ├── groq
│ │ └── index.mdx
│ ├── huggingface
│ │ └── index.mdx
│ ├── openchat
│ │ └── index.mdx
│ ├── other
│ │ └── index.mdx
│ ├── pawan
│ │ └── index.mdx
│ └── translate
│ │ └── index.mdx
└── video
│ └── zelescope
│ └── index.mdx
├── package-lock.json
├── package.json
├── src
├── db
│ ├── mq.ts
│ ├── redis.ts
│ └── supabase.ts
├── handlers
│ ├── audio.ts
│ ├── image.ts
│ ├── text.ts
│ └── video.ts
├── index.ts
├── middlewares
│ ├── captchas
│ │ ├── hcaptchas.ts
│ │ └── turnstile.ts
│ ├── geo.ts
│ └── key.ts
├── models
│ ├── audio
│ │ ├── music.ts
│ │ ├── stt.ts
│ │ └── tts.ts
│ ├── image
│ │ ├── anything.ts
│ │ ├── controlnet.ts
│ │ ├── dall-e.ts
│ │ ├── sh.ts
│ │ ├── upscale.ts
│ │ └── vision.ts
│ ├── text
│ │ ├── alan.ts
│ │ ├── anthropic.ts
│ │ ├── filter.ts
│ │ ├── google.ts
│ │ ├── gpt-new.ts
│ │ ├── groq.ts
│ │ ├── openchat.ts
│ │ └── pawan.ts
│ └── video
│ │ └── zelescope.ts
├── routes
│ ├── chart.routes.ts
│ ├── data.routes.ts
│ ├── dataset.routes.ts
│ ├── key.routes.ts
│ ├── models.routes.ts
│ ├── other.routes.ts
│ ├── payment.routes.ts
│ ├── runpod.routes.ts
│ └── storage.routes.ts
├── rundocs.ts
└── utils
│ ├── chart.ts
│ ├── ciclic.ts
│ ├── datasets.ts
│ ├── db.ts
│ ├── docs.ts
│ ├── key.ts
│ ├── keywords.ts
│ ├── log.ts
│ ├── ms.ts
│ ├── plugins.ts
│ ├── runpod.ts
│ ├── stats.ts
│ └── tokenizer.ts
└── tsconfig.json
/.github/workflows/deploy.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to SSH VPS
2 |
3 | on:
4 | push:
5 | branches:
6 | - main
7 |
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | # Checkout code from the main branch
14 | - name: Checkout code
15 | uses: actions/checkout@v2
16 |
17 | # Install Node.js and PM2
18 |
19 | # Connect to remote server via SSH to start the bot using PM2
20 | - name: Start API with PM2
21 | uses: appleboy/ssh-action@master
22 | with:
23 | host: ${{ secrets.HOST }}
24 | username: ${{ secrets.USERNAME }}
25 | password: ${{ secrets.PASSWORD }}
26 | script: |
27 | cd /home/loick/github/turing-api
28 | npm run git
29 | npm i
30 | npm run build
31 | nvm use 18
32 | pm2 reload TuringAPI
33 |
--------------------------------------------------------------------------------
/.github/workflows/deployNew.yml:
--------------------------------------------------------------------------------
1 | name: Deploy to SSH VPS
2 |
3 | on:
4 | push:
5 | branches:
6 | - new
7 |
8 | jobs:
9 | deploy:
10 | runs-on: ubuntu-latest
11 |
12 | steps:
13 | # Checkout code from the main branch
14 | - name: Checkout code
15 | uses: actions/checkout@v2
16 |
17 | # Connect to remote server via SSH to start the bot using PM2
18 | - name: Build and reload API
19 | uses: appleboy/ssh-action@master
20 | with:
21 | host: ${{ secrets.HOST }}
22 | username: ${{ secrets.USERNAME }}
23 | password: ${{ secrets.PASSWORD }}
24 | script: |
25 | export NVM_DIR="$HOME/.nvm"
26 | [ -s "$NVM_DIR/nvm.sh" ] && \. "$NVM_DIR/nvm.sh"
27 | [ -s "$NVM_DIR/bash_completion" ] && \. "$NVM_DIR/bash_completion"
28 | cd /home/trident/github/turing-api-new
29 | nvm use 20
30 | PATH="$HOME/.nvm/versions/node/v20.0.0/bin:$PATH"
31 | npm run git
32 | npm i
33 | rm -r dist
34 | npm run build
35 | pm2 reload TuringAPINew
36 |
--------------------------------------------------------------------------------
/.gitignore:
--------------------------------------------------------------------------------
1 | # Logs
2 | logs
3 | *.log
4 | npm-debug.log*
5 | yarn-debug.log*
6 | yarn-error.log*
7 | lerna-debug.log*
8 |
9 | # Diagnostic reports (https://nodejs.org/api/report.html)
10 | report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
11 | guilds.txt
12 |
13 | # Runtime data
14 | pids
15 | *.pid
16 | *.seed
17 | *.pid.lock
18 |
19 | # Directory for instrumented libs generated by jscoverage/JSCover
20 | lib-cov
21 |
22 | # Coverage directory used by tools like istanbul
23 | coverage
24 | *.lcov
25 |
26 | # nyc test coverage
27 | .nyc_output
28 |
29 | # Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
30 | .grunt
31 |
32 | # Bower dependency directory (https://bower.io/)
33 | bower_components
34 |
35 | # node-waf configuration
36 | .lock-wscript
37 |
38 | # Compiled binary addons (https://nodejs.org/api/addons.html)
39 | build/Release
40 |
41 | # Dependency directories
42 | node_modules/
43 | jspm_packages/
44 |
45 | # TypeScript v1 declaration files
46 | typings/
47 |
48 | # TypeScript cache
49 | *.tsbuildinfo
50 |
51 | # Optional npm cache directory
52 | .npm
53 |
54 | # Optional eslint cache
55 | .eslintcache
56 |
57 | # Microbundle cache
58 | .rpt2_cache/
59 | .rts2_cache_cjs/
60 | .rts2_cache_es/
61 | .rts2_cache_umd/
62 |
63 | # Optional REPL history
64 | .node_repl_history
65 |
66 | # Output of 'npm pack'
67 | *.tgz
68 |
69 | # Yarn Integrity file
70 | .yarn-integrity
71 |
72 | # dotenv environment variables file
73 | .env
74 | .env.test
75 |
76 | # parcel-bundler cache (https://parceljs.org/)
77 | .cache
78 |
79 | # Next.js build output
80 | .next
81 |
82 | # Nuxt.js build / generate output
83 | .nuxt
84 | dist
85 |
86 | # Gatsby files
87 | .cache/
88 | # Comment in the public line in if your project uses Gatsby and *not* Next.js
89 | # https://nextjs.org/blog/next-9-1#public-directory-support
90 | # public
91 |
92 | # vuepress build output
93 | .vuepress/dist
94 |
95 | # Serverless directories
96 | .serverless/
97 |
98 | # FuseBox cache
99 | .fusebox/
100 |
101 | # DynamoDB Local files
102 | .dynamodb/
103 |
104 | # TernJS port file
105 | .tern-port
106 |
107 | temp/
108 | temp/**/*
109 | g-keyfile.json
--------------------------------------------------------------------------------
/README.md:
--------------------------------------------------------------------------------
1 | # Turing API
2 |
3 | 
4 |
5 | Turing API is the official API from TuringAI and the best API for AI.
6 |
7 | ## Guide
8 |
9 | We are working on libraries/sdks for the most famous programming languages.
10 |
11 | Right now you can use the API by doing normal HTTP requests.
12 |
13 | You can find the documentation [here](https://docs.turing.sh).
14 |
15 | ## Contributing
16 |
17 | You can contribute to the API by making a pull request.
18 |
19 | If you want to contribute to our libraries you need to go to the next repos:
20 |
21 | - [JavaScript](https://github.com/TuringAI-Team/turing-library/tree/typescript)
22 | - [Python](https://github.com/TuringAI-Team/turing-library/tree/python)
23 |
24 | If you want to contribute to the documentation you need to go to the [models folder in this repo](https://github.com/TuringAI-Team/turing-ai-api/tree/new/src/models) or the docs file under the utils folder. You cannot contribute to the documentation by modifying the docs folder since the docs folder is autogenerated using the docs.ts filter based on the data extracted by the models.
25 | You can run the docs.ts file by doing `npm run docs` and you can check [docs.page documentation](https://docs.page) to learn how to use the docs.ts file.
26 |
--------------------------------------------------------------------------------
/docs.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "TuringAI API",
3 | "description": "TuringAI API Documentation. The best API for AI.",
4 | "theme": "#A179D9",
5 | "favicon": "https://turing.sh/neon.png",
6 | "logo": "https://turing.sh/neon.png",
7 | "twitter": "Turing_AI_",
8 | "anchors": [
9 | {
10 | "title": "Homepage",
11 | "icon": "house",
12 | "link": "/"
13 | },
14 | {
15 | "title": "Discord",
16 | "icon": "discord",
17 | "link": "https://link.turing.sh/discord"
18 | }
19 | ],
20 | "docsearch": {
21 | "appId": "57EGN36JTA",
22 | "apiKey": "64c360c5620075061cf3018f0c801aaa",
23 | "indexName": "TuringAI-Team"
24 | },
25 | "sidebar": [
26 | [
27 | "Text Models",
28 | [
29 | [
30 | "Alan",
31 | "/text/alan"
32 | ],
33 | [
34 | "Anthropic Models",
35 | "/text/anthropic"
36 | ],
37 | [
38 | "Text Filter",
39 | "/text/filter"
40 | ],
41 | [
42 | "Google Models",
43 | "/text/google"
44 | ],
45 | [
46 | "OpenAI models",
47 | "/text/gpt-new"
48 | ],
49 | [
50 | "GroqCloud models",
51 | "/text/groq"
52 | ],
53 | [
54 | "OpenChat models",
55 | "/text/openchat"
56 | ],
57 | [
58 | "Pawan.krd models",
59 | "/text/pawan"
60 | ]
61 | ]
62 | ],
63 | [
64 | "Image Models",
65 | [
66 | [
67 | "Anything models",
68 | "/image/anything"
69 | ],
70 | [
71 | "Controlnet",
72 | "/image/controlnet"
73 | ],
74 | [
75 | "Dall-e 3",
76 | "/image/dall-e"
77 | ],
78 | [
79 | "Fast SDXL",
80 | "/image/fast_sdxl"
81 | ],
82 | [
83 | "Kandinsky 2.1",
84 | "/image/kandinsky"
85 | ],
86 | [
87 | "Stablehorde",
88 | "/image/sh"
89 | ],
90 | [
91 | "Upscale models",
92 | "/image/upscale"
93 | ],
94 | [
95 | "Image vision",
96 | "/image/vision"
97 | ]
98 | ]
99 | ],
100 | [
101 | "Audio Models",
102 | [
103 | [
104 | "Music generation",
105 | "/audio/music"
106 | ],
107 | [
108 | "Speech to text",
109 | "/audio/stt"
110 | ],
111 | [
112 | "Text to speech",
113 | "/audio/tts"
114 | ]
115 | ]
116 | ],
117 | [
118 | "Video Models",
119 | [
120 | [
121 | "Zelescope",
122 | "/video/zelescope"
123 | ]
124 | ]
125 | ]
126 | ]
127 | }
--------------------------------------------------------------------------------
/docs/audio/music/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Music generation
3 | ---
4 |
5 | # Music generation
6 | POST *https://api.turing.sh/audio/music*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: small, medium, melody, large
19 | - Default: small
20 |
21 | - **duration**
22 | - Type: number
23 | - Required: false
24 | - Default: 8
25 |
26 | - **stream**
27 | - Type: boolean
28 | - Required: false
29 |
30 | ## Response
31 |
32 | Response not defined yet
33 |
34 |
35 | ## Examples
36 |
37 |
38 | ```typescript
39 | import axios from "axios";
40 | (async () => {
41 | let response = await axios({
42 | method: "post",
43 | url: 'https://api.turing.sh/audio/music',
44 | headers: {
45 | "Content-Type": "application/json",
46 | Authorization: "Bearer YOUR_API_KEY",
47 | "x-captcha-token": "Captcha key"
48 | },
49 | data: {
50 | "prompt": "string",
51 | "model": "small",
52 | "duration": 8
53 | },
54 | })
55 | })();
56 | ```
57 | ```python
58 | import requests
59 | import json
60 | response = requests.post(
61 | "https://api.turing.sh/audio/music",
62 | headers={
63 | "Content-Type": "application/json",
64 | "Authorization": "Bearer YOUR_API_KEY",
65 | "x-captcha-token": "Captcha key"
66 | },
67 | data=json.dumps({
68 | "prompt": "string",
69 | "model": "small",
70 | "duration": 8
71 | }),
72 | )
73 | ```
74 |
--------------------------------------------------------------------------------
/docs/audio/stt/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Speech to text
3 | ---
4 |
5 | # Speech to text
6 | POST *https://api.turing.sh/audio/stt*
7 |
8 | ## Parameters
9 |
10 |
11 | - **model**
12 | - Type: string
13 | - Required: false
14 | - Description: Model to use for speech to text
15 | - Options: whisper, fast-whisper, gladia
16 | - Default: fast-whisper
17 |
18 | - **audio**
19 | - Type: string
20 | - Required: true
21 | - Description: Audio URL to transcribe
22 |
23 | - **diarization**
24 | - Type: boolean
25 | - Required: false
26 | - Description: Whether to use diarization or not
27 |
28 | - **type**
29 | - Type: string
30 | - Required: false
31 | - Options: tiny, base, small, medium, large-v1, large-v2
32 | - Default: base
33 |
34 | - **stream**
35 | - Type: boolean
36 | - Required: false
37 |
38 | ## Response
39 |
40 | Response not defined yet
41 |
42 |
43 | ## Examples
44 |
45 |
46 | ```typescript
47 | import axios from "axios";
48 | (async () => {
49 | let response = await axios({
50 | method: "post",
51 | url: 'https://api.turing.sh/audio/stt',
52 | headers: {
53 | "Content-Type": "application/json",
54 | Authorization: "Bearer YOUR_API_KEY",
55 | "x-captcha-token": "Captcha key"
56 | },
57 | data: {
58 | "model": "fast-whisper",
59 | "audio": "string",
60 | "type": "base"
61 | },
62 | })
63 | })();
64 | ```
65 | ```python
66 | import requests
67 | import json
68 | response = requests.post(
69 | "https://api.turing.sh/audio/stt",
70 | headers={
71 | "Content-Type": "application/json",
72 | "Authorization": "Bearer YOUR_API_KEY",
73 | "x-captcha-token": "Captcha key"
74 | },
75 | data=json.dumps({
76 | "model": "fast-whisper",
77 | "audio": "string",
78 | "type": "base"
79 | }),
80 | )
81 | ```
82 |
--------------------------------------------------------------------------------
/docs/audio/tts/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Text to speech
3 | ---
4 |
5 | # Text to speech
6 | POST *https://api.turing.sh/audio/tts*
7 |
8 | ## Parameters
9 |
10 |
11 | - **model**
12 | - Type: string
13 | - Required: true
14 | - Options: google, elevenlabs
15 | - Default: google
16 |
17 | - **voice**
18 | - Type: string
19 | - Required: true
20 | - Description: Voice to use (elevenlabs only)
21 | - Default: adam
22 |
23 | - **text**
24 | - Type: string
25 | - Required: true
26 | - Description: Text to convert to speech
27 |
28 | - **language**
29 | - Type: string
30 | - Required: true
31 | - Description: Language code to use (google only)
32 | - Default: en
33 |
34 | - **slow**
35 | - Type: boolean
36 | - Required: false
37 | - Description: Speak slowly (google only)
38 |
39 | - **stream**
40 | - Type: boolean
41 | - Required: false
42 |
43 | ## Response
44 |
45 | Response not defined yet
46 |
47 |
48 | ## Examples
49 |
50 |
51 | ```typescript
52 | import axios from "axios";
53 | (async () => {
54 | let response = await axios({
55 | method: "post",
56 | url: 'https://api.turing.sh/audio/tts',
57 | headers: {
58 | "Content-Type": "application/json",
59 | Authorization: "Bearer YOUR_API_KEY",
60 | "x-captcha-token": "Captcha key"
61 | },
62 | data: {
63 | "model": "google",
64 | "voice": "adam",
65 | "text": "string",
66 | "language": "en"
67 | },
68 | })
69 | })();
70 | ```
71 | ```python
72 | import requests
73 | import json
74 | response = requests.post(
75 | "https://api.turing.sh/audio/tts",
76 | headers={
77 | "Content-Type": "application/json",
78 | "Authorization": "Bearer YOUR_API_KEY",
79 | "x-captcha-token": "Captcha key"
80 | },
81 | data=json.dumps({
82 | "model": "google",
83 | "voice": "adam",
84 | "text": "string",
85 | "language": "en"
86 | }),
87 | )
88 | ```
89 |
--------------------------------------------------------------------------------
/docs/image/anything/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Anything models
3 | ---
4 |
5 | # Anything models
6 | POST *https://api.turing.sh/image/anything*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 | - Description: Prompt to generate the image
15 |
16 | - **steps**
17 | - Type: number
18 | - Required: false
19 | - Default: 100
20 |
21 | - **number**
22 | - Type: number
23 | - Required: false
24 | - Default: 1
25 |
26 | - **negative_prompt**
27 | - Type: string
28 | - Required: false
29 | - Default: disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces
30 |
31 | - **guidance_scale**
32 | - Type: number
33 | - Required: false
34 | - Default: 4
35 |
36 | - **width**
37 | - Type: number
38 | - Required: false
39 | - Default: 512
40 |
41 | - **height**
42 | - Type: number
43 | - Required: false
44 | - Default: 512
45 |
46 | - **cfg_scale**
47 | - Type: number
48 | - Required: false
49 | - Default: 4
50 |
51 | - **stream**
52 | - Type: boolean
53 | - Required: false
54 | - Default: true
55 |
56 | ## Response
57 |
58 | Response not defined yet
59 |
60 |
61 | ## Examples
62 |
63 |
64 | ```typescript
65 | import axios from "axios";
66 | (async () => {
67 | let response = await axios({
68 | method: "post",
69 | url: 'https://api.turing.sh/image/anything',
70 | headers: {
71 | "Content-Type": "application/json",
72 | Authorization: "Bearer YOUR_API_KEY",
73 | "x-captcha-token": "Captcha key"
74 | },
75 | data: {
76 | "prompt": "string",
77 | "steps": 100,
78 | "number": 1,
79 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
80 | "guidance_scale": 4,
81 | "width": 512,
82 | "height": 512,
83 | "cfg_scale": 4,
84 | "stream": true
85 | },
86 | })
87 | })();
88 | ```
89 | ```python
90 | import requests
91 | import json
92 | response = requests.post(
93 | "https://api.turing.sh/image/anything",
94 | headers={
95 | "Content-Type": "application/json",
96 | "Authorization": "Bearer YOUR_API_KEY",
97 | "x-captcha-token": "Captcha key"
98 | },
99 | data=json.dumps({
100 | "prompt": "string",
101 | "steps": 100,
102 | "number": 1,
103 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
104 | "guidance_scale": 4,
105 | "width": 512,
106 | "height": 512,
107 | "cfg_scale": 4,
108 | "stream": true
109 | }),
110 | )
111 | ```
112 |
--------------------------------------------------------------------------------
/docs/image/controlnet/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Controlnet
3 | ---
4 |
5 | # Controlnet
6 | POST *https://api.turing.sh/image/controlnet*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: true
18 | - Options: normal, canny, hough, hed, depth2img, pose, seg
19 | - Default: normal
20 |
21 | - **image**
22 | - Type: string
23 | - Required: true
24 |
25 | - **stream**
26 | - Type: boolean
27 | - Required: false
28 |
29 | ## Response
30 |
31 | Response not defined yet
32 |
33 |
34 | ## Examples
35 |
36 |
37 | ```typescript
38 | import axios from "axios";
39 | (async () => {
40 | let response = await axios({
41 | method: "post",
42 | url: 'https://api.turing.sh/image/controlnet',
43 | headers: {
44 | "Content-Type": "application/json",
45 | Authorization: "Bearer YOUR_API_KEY",
46 | "x-captcha-token": "Captcha key"
47 | },
48 | data: {
49 | "prompt": "string",
50 | "model": "normal",
51 | "image": "string"
52 | },
53 | })
54 | })();
55 | ```
56 | ```python
57 | import requests
58 | import json
59 | response = requests.post(
60 | "https://api.turing.sh/image/controlnet",
61 | headers={
62 | "Content-Type": "application/json",
63 | "Authorization": "Bearer YOUR_API_KEY",
64 | "x-captcha-token": "Captcha key"
65 | },
66 | data=json.dumps({
67 | "prompt": "string",
68 | "model": "normal",
69 | "image": "string"
70 | }),
71 | )
72 | ```
73 |
--------------------------------------------------------------------------------
/docs/image/dall-e/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Dall-e 3
3 | ---
4 |
5 | # Dall-e 3
6 | POST *https://api.turing.sh/image/dall-e*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: false
14 |
15 | - **number**
16 | - Type: number
17 | - Required: true
18 | - Description: Number of images to generate
19 | - Options: 1, 2, 3, 4
20 | - Default: 1
21 |
22 | - **size**
23 | - Type: string
24 | - Required: false
25 | - Options: 512x512, 256x256, 1024x1024
26 | - Default: 512x512
27 |
28 | - **image**
29 | - Type: string
30 | - Required: false
31 | - Description: Image you want to vary
32 |
33 | - **stream**
34 | - Type: boolean
35 | - Required: false
36 |
37 | ## Response
38 |
39 |
40 | - **cost**
41 | - Type: number
42 |
43 | - **results**
44 | - Type: array
45 |
46 | - **status**
47 | - Type: string
48 |
49 | - **progress**
50 | - Type: number
51 |
52 | - **id**
53 | - Type: string
54 |
55 | - **done**
56 | - Type: boolean
57 |
58 | ## Examples
59 |
60 |
61 | ```typescript
62 | import axios from "axios";
63 | (async () => {
64 | let response = await axios({
65 | method: "post",
66 | url: 'https://api.turing.sh/image/dall-e',
67 | headers: {
68 | "Content-Type": "application/json",
69 | Authorization: "Bearer YOUR_API_KEY",
70 | "x-captcha-token": "Captcha key"
71 | },
72 | data: {
73 | "number": 1,
74 | "size": "512x512"
75 | },
76 | })
77 | })();
78 | ```
79 | ```python
80 | import requests
81 | import json
82 | response = requests.post(
83 | "https://api.turing.sh/image/dall-e",
84 | headers={
85 | "Content-Type": "application/json",
86 | "Authorization": "Bearer YOUR_API_KEY",
87 | "x-captcha-token": "Captcha key"
88 | },
89 | data=json.dumps({
90 | "number": 1,
91 | "size": "512x512"
92 | }),
93 | )
94 | ```
95 |
--------------------------------------------------------------------------------
/docs/image/fast_sdxl/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Fast SDXL
3 | ---
4 |
5 | # Fast SDXL
6 | POST *https://api.turing.sh/image/fast_sdxl*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 | - Description: Prompt to generate the image
15 |
16 | - **steps**
17 | - Type: number
18 | - Required: false
19 | - Default: 4
20 |
21 | - **number**
22 | - Type: number
23 | - Required: false
24 | - Description: Number of images to generate
25 | - Default: 1
26 |
27 | - **negative_prompt**
28 | - Type: string
29 | - Required: false
30 | - Default: disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces
31 |
32 | - **width**
33 | - Type: number
34 | - Required: false
35 | - Default: 1024
36 |
37 | - **height**
38 | - Type: number
39 | - Required: false
40 | - Default: 1024
41 |
42 | - **model_version**
43 | - Type: string
44 | - Required: false
45 | - Options: lcm, turbo
46 | - Default: lcm
47 |
48 | - **stream**
49 | - Type: boolean
50 | - Required: false
51 | - Default: true
52 |
53 | ## Response
54 |
55 |
56 | - **cost**
57 | - Type: number
58 |
59 | - **results**
60 | - Type: array
61 |
62 | - **status**
63 | - Type: string
64 |
65 | - **progress**
66 | - Type: number
67 |
68 | - **id**
69 | - Type: string
70 |
71 | ## Examples
72 |
73 |
74 | ```typescript
75 | import axios from "axios";
76 | (async () => {
77 | let response = await axios({
78 | method: "post",
79 | url: 'https://api.turing.sh/image/fast_sdxl',
80 | headers: {
81 | "Content-Type": "application/json",
82 | Authorization: "Bearer YOUR_API_KEY",
83 | "x-captcha-token": "Captcha key"
84 | },
85 | data: {
86 | "prompt": "string",
87 | "steps": 4,
88 | "number": 1,
89 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
90 | "width": 1024,
91 | "height": 1024,
92 | "model_version": "lcm",
93 | "stream": true
94 | },
95 | })
96 | })();
97 | ```
98 | ```python
99 | import requests
100 | import json
101 | response = requests.post(
102 | "https://api.turing.sh/image/fast_sdxl",
103 | headers={
104 | "Content-Type": "application/json",
105 | "Authorization": "Bearer YOUR_API_KEY",
106 | "x-captcha-token": "Captcha key"
107 | },
108 | data=json.dumps({
109 | "prompt": "string",
110 | "steps": 4,
111 | "number": 1,
112 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
113 | "width": 1024,
114 | "height": 1024,
115 | "model_version": "lcm",
116 | "stream": true
117 | }),
118 | )
119 | ```
120 |
--------------------------------------------------------------------------------
/docs/image/fasts-sdxl/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Fast SDXL
3 | ---
4 |
5 | # Fast SDXL
6 | POST *https://api.turing.sh/image/fasts-sdxl*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 | - Description: Prompt to generate the image
15 |
16 | - **steps**
17 | - Type: number
18 | - Required: false
19 | - Default: 4
20 |
21 | - **number**
22 | - Type: number
23 | - Required: false
24 | - Description: Number of images to generate
25 | - Default: 1
26 |
27 | - **negative_prompt**
28 | - Type: string
29 | - Required: false
30 | - Default: disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces
31 |
32 | - **width**
33 | - Type: number
34 | - Required: false
35 | - Default: 1024
36 |
37 | - **height**
38 | - Type: number
39 | - Required: false
40 | - Default: 1024
41 |
42 | - **model_version**
43 | - Type: string
44 | - Required: false
45 | - Options: lcm, turbo
46 | - Default: lcm
47 |
48 | - **stream**
49 | - Type: boolean
50 | - Required: false
51 | - Default: true
52 |
53 | ## Response
54 |
55 |
56 | - **cost**
57 | - Type: number
58 |
59 | - **results**
60 | - Type: array
61 |
62 | - **status**
63 | - Type: string
64 |
65 | - **progress**
66 | - Type: number
67 |
68 | - **id**
69 | - Type: string
70 |
71 | ## Examples
72 |
73 |
74 | ```typescript
75 | import axios from "axios";
76 | (async () => {
77 | let response = await axios({
78 | method: "post",
79 | url: 'https://api.turing.sh/image/fasts-sdxl',
80 | headers: {
81 | "Content-Type": "application/json",
82 | Authorization: "Bearer YOUR_API_KEY",
83 | "x-captcha-token": "Captcha key"
84 | },
85 | data: {
86 | "prompt": "string",
87 | "steps": 4,
88 | "number": 1,
89 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
90 | "width": 1024,
91 | "height": 1024,
92 | "model_version": "lcm",
93 | "stream": true
94 | },
95 | })
96 | })();
97 | ```
98 | ```python
99 | import requests
100 | import json
101 | response = requests.post(
102 | "https://api.turing.sh/image/fasts-sdxl",
103 | headers={
104 | "Content-Type": "application/json",
105 | "Authorization": "Bearer YOUR_API_KEY",
106 | "x-captcha-token": "Captcha key"
107 | },
108 | data=json.dumps({
109 | "prompt": "string",
110 | "steps": 4,
111 | "number": 1,
112 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
113 | "width": 1024,
114 | "height": 1024,
115 | "model_version": "lcm",
116 | "stream": true
117 | }),
118 | )
119 | ```
120 |
--------------------------------------------------------------------------------
/docs/image/kandinsky/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Kandinsky 2.1
3 | ---
4 |
5 | # Kandinsky 2.1
6 | POST *https://api.turing.sh/image/kandinsky*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 | - Description: Prompt to generate the image
15 |
16 | - **steps**
17 | - Type: number
18 | - Required: false
19 | - Default: 100
20 |
21 | - **number**
22 | - Type: number
23 | - Required: false
24 | - Description: Number of images to generate
25 | - Default: 1
26 |
27 | - **negative_prompt**
28 | - Type: string
29 | - Required: false
30 | - Default: disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces
31 |
32 | - **guidance_scale**
33 | - Type: number
34 | - Required: false
35 | - Default: 4
36 |
37 | - **width**
38 | - Type: number
39 | - Required: false
40 | - Default: 512
41 |
42 | - **height**
43 | - Type: number
44 | - Required: false
45 | - Default: 512
46 |
47 | - **cfg_scale**
48 | - Type: number
49 | - Required: false
50 | - Default: 4
51 |
52 | - **model_version**
53 | - Type: string
54 | - Required: false
55 | - Options: 2.1, 2.2
56 | - Default: 2.2
57 |
58 | - **stream**
59 | - Type: boolean
60 | - Required: false
61 | - Default: true
62 |
63 | ## Response
64 |
65 |
66 | - **cost**
67 | - Type: number
68 |
69 | - **results**
70 | - Type: array
71 |
72 | - **status**
73 | - Type: string
74 |
75 | - **progress**
76 | - Type: number
77 |
78 | - **id**
79 | - Type: string
80 |
81 | ## Examples
82 |
83 |
84 | ```typescript
85 | import axios from "axios";
86 | (async () => {
87 | let response = await axios({
88 | method: "post",
89 | url: 'https://api.turing.sh/image/kandinsky',
90 | headers: {
91 | "Content-Type": "application/json",
92 | Authorization: "Bearer YOUR_API_KEY",
93 | "x-captcha-token": "Captcha key"
94 | },
95 | data: {
96 | "prompt": "string",
97 | "steps": 100,
98 | "number": 1,
99 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
100 | "guidance_scale": 4,
101 | "width": 512,
102 | "height": 512,
103 | "cfg_scale": 4,
104 | "model_version": "2.2",
105 | "stream": true
106 | },
107 | })
108 | })();
109 | ```
110 | ```python
111 | import requests
112 | import json
113 | response = requests.post(
114 | "https://api.turing.sh/image/kandinsky",
115 | headers={
116 | "Content-Type": "application/json",
117 | "Authorization": "Bearer YOUR_API_KEY",
118 | "x-captcha-token": "Captcha key"
119 | },
120 | data=json.dumps({
121 | "prompt": "string",
122 | "steps": 100,
123 | "number": 1,
124 | "negative_prompt": "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
125 | "guidance_scale": 4,
126 | "width": 512,
127 | "height": 512,
128 | "cfg_scale": 4,
129 | "model_version": "2.2",
130 | "stream": true
131 | }),
132 | )
133 | ```
134 |
--------------------------------------------------------------------------------
/docs/image/sdxl/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Stable Diffusion XL
3 | ---
4 |
5 | # Stable Diffusion XL
6 | POST *https://api.turing.sh/image/sdxl*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 |
15 | - **negative_prompt**
16 | - Type: string
17 | - Required: false
18 |
19 | - **image**
20 | - Type: string
21 | - Required: false
22 |
23 | - **action**
24 | - Type: string
25 | - Required: true
26 | - Options: generate, img2img, upscale
27 | - Default: generate
28 |
29 | - **width**
30 | - Type: number
31 | - Required: false
32 | - Default: 512
33 |
34 | - **height**
35 | - Type: number
36 | - Required: false
37 | - Default: 512
38 |
39 | - **steps**
40 | - Type: number
41 | - Required: false
42 | - Default: 100
43 |
44 | - **number**
45 | - Type: number
46 | - Required: false
47 | - Default: 1
48 |
49 | - **sampler**
50 | - Type: string
51 | - Required: false
52 | - Options: DDIM, DDPM, K_DPMPP_2M, K_DPMPP_2S_ANCESTRAL, K_DPM_2, K_DPM_2_ANCESTRAL, K_EULER, K_EULER_ANCESTRAL, K_HEUN, K_LMS
53 |
54 | - **cfg_scale**
55 | - Type: number
56 | - Required: false
57 | - Default: 7
58 |
59 | - **seed**
60 | - Type: number
61 | - Required: false
62 |
63 | - **style**
64 | - Type: string
65 | - Required: false
66 | - Description: Style to use for generating the image
67 | - Options: 3d-model, analog-film, anime, cinematic, comic-book, digital-art, enhance, fantasy-art, isometric, line-art, low-poly, modeling-compound, neon-punk, origami, photographic, pixel-art, title-texture
68 |
69 | - **model**
70 | - Type: string
71 | - Required: false
72 | - Options: sdxl, sd-1.5, sd, sd-768, stable-diffusion-xl-1024-v0-9, stable-diffusion-v1, stable-diffusion-v1-5, stable-diffusion-512-v2-0, stable-diffusion-768-v2-0, stable-diffusion-depth-v2-0, stable-diffusion-512-v2-1, stable-diffusion-768-v2-1, stable-diffusion-xl-beta-v2-2-2
73 | - Default: sdxl
74 |
75 | - **strength**
76 | - Type: number
77 | - Required: false
78 |
79 | - **stream**
80 | - Type: boolean
81 | - Required: false
82 | - Default: true
83 |
84 | ## Response
85 |
86 |
87 | - **cost**
88 | - Type: number
89 | - Description: Cost of the request in USD
90 |
91 | - **results**
92 | - Type: array
93 | - Description: Results of the request
94 |
95 | - **status**
96 | - Type: string
97 | - Description: Status of the request
98 |
99 | - **progress**
100 | - Type: number
101 | - Description: Progress of the request
102 |
103 | - **id**
104 | - Type: string
105 | - Description: ID of the request
106 |
107 | - **error**
108 | - Type: string
109 | - Description: Error of the request
110 |
111 | ## Examples
112 |
113 |
114 | ```typescript
115 | import axios from "axios";
116 | (async () => {
117 | let response = await axios({
118 | method: "post",
119 | url: 'https://api.turing.sh/image/sdxl',
120 | headers: {
121 | "Content-Type": "application/json",
122 | Authorization: "Bearer YOUR_API_KEY",
123 | "x-captcha-token": "Captcha key"
124 | },
125 | data: {
126 | "prompt": "string",
127 | "action": "generate",
128 | "width": 512,
129 | "height": 512,
130 | "steps": 100,
131 | "number": 1,
132 | "sampler": "DDIM",
133 | "cfg_scale": 7,
134 | "style": "3d-model",
135 | "model": "sdxl",
136 | "stream": true
137 | },
138 | })
139 | })();
140 | ```
141 | ```python
142 | import requests
143 | import json
144 | response = requests.post(
145 | "https://api.turing.sh/image/sdxl",
146 | headers={
147 | "Content-Type": "application/json",
148 | "Authorization": "Bearer YOUR_API_KEY",
149 | "x-captcha-token": "Captcha key"
150 | },
151 | data=json.dumps({
152 | "prompt": "string",
153 | "action": "generate",
154 | "width": 512,
155 | "height": 512,
156 | "steps": 100,
157 | "number": 1,
158 | "sampler": "DDIM",
159 | "cfg_scale": 7,
160 | "style": "3d-model",
161 | "model": "sdxl",
162 | "stream": true
163 | }),
164 | )
165 | ```
166 |
--------------------------------------------------------------------------------
/docs/image/sh/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Stablehorde
3 | ---
4 |
5 | # Stablehorde
6 | POST *https://api.turing.sh/image/sh*
7 |
8 | ## Parameters
9 |
10 |
11 | - **prompt**
12 | - Type: string
13 | - Required: true
14 | - Description: Prompt to generate the image
15 |
16 | - **negative_prompt**
17 | - Type: string
18 | - Required: false
19 |
20 | - **image**
21 | - Type: string
22 | - Required: false
23 | - Description: Image URL for the model to use when doing img2img
24 |
25 | - **width**
26 | - Type: number
27 | - Required: false
28 | - Default: 512
29 |
30 | - **height**
31 | - Type: number
32 | - Required: false
33 | - Default: 512
34 |
35 | - **steps**
36 | - Type: number
37 | - Required: false
38 | - Default: 50
39 |
40 | - **number**
41 | - Type: number
42 | - Required: false
43 | - Description: Number of images to generate
44 | - Default: 1
45 |
46 | - **strength**
47 | - Type: number
48 | - Required: false
49 |
50 | - **sampler**
51 | - Type: string
52 | - Required: false
53 | - Options: k_lms, k_heun, k_euler, k_euler_a, k_dpm_2, k_dpm_2_a, DDIM, k_dpm_fast, k_dpm_adaptive, k_dpmpp_2m, k_dpmpp_2s_a, k_dpmpp_sde
54 |
55 | - **cfg_scale**
56 | - Type: number
57 | - Required: false
58 |
59 | - **seed**
60 | - Type: number
61 | - Required: false
62 |
63 | - **model**
64 | - Type: string
65 | - Required: false
66 | - Options: SDXL 1.0, AlbedoBase XL (SDXL), ICBINP XL, TURBO XL, Fustercluck, stable_cascade
67 | - Default: stable_cascade
68 |
69 | - **nsfw**
70 | - Type: boolean
71 | - Required: false
72 |
73 | - **stream**
74 | - Type: boolean
75 | - Required: false
76 | - Default: true
77 |
78 | ## Response
79 |
80 |
81 | - **cost**
82 | - Type: number
83 | - Description: Cost of the request in USD
84 |
85 | - **id**
86 | - Type: string
87 | - Description: ID of the request
88 |
89 | - **status**
90 | - Type: string
91 | - Description: Status of the request
92 |
93 | - **progress**
94 | - Type: number
95 | - Description: Progress of the request
96 |
97 | - **queue_position**
98 | - Type: number
99 | - Description: Queue position of the request
100 |
101 | - **results**
102 | - Type: array
103 | - Description: Results of the request
104 |
105 | ## Examples
106 |
107 |
108 | ```typescript
109 | import axios from "axios";
110 | (async () => {
111 | let response = await axios({
112 | method: "post",
113 | url: 'https://api.turing.sh/image/sh',
114 | headers: {
115 | "Content-Type": "application/json",
116 | Authorization: "Bearer YOUR_API_KEY",
117 | "x-captcha-token": "Captcha key"
118 | },
119 | data: {
120 | "prompt": "string",
121 | "width": 512,
122 | "height": 512,
123 | "steps": 50,
124 | "number": 1,
125 | "sampler": "k_lms",
126 | "model": "stable_cascade",
127 | "stream": true
128 | },
129 | })
130 | })();
131 | ```
132 | ```python
133 | import requests
134 | import json
135 | response = requests.post(
136 | "https://api.turing.sh/image/sh",
137 | headers={
138 | "Content-Type": "application/json",
139 | "Authorization": "Bearer YOUR_API_KEY",
140 | "x-captcha-token": "Captcha key"
141 | },
142 | data=json.dumps({
143 | "prompt": "string",
144 | "width": 512,
145 | "height": 512,
146 | "steps": 50,
147 | "number": 1,
148 | "sampler": "k_lms",
149 | "model": "stable_cascade",
150 | "stream": true
151 | }),
152 | )
153 | ```
154 |
--------------------------------------------------------------------------------
/docs/image/upscale/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Upscale models
3 | ---
4 |
5 | # Upscale models
6 | POST *https://api.turing.sh/image/upscale*
7 |
8 | ## Pricing
9 |
10 |
11 | - **Average:** 0.01
12 |
13 | ## Parameters
14 |
15 |
16 | - **upscaler**
17 | - Type: string
18 | - Required: false
19 | - Description: Upscaler to use, by selecting this you won't generate any image but you will upscale the image you provide
20 | - Options: GFPGAN, RealESRGAN_x4plus, RealESRGAN_x2plus, RealESRGAN_x4plus_anime_6B, NMKD_Siax, 4x_AnimeSharp
21 | - Default: RealESRGAN_x2plus
22 |
23 | - **image**
24 | - Type: string
25 | - Required: true
26 | - Description: Image URL for the model to use when doing the upscaling
27 |
28 | ## Response
29 |
30 |
31 | - **cost**
32 | - Type: number
33 | - Description: Cost of the request in USD
34 |
35 | - **result**
36 | - Type: string
37 | - Description: Object containing the upscaled image URL
38 |
39 | - **status**
40 | - Type: string
41 | - Description: Status of the request
42 |
43 | - **done**
44 | - Type: boolean
45 | - Description: Whether the request is done or not
46 |
47 | ## Examples
48 |
49 |
50 | ```typescript
51 | import axios from "axios";
52 | (async () => {
53 | let response = await axios({
54 | method: "post",
55 | url: 'https://api.turing.sh/image/upscale',
56 | headers: {
57 | "Content-Type": "application/json",
58 | Authorization: "Bearer YOUR_API_KEY",
59 | "x-captcha-token": "Captcha key"
60 | },
61 | data: {
62 | "upscaler": "RealESRGAN_x2plus",
63 | "image": "string"
64 | },
65 | })
66 | })();
67 | ```
68 | ```python
69 | import requests
70 | import json
71 | response = requests.post(
72 | "https://api.turing.sh/image/upscale",
73 | headers={
74 | "Content-Type": "application/json",
75 | "Authorization": "Bearer YOUR_API_KEY",
76 | "x-captcha-token": "Captcha key"
77 | },
78 | data=json.dumps({
79 | "upscaler": "RealESRGAN_x2plus",
80 | "image": "string"
81 | }),
82 | )
83 | ```
84 |
--------------------------------------------------------------------------------
/docs/image/vision/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Image vision
3 | ---
4 |
5 | # Image vision
6 | POST *https://api.turing.sh/image/vision*
7 |
8 | ## Parameters
9 |
10 |
11 | - **model**
12 | - Type: array
13 | - Required: true
14 | - Description: Model to use for the analysis
15 | - Options: blip2, ocr, gemini
16 | - Default: gemini
17 |
18 | - **image**
19 | - Type: string
20 | - Required: true
21 | - Description: Image URL for the model to process
22 |
23 | - **typeImage**
24 | - Type: string
25 | - Required: false
26 | - Description: Type of image to process
27 | - Options: anything, person
28 | - Default: anything
29 |
30 | ## Response
31 |
32 |
33 | - **cost**
34 | - Type: number
35 | - Description: Cost of the request in USD
36 |
37 | - **description**
38 | - Type: string
39 | - Description: Description of the image
40 |
41 | - **text**
42 | - Type: string
43 | - Description: Text extracted from the image
44 |
45 | - **done**
46 | - Type: boolean
47 | - Description: Whether the request is done or not
48 |
49 | ## Examples
50 |
51 |
52 | ```typescript
53 | import axios from "axios";
54 | (async () => {
55 | let response = await axios({
56 | method: "post",
57 | url: 'https://api.turing.sh/image/vision',
58 | headers: {
59 | "Content-Type": "application/json",
60 | Authorization: "Bearer YOUR_API_KEY",
61 | "x-captcha-token": "Captcha key"
62 | },
63 | data: {
64 | "model": [
65 | "gemini"
66 | ],
67 | "image": "string",
68 | "typeImage": "anything"
69 | },
70 | })
71 | })();
72 | ```
73 | ```python
74 | import requests
75 | import json
76 | response = requests.post(
77 | "https://api.turing.sh/image/vision",
78 | headers={
79 | "Content-Type": "application/json",
80 | "Authorization": "Bearer YOUR_API_KEY",
81 | "x-captcha-token": "Captcha key"
82 | },
83 | data=json.dumps({
84 | "model": [
85 | "gemini"
86 | ],
87 | "image": "string",
88 | "typeImage": "anything"
89 | }),
90 | )
91 | ```
92 |
--------------------------------------------------------------------------------
/docs/index.mdx:
--------------------------------------------------------------------------------
1 | # TuringAI API
2 |
3 | The best tool for developers to create AI-powered apps.
4 |
5 | ## What is TuringAI?
6 |
7 | TuringAI is an organization that bring the best AI models to the mass public for free. We believe that AI should be accessible to everyone, and we are working hard to make it happen.
8 |
9 | ## How to use TuringAI API?
10 |
11 | TuringAI API right now is still closed. We are working hard to make it public as soon as possible. If you want to use TuringAI API, please contact us in our [Discord server](https://discord.gg/turing).
12 | When the API is launched we will release some sdk for you to use in various languages such as Python, Javascript. In addition to that, we will also release some sample code for you to use. And the actual documentation containing all the information about the API will be released as well.
13 |
14 | ## How to contribute to TuringAI?
15 |
16 | You can support us by donating at [our page](https://app.turing.sh/pay). If you want to contribute to TuringAI as a developer, please contact us in our [Discord server](https://discord.gg/turing).
17 |
18 | ## How to contact TuringAI?
19 |
20 | The fastest way to contact us is through our [Discord server](https://discord.gg/turing). You can also contact us through our [Twitter](https://twitter.com/turing_ai_)
21 |
--------------------------------------------------------------------------------
/docs/text/alan/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Alan
3 | ---
4 |
5 | # Alan
6 | POST *https://api.turing.sh/text/alan*
7 | This model is unfinished and is not working yet.
8 |
9 |
10 | ## Parameters
11 |
12 |
13 | - **userName**
14 | - Type: string
15 | - Required: true
16 |
17 | - **messages**
18 | - Type: array
19 | - Required: true
20 |
21 | - **searchEngine**
22 | - Type: string
23 | - Required: false
24 | - Options: google, none
25 |
26 | - **image**
27 | - Type: string
28 | - Required: false
29 |
30 | - **imageDescription**
31 | - Type: string
32 | - Required: false
33 |
34 | - **imageGenerator**
35 | - Type: string
36 | - Required: false
37 | - Options: sdxl, kandinsky, none
38 |
39 | - **nsfw**
40 | - Type: boolean
41 | - Required: false
42 |
43 | - **audioGenerator**
44 | - Type: string
45 | - Required: false
46 | - Options: musicgen
47 |
48 | - **imageModificator**
49 | - Type: string
50 | - Required: false
51 | - Options: controlnet, none
52 |
53 | - **max_tokens**
54 | - Type: number
55 | - Required: false
56 | - Default: 250
57 |
58 | ## Response
59 |
60 | Response not defined yet
61 |
62 |
63 | ## Examples
64 |
65 |
66 | ```typescript
67 | import axios from "axios";
68 | (async () => {
69 | let response = await axios({
70 | method: "post",
71 | url: 'https://api.turing.sh/text/alan',
72 | headers: {
73 | "Content-Type": "application/json",
74 | Authorization: "Bearer YOUR_API_KEY",
75 | "x-captcha-token": "Captcha key"
76 | },
77 | data: {
78 | "userName": "string",
79 | "messages": "array",
80 | "searchEngine": "google",
81 | "imageGenerator": "sdxl",
82 | "audioGenerator": "musicgen",
83 | "imageModificator": "controlnet",
84 | "max_tokens": 250
85 | },
86 | })
87 | })();
88 | ```
89 | ```python
90 | import requests
91 | import json
92 | response = requests.post(
93 | "https://api.turing.sh/text/alan",
94 | headers={
95 | "Content-Type": "application/json",
96 | "Authorization": "Bearer YOUR_API_KEY",
97 | "x-captcha-token": "Captcha key"
98 | },
99 | data=json.dumps({
100 | "userName": "string",
101 | "messages": "array",
102 | "searchEngine": "google",
103 | "imageGenerator": "sdxl",
104 | "audioGenerator": "musicgen",
105 | "imageModificator": "controlnet",
106 | "max_tokens": 250
107 | }),
108 | )
109 | ```
110 |
--------------------------------------------------------------------------------
/docs/text/anthropic/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Anthropic Models
3 | ---
4 |
5 | # Anthropic Models
6 | POST *https://api.turing.sh/text/anthropic*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: claude-instant-1.2, claude-2.1
19 | - Default: claude-instant-1.2
20 |
21 | - **max_tokens**
22 | - Type: number
23 | - Required: false
24 | - Default: 512
25 |
26 | - **temperature**
27 | - Type: number
28 | - Required: false
29 | - Default: 0.9
30 |
31 | - **stream**
32 | - Type: boolean
33 | - Required: false
34 |
35 | ## Response
36 |
37 |
38 | - **cost**
39 | - Type: number
40 | - Description: Cost of the request in USD
41 |
42 | - **result**
43 | - Type: string
44 | - Description: Result of the request
45 |
46 | ## Examples
47 |
48 |
49 | ```typescript
50 | import axios from "axios";
51 | (async () => {
52 | let response = await axios({
53 | method: "post",
54 | url: 'https://api.turing.sh/text/anthropic',
55 | headers: {
56 | "Content-Type": "application/json",
57 | Authorization: "Bearer YOUR_API_KEY",
58 | "x-captcha-token": "Captcha key"
59 | },
60 | data: {
61 | "messages": "array",
62 | "model": "claude-instant-1.2",
63 | "max_tokens": 512,
64 | "temperature": 0.9
65 | },
66 | })
67 | })();
68 | ```
69 | ```python
70 | import requests
71 | import json
72 | response = requests.post(
73 | "https://api.turing.sh/text/anthropic",
74 | headers={
75 | "Content-Type": "application/json",
76 | "Authorization": "Bearer YOUR_API_KEY",
77 | "x-captcha-token": "Captcha key"
78 | },
79 | data=json.dumps({
80 | "messages": "array",
81 | "model": "claude-instant-1.2",
82 | "max_tokens": 512,
83 | "temperature": 0.9
84 | }),
85 | )
86 | ```
87 |
--------------------------------------------------------------------------------
/docs/text/filter/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Text Filter
3 | ---
4 |
5 | # Text Filter
6 | POST *https://api.turing.sh/text/filter*
7 |
8 | ## Parameters
9 |
10 |
11 | - **text**
12 | - Type: string
13 | - Required: true
14 | - Description: Text you want to filter
15 |
16 | - **filters**
17 | - Type: array
18 | - Required: true
19 | - Description: Filters you want to apply
20 | - Options: nsfw, cp, toxicity
21 |
22 | - **stream**
23 | - Type: boolean
24 | - Required: false
25 |
26 | ## Response
27 |
28 |
29 | - **nsfw**
30 | - Type: boolean
31 | - Description: Whether the text is nsfw or not
32 |
33 | - **youth**
34 | - Type: boolean
35 | - Description: Whether the text is youth or not
36 |
37 | - **cp**
38 | - Type: boolean
39 | - Description: Whether the text is cp or not
40 |
41 | - **toxic**
42 | - Type: boolean
43 | - Description: Whether the text is toxic or not
44 |
45 | - **done**
46 | - Type: boolean
47 | - Description: Whether the request is done or not
48 |
49 | ## Examples
50 |
51 |
52 | ```typescript
53 | import axios from "axios";
54 | (async () => {
55 | let response = await axios({
56 | method: "post",
57 | url: 'https://api.turing.sh/text/filter',
58 | headers: {
59 | "Content-Type": "application/json",
60 | Authorization: "Bearer YOUR_API_KEY",
61 | "x-captcha-token": "Captcha key"
62 | },
63 | data: {
64 | "text": "string",
65 | "filters": "nsfw"
66 | },
67 | })
68 | })();
69 | ```
70 | ```python
71 | import requests
72 | import json
73 | response = requests.post(
74 | "https://api.turing.sh/text/filter",
75 | headers={
76 | "Content-Type": "application/json",
77 | "Authorization": "Bearer YOUR_API_KEY",
78 | "x-captcha-token": "Captcha key"
79 | },
80 | data=json.dumps({
81 | "text": "string",
82 | "filters": "nsfw"
83 | }),
84 | )
85 | ```
86 |
--------------------------------------------------------------------------------
/docs/text/google/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Google Models
3 | ---
4 |
5 | # Google Models
6 | POST *https://api.turing.sh/text/google*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: gemini-pro, gemini-pro-vision
19 | - Default: gemini-pro
20 |
21 | - **max_tokens**
22 | - Type: number
23 | - Required: false
24 | - Default: 512
25 |
26 | - **temperature**
27 | - Type: number
28 | - Required: false
29 | - Default: 0.9
30 |
31 | - **id**
32 | - Type: string
33 | - Required: false
34 | - Description: ID of the conversation (used for data saving)
35 | - Default: bfb34ea4-dc9d-4f8e-b07d-e169e113d951
36 |
37 | ## Response
38 |
39 |
40 | - **cost**
41 | - Type: number
42 | - Description: Cost of the request in USD
43 |
44 | - **result**
45 | - Type: string
46 | - Description: Result of the request
47 |
48 | - **done**
49 | - Type: boolean
50 | - Description: Whether the request is done or not
51 |
52 | - **id**
53 | - Type: string
54 | - Description: ID of the conversation (used for data saving)
55 |
56 | ## Examples
57 |
58 |
59 | ```typescript
60 | import axios from "axios";
61 | (async () => {
62 | let response = await axios({
63 | method: "post",
64 | url: 'https://api.turing.sh/text/google',
65 | headers: {
66 | "Content-Type": "application/json",
67 | Authorization: "Bearer YOUR_API_KEY",
68 | "x-captcha-token": "Captcha key"
69 | },
70 | data: {
71 | "messages": "array",
72 | "model": "gemini-pro",
73 | "max_tokens": 512,
74 | "temperature": 0.9,
75 | "id": "bfb34ea4-dc9d-4f8e-b07d-e169e113d951"
76 | },
77 | })
78 | })();
79 | ```
80 | ```python
81 | import requests
82 | import json
83 | response = requests.post(
84 | "https://api.turing.sh/text/google",
85 | headers={
86 | "Content-Type": "application/json",
87 | "Authorization": "Bearer YOUR_API_KEY",
88 | "x-captcha-token": "Captcha key"
89 | },
90 | data=json.dumps({
91 | "messages": "array",
92 | "model": "gemini-pro",
93 | "max_tokens": 512,
94 | "temperature": 0.9,
95 | "id": "bfb34ea4-dc9d-4f8e-b07d-e169e113d951"
96 | }),
97 | )
98 | ```
99 |
--------------------------------------------------------------------------------
/docs/text/gpt-new/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: OpenAI models
3 | ---
4 |
5 | # OpenAI models
6 | POST *https://api.turing.sh/text/gpt-new*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: true
18 | - Options: gpt-3.5-turbo, gpt-4, gpt-3.5-turbo-16k
19 |
20 | - **max_tokens**
21 | - Type: number
22 | - Required: false
23 | - Default: 512
24 |
25 | - **temperature**
26 | - Type: number
27 | - Required: false
28 | - Default: 0.9
29 |
30 | - **plugins**
31 | - Type: array
32 | - Required: false
33 | - Options: google, youtube-search, weather, wikipedia, tenor, alphavantage-stocks, alphavantage-crypto, alphavantage-forex, free-games, tasty, world-news, calculator, github, code-interpreter, diagrams, render-diagrams, planfit, wolfram, image, music
34 | - Default:
35 |
36 | - **id**
37 | - Type: string
38 | - Required: false
39 | - Description: ID of the conversation (used for data saving)
40 | - Default: b62f4cc5-0a7b-4044-9267-065c63c24469
41 |
42 | ## Response
43 |
44 |
45 | - **result**
46 | - Type: string
47 |
48 | - **done**
49 | - Type: boolean
50 |
51 | - **cost**
52 | - Type: number
53 |
54 | - **tool**
55 | - Type: object
56 |
57 | - **finishReason**
58 | - Type: string
59 |
60 | - **id**
61 | - Type: string
62 | - Description: ID of the conversation (used for data saving)
63 |
64 | ## Examples
65 |
66 |
67 | ```typescript
68 | import axios from "axios";
69 | (async () => {
70 | let response = await axios({
71 | method: "post",
72 | url: 'https://api.turing.sh/text/gpt-new',
73 | headers: {
74 | "Content-Type": "application/json",
75 | Authorization: "Bearer YOUR_API_KEY",
76 | "x-captcha-token": "Captcha key"
77 | },
78 | data: {
79 | "messages": "array",
80 | "model": "gpt-3.5-turbo",
81 | "max_tokens": 512,
82 | "temperature": 0.9,
83 | "plugins": [],
84 | "id": "b62f4cc5-0a7b-4044-9267-065c63c24469"
85 | },
86 | })
87 | })();
88 | ```
89 | ```python
90 | import requests
91 | import json
92 | response = requests.post(
93 | "https://api.turing.sh/text/gpt-new",
94 | headers={
95 | "Content-Type": "application/json",
96 | "Authorization": "Bearer YOUR_API_KEY",
97 | "x-captcha-token": "Captcha key"
98 | },
99 | data=json.dumps({
100 | "messages": "array",
101 | "model": "gpt-3.5-turbo",
102 | "max_tokens": 512,
103 | "temperature": 0.9,
104 | "plugins": [],
105 | "id": "b62f4cc5-0a7b-4044-9267-065c63c24469"
106 | }),
107 | )
108 | ```
109 |
--------------------------------------------------------------------------------
/docs/text/groq/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: GroqCloud models
3 | ---
4 |
5 | # GroqCloud models
6 | POST *https://api.turing.sh/text/groq*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: mixtral-8x7b-32768
19 | - Default: mixtral-8x7b-32768
20 |
21 | - **max_tokens**
22 | - Type: number
23 | - Required: false
24 | - Default: 512
25 |
26 | - **temperature**
27 | - Type: number
28 | - Required: false
29 | - Default: 0.9
30 |
31 | - **id**
32 | - Type: string
33 | - Required: false
34 | - Description: ID of the conversation (used for data saving)
35 | - Default: 7ab7480c-8e5d-4177-89a1-f90444798ae5
36 |
37 | ## Response
38 |
39 |
40 | - **result**
41 | - Type: string
42 |
43 | - **done**
44 | - Type: boolean
45 |
46 | - **cost**
47 | - Type: number
48 |
49 | - **finishReason**
50 | - Type: string
51 |
52 | - **id**
53 | - Type: string
54 | - Description: ID of the conversation (used for data saving)
55 |
56 | ## Examples
57 |
58 |
59 | ```typescript
60 | import axios from "axios";
61 | (async () => {
62 | let response = await axios({
63 | method: "post",
64 | url: 'https://api.turing.sh/text/groq',
65 | headers: {
66 | "Content-Type": "application/json",
67 | Authorization: "Bearer YOUR_API_KEY",
68 | "x-captcha-token": "Captcha key"
69 | },
70 | data: {
71 | "messages": "array",
72 | "model": "mixtral-8x7b-32768",
73 | "max_tokens": 512,
74 | "temperature": 0.9,
75 | "id": "7ab7480c-8e5d-4177-89a1-f90444798ae5"
76 | },
77 | })
78 | })();
79 | ```
80 | ```python
81 | import requests
82 | import json
83 | response = requests.post(
84 | "https://api.turing.sh/text/groq",
85 | headers={
86 | "Content-Type": "application/json",
87 | "Authorization": "Bearer YOUR_API_KEY",
88 | "x-captcha-token": "Captcha key"
89 | },
90 | data=json.dumps({
91 | "messages": "array",
92 | "model": "mixtral-8x7b-32768",
93 | "max_tokens": 512,
94 | "temperature": 0.9,
95 | "id": "7ab7480c-8e5d-4177-89a1-f90444798ae5"
96 | }),
97 | )
98 | ```
99 |
--------------------------------------------------------------------------------
/docs/text/huggingface/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Huggingface based models
3 | ---
4 |
5 | # Huggingface based models
6 | POST *https://api.turing.sh/text/huggingface*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: false
14 |
15 | - **prompt**
16 | - Type: string
17 | - Required: false
18 |
19 | - **chat**
20 | - Type: boolean
21 | - Required: false
22 |
23 | - **model**
24 | - Type: string
25 | - Required: true
26 | - Options: OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5
27 |
28 | - **stop**
29 | - Type: string
30 | - Required: false
31 |
32 | ## Response
33 |
34 |
35 | - **cost**
36 | - Type: number
37 | - Description: Cost of the request in USD
38 |
39 | - **result**
40 | - Type: string
41 | - Description: Result of the request
42 |
43 | - **done**
44 | - Type: boolean
45 | - Description: Whether the request is done or not
46 |
47 | ## Examples
48 |
49 |
50 | ```typescript
51 | import axios from "axios";
52 | (async () => {
53 | let response = await axios({
54 | method: "post",
55 | url: 'https://api.turing.sh/text/huggingface',
56 | headers: {
57 | "Content-Type": "application/json",
58 | Authorization: "Bearer YOUR_API_KEY",
59 | "x-captcha-token": "Captcha key"
60 | },
61 | data: {
62 | "model": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5"
63 | },
64 | })
65 | })();
66 | ```
67 | ```python
68 | import requests
69 | import json
70 | response = requests.post(
71 | "https://api.turing.sh/text/huggingface",
72 | headers={
73 | "Content-Type": "application/json",
74 | "Authorization": "Bearer YOUR_API_KEY",
75 | "x-captcha-token": "Captcha key"
76 | },
77 | data=json.dumps({
78 | "model": "OpenAssistant/oasst-sft-4-pythia-12b-epoch-3.5"
79 | }),
80 | )
81 | ```
82 |
--------------------------------------------------------------------------------
/docs/text/openchat/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: OpenChat models
3 | ---
4 |
5 | # OpenChat models
6 | POST *https://api.turing.sh/text/openchat*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: openchat_v3.2_mistral
19 | - Default: openchat_v3.2_mistral
20 |
21 | - **max_tokens**
22 | - Type: number
23 | - Required: false
24 | - Default: 512
25 |
26 | - **temperature**
27 | - Type: number
28 | - Required: false
29 | - Default: 0.9
30 |
31 | - **id**
32 | - Type: string
33 | - Required: false
34 | - Description: ID of the conversation (used for data saving)
35 | - Default: a582c198-c87a-4180-bfc1-4b316bd21fb0
36 |
37 | - **autoSystemMessage**
38 | - Type: boolean
39 | - Required: false
40 | - Description: Send system messages automatically
41 | - Default: true
42 |
43 | ## Response
44 |
45 |
46 | - **result**
47 | - Type: string
48 |
49 | - **done**
50 | - Type: boolean
51 |
52 | - **cost**
53 | - Type: number
54 |
55 | - **finishReason**
56 | - Type: string
57 |
58 | - **id**
59 | - Type: string
60 | - Description: ID of the conversation (used for data saving)
61 |
62 | ## Examples
63 |
64 |
65 | ```typescript
66 | import axios from "axios";
67 | (async () => {
68 | let response = await axios({
69 | method: "post",
70 | url: 'https://api.turing.sh/text/openchat',
71 | headers: {
72 | "Content-Type": "application/json",
73 | Authorization: "Bearer YOUR_API_KEY",
74 | "x-captcha-token": "Captcha key"
75 | },
76 | data: {
77 | "messages": "array",
78 | "model": "openchat_v3.2_mistral",
79 | "max_tokens": 512,
80 | "temperature": 0.9,
81 | "id": "a582c198-c87a-4180-bfc1-4b316bd21fb0",
82 | "autoSystemMessage": true
83 | },
84 | })
85 | })();
86 | ```
87 | ```python
88 | import requests
89 | import json
90 | response = requests.post(
91 | "https://api.turing.sh/text/openchat",
92 | headers={
93 | "Content-Type": "application/json",
94 | "Authorization": "Bearer YOUR_API_KEY",
95 | "x-captcha-token": "Captcha key"
96 | },
97 | data=json.dumps({
98 | "messages": "array",
99 | "model": "openchat_v3.2_mistral",
100 | "max_tokens": 512,
101 | "temperature": 0.9,
102 | "id": "a582c198-c87a-4180-bfc1-4b316bd21fb0",
103 | "autoSystemMessage": true
104 | }),
105 | )
106 | ```
107 |
--------------------------------------------------------------------------------
/docs/text/other/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Other models
3 | ---
4 |
5 | # Other models
6 | POST *https://api.turing.sh/text/other*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: true
18 | - Options: llama2
19 |
20 | - **max_tokens**
21 | - Type: number
22 | - Required: false
23 | - Default: 300
24 |
25 | - **temperature**
26 | - Type: number
27 | - Required: false
28 | - Default: 0.7
29 |
30 | - **stream**
31 | - Type: boolean
32 | - Required: false
33 |
34 | ## Response
35 |
36 |
37 | - **cost**
38 | - Type: number
39 | - Description: Cost of the request in USD
40 |
41 | - **result**
42 | - Type: string
43 | - Description: Result of the request
44 |
45 | - **status**
46 | - Type: string
47 | - Description: Status of the request
48 |
49 | - **done**
50 | - Type: boolean
51 | - Description: Whether the request is done or not
52 |
53 | ## Examples
54 |
55 |
56 | ```typescript
57 | import axios from "axios";
58 | (async () => {
59 | let response = await axios({
60 | method: "post",
61 | url: 'https://api.turing.sh/text/other',
62 | headers: {
63 | "Content-Type": "application/json",
64 | Authorization: "Bearer YOUR_API_KEY",
65 | "x-captcha-token": "Captcha key"
66 | },
67 | data: {
68 | "messages": "array",
69 | "model": "llama2",
70 | "max_tokens": 300,
71 | "temperature": 0.7
72 | },
73 | })
74 | })();
75 | ```
76 | ```python
77 | import requests
78 | import json
79 | response = requests.post(
80 | "https://api.turing.sh/text/other",
81 | headers={
82 | "Content-Type": "application/json",
83 | "Authorization": "Bearer YOUR_API_KEY",
84 | "x-captcha-token": "Captcha key"
85 | },
86 | data=json.dumps({
87 | "messages": "array",
88 | "model": "llama2",
89 | "max_tokens": 300,
90 | "temperature": 0.7
91 | }),
92 | )
93 | ```
94 |
--------------------------------------------------------------------------------
/docs/text/pawan/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Pawan.krd models
3 | ---
4 |
5 | # Pawan.krd models
6 | POST *https://api.turing.sh/text/pawan*
7 |
8 | ## Parameters
9 |
10 |
11 | - **messages**
12 | - Type: array
13 | - Required: true
14 |
15 | - **model**
16 | - Type: string
17 | - Required: false
18 | - Options: zephyr-7b-beta, pai-001-light-beta
19 | - Default: zephyr-7b-beta
20 |
21 | - **max_tokens**
22 | - Type: number
23 | - Required: false
24 | - Default: 512
25 |
26 | - **temperature**
27 | - Type: number
28 | - Required: false
29 | - Default: 0.9
30 |
31 | - **id**
32 | - Type: string
33 | - Required: false
34 | - Description: ID of the conversation (used for data saving)
35 | - Default: 9bed6ed8-6040-4cd1-84a3-68a414d7a731
36 |
37 | - **autoSystemMessage**
38 | - Type: boolean
39 | - Required: false
40 | - Description: Send system messages automatically
41 | - Default: true
42 |
43 | ## Response
44 |
45 |
46 | - **result**
47 | - Type: string
48 |
49 | - **done**
50 | - Type: boolean
51 |
52 | - **cost**
53 | - Type: number
54 |
55 | - **finishReason**
56 | - Type: string
57 |
58 | - **id**
59 | - Type: string
60 | - Description: ID of the conversation (used for data saving)
61 |
62 | ## Examples
63 |
64 |
65 | ```typescript
66 | import axios from "axios";
67 | (async () => {
68 | let response = await axios({
69 | method: "post",
70 | url: 'https://api.turing.sh/text/pawan',
71 | headers: {
72 | "Content-Type": "application/json",
73 | Authorization: "Bearer YOUR_API_KEY",
74 | "x-captcha-token": "Captcha key"
75 | },
76 | data: {
77 | "messages": "array",
78 | "model": "zephyr-7b-beta",
79 | "max_tokens": 512,
80 | "temperature": 0.9,
81 | "id": "9bed6ed8-6040-4cd1-84a3-68a414d7a731",
82 | "autoSystemMessage": true
83 | },
84 | })
85 | })();
86 | ```
87 | ```python
88 | import requests
89 | import json
90 | response = requests.post(
91 | "https://api.turing.sh/text/pawan",
92 | headers={
93 | "Content-Type": "application/json",
94 | "Authorization": "Bearer YOUR_API_KEY",
95 | "x-captcha-token": "Captcha key"
96 | },
97 | data=json.dumps({
98 | "messages": "array",
99 | "model": "zephyr-7b-beta",
100 | "max_tokens": 512,
101 | "temperature": 0.9,
102 | "id": "9bed6ed8-6040-4cd1-84a3-68a414d7a731",
103 | "autoSystemMessage": true
104 | }),
105 | )
106 | ```
107 |
--------------------------------------------------------------------------------
/docs/text/translate/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Translate text
3 | ---
4 |
5 | # Translate text
6 | POST *https://api.turing.sh/text/translate*
7 |
8 | ## Parameters
9 |
10 |
11 | - **text**
12 | - Type: string
13 | - Required: true
14 | - Description: Text to translate
15 |
16 | - **from**
17 | - Type: string
18 | - Required: false
19 | - Description: Language code to translate from
20 | - Default: auto
21 |
22 | - **to**
23 | - Type: string
24 | - Required: true
25 | - Description: Language code to translate to
26 |
27 | - **ai**
28 | - Type: string
29 | - Required: true
30 | - Options: google, microsoft
31 | - Default: google
32 |
33 | ## Response
34 |
35 | Response not defined yet
36 |
37 |
38 | ## Examples
39 |
40 |
41 | ```typescript
42 | import axios from "axios";
43 | (async () => {
44 | let response = await axios({
45 | method: "post",
46 | url: 'https://api.turing.sh/text/translate',
47 | headers: {
48 | "Content-Type": "application/json",
49 | Authorization: "Bearer YOUR_API_KEY",
50 | "x-captcha-token": "Captcha key"
51 | },
52 | data: {
53 | "text": "string",
54 | "from": "auto",
55 | "to": "string",
56 | "ai": "google"
57 | },
58 | })
59 | })();
60 | ```
61 | ```python
62 | import requests
63 | import json
64 | response = requests.post(
65 | "https://api.turing.sh/text/translate",
66 | headers={
67 | "Content-Type": "application/json",
68 | "Authorization": "Bearer YOUR_API_KEY",
69 | "x-captcha-token": "Captcha key"
70 | },
71 | data=json.dumps({
72 | "text": "string",
73 | "from": "auto",
74 | "to": "string",
75 | "ai": "google"
76 | }),
77 | )
78 | ```
79 |
--------------------------------------------------------------------------------
/docs/video/zelescope/index.mdx:
--------------------------------------------------------------------------------
1 | ---
2 | title: Zelescope
3 | ---
4 |
5 | # Zelescope
6 | POST *https://api.turing.sh/video/zelescope*
7 | This model is not yet implemented
8 |
9 |
10 | ## Parameters
11 |
12 |
13 | - **prompt**
14 | - Type: string
15 | - Required: true
16 |
17 | - **duration**
18 | - Type: number
19 | - Required: false
20 | - Default: 10
21 |
22 | ## Response
23 |
24 | Response not defined yet
25 |
26 |
27 | ## Examples
28 |
29 |
30 | ```typescript
31 | import axios from "axios";
32 | (async () => {
33 | let response = await axios({
34 | method: "post",
35 | url: 'https://api.turing.sh/video/zelescope',
36 | headers: {
37 | "Content-Type": "application/json",
38 | Authorization: "Bearer YOUR_API_KEY",
39 | "x-captcha-token": "Captcha key"
40 | },
41 | data: {
42 | "prompt": "string",
43 | "duration": 10
44 | },
45 | })
46 | })();
47 | ```
48 | ```python
49 | import requests
50 | import json
51 | response = requests.post(
52 | "https://api.turing.sh/video/zelescope",
53 | headers={
54 | "Content-Type": "application/json",
55 | "Authorization": "Bearer YOUR_API_KEY",
56 | "x-captcha-token": "Captcha key"
57 | },
58 | data=json.dumps({
59 | "prompt": "string",
60 | "duration": 10
61 | }),
62 | )
63 | ```
64 |
--------------------------------------------------------------------------------
/package.json:
--------------------------------------------------------------------------------
1 | {
2 | "name": "turing-api",
3 | "version": "1.0.0",
4 | "description": "",
5 | "main": "dist/index.js",
6 | "type": "module",
7 | "scripts": {
8 | "build": "tsc",
9 | "start": "tsc && node dist/index.js",
10 | "git": "git fetch && git pull",
11 | "docs": "tsc && node dist/rundocs.js"
12 | },
13 | "repository": {
14 | "type": "git",
15 | "url": "git+https://github.com/TuringAI-Team/turing-ai-api.git"
16 | },
17 | "author": "TuringAI",
18 | "license": "Apache-2.0",
19 | "bugs": {
20 | "url": "https://github.com/TuringAI-Team/turing-ai-api/issues"
21 | },
22 | "homepage": "https://github.com/TuringAI-Team/turing-ai-api#readme",
23 | "dependencies": {
24 | "@anthropic-ai/sdk": "^0.6.2",
25 | "@dqbd/tiktoken": "^1.0.7",
26 | "@google-cloud/vertexai": "^0.1.3",
27 | "@huggingface/inference": "^2.5.2",
28 | "@mermaid-js/mermaid-cli": "^10.3.0",
29 | "@octokit/rest": "^19.0.13",
30 | "@sellix/node-sdk": "^1.0.9",
31 | "@supabase/supabase-js": "^2.33.1",
32 | "@waylaidwanderer/fetch-event-source": "^3.0.1",
33 | "axios": "^1.5.0",
34 | "canvas": "^2.11.2",
35 | "chalk": "^5.3.0",
36 | "chartjs-to-image": "^1.2.1",
37 | "cors": "^2.8.5",
38 | "delay": "^6.0.0",
39 | "dotenv": "^16.3.1",
40 | "express": "^4.18.2",
41 | "express-rate-limit": "^6.11.0",
42 | "fluent-ffmpeg": "^2.1.2",
43 | "google-auth-library": "^8.9.0",
44 | "google-tts-api": "^2.0.2",
45 | "googlethis": "^1.7.1",
46 | "groq-sdk": "^0.3.1",
47 | "hcaptcha": "^0.1.1",
48 | "helmet": "^7.0.0",
49 | "jsonwebtoken": "^9.0.2",
50 | "lang-detector": "^1.0.6",
51 | "mathjs": "^11.11.0",
52 | "openai": "^3.3.0",
53 | "puppeteer": "^19.11.1",
54 | "puppeteer-core": "^21.1.1",
55 | "rabbitmq-client": "^4.3.0",
56 | "redis": "^4.6.8",
57 | "replicate-api": "^0.4.4",
58 | "turing.sh": "^0.0.9",
59 | "uuid": "^9.0.0",
60 | "wandbox-api-updated": "^1.0.3",
61 | "yt-search": "^2.10.4"
62 | },
63 | "devDependencies": {
64 | "@types/node": "^20.5.9",
65 | "typescript": "^5.2.2"
66 | }
67 | }
68 |
--------------------------------------------------------------------------------
/src/db/mq.ts:
--------------------------------------------------------------------------------
1 | import { Connection } from "rabbitmq-client";
2 | import log from "../utils/log.js";
3 | const rabbit = new Connection(process.env.MQ_URL);
4 | rabbit.on("error", (err) => {
5 | log("error", "RabbitMQ connection error", err);
6 | });
7 | rabbit.on("connection", () => {
8 | log("info", "RabbitMQ connected");
9 | });
10 |
11 | const pub = rabbit.createPublisher({
12 | // Enable publish confirmations, similar to consumer acknowledgements
13 | confirm: true,
14 | // Enable retries
15 | maxAttempts: 2,
16 | // Optionally ensure the existence of an exchange before we use it
17 | exchanges: [{ exchange: "db", type: "topic" }],
18 | });
19 | export { pub };
20 | export default rabbit;
21 |
--------------------------------------------------------------------------------
/src/db/redis.ts:
--------------------------------------------------------------------------------
1 | import { createClient, defineScript } from "redis";
2 |
3 | let port: any = process.env.REDIS_PORT;
4 | const redisClient = createClient({
5 | password: process.env.REDIS_PASSWORD || "password",
6 | socket: {
7 | host: process.env.REDIS_HOST || "localhost",
8 | port: port,
9 | },
10 | });
11 |
12 | redisClient.on("error", (err) => console.log("Client error: Redis", err));
13 |
14 | await redisClient.connect();
15 |
16 | export default redisClient;
17 |
--------------------------------------------------------------------------------
/src/db/supabase.ts:
--------------------------------------------------------------------------------
1 | import { createClient } from "@supabase/supabase-js";
2 |
3 | const supabaseUrl = process.env.SUPABASE_URL as string;
4 | const supabaseKey = process.env.SUPABASE_KEY as string;
5 | const supabase = createClient(supabaseUrl, supabaseKey);
6 |
7 | export default supabase;
--------------------------------------------------------------------------------
/src/handlers/audio.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import fs from "node:fs";
3 | import { fileURLToPath } from "url";
4 | import log from "../utils/log.js";
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | export default async function audioHandler(client) {
9 | if (client.audio.length > 0) return;
10 | const audios = [];
11 | const audioPath = path.join(__dirname, "../models/audio");
12 |
13 | const audioFils = fs
14 | .readdirSync(audioPath)
15 | .filter((file) => file.endsWith(".js"));
16 |
17 | for (const file of audioFils) {
18 | const filePath = `../models/audio/${file}`;
19 | const { default: audio } = await import(filePath);
20 | // Set a new item in the Collection with the key as the command name and the value as the exported module
21 | if ("data" in audio && "execute" in audio) {
22 | audios.push(audio);
23 | } else {
24 | log(
25 | "warning",
26 | `The command at ${filePath} is missing a required "data" or "execute" property.`
27 | );
28 | }
29 | }
30 | client.audio = audios;
31 | log("info", `Loaded ${audios.length} audio models.`);
32 | }
33 |
--------------------------------------------------------------------------------
/src/handlers/image.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import fs from "node:fs";
3 | import { fileURLToPath } from "url";
4 | import log from "../utils/log.js";
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | export default async function imageHandler(client) {
9 | if (client.image.length > 0) return;
10 | const images = [];
11 | const imagePath = path.join(__dirname, "../models/image");
12 |
13 | const imageFiles = fs
14 | .readdirSync(imagePath)
15 | .filter((file) => file.endsWith(".js"));
16 |
17 | for (const file of imageFiles) {
18 | const filePath = `../models/image/${file}`;
19 | const { default: image } = await import(filePath);
20 | if (!image) {
21 | log(
22 | "warning",
23 | `The command at ${filePath} is missing a required "data" or "execute" property.`
24 | );
25 | continue;
26 | }
27 | // Set a new item in the Collection with the key as the command name and the value as the exported module
28 | if ("data" in image && "execute" in image) {
29 | images.push(image);
30 | } else {
31 | log(
32 | "warning",
33 | `The command at ${filePath} is missing a required "data" or "execute" property.`
34 | );
35 | }
36 | }
37 | client.image = images;
38 | log("info", `Loaded ${images.length} image models.`);
39 | }
40 |
--------------------------------------------------------------------------------
/src/handlers/text.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import fs from "node:fs";
3 | import { fileURLToPath } from "url";
4 | import log from "../utils/log.js";
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | export default async function textHandler(client) {
9 | if (client.text.length > 0) return;
10 | const texts = [];
11 | const textPath = path.join(__dirname, "../models/text");
12 |
13 | const textFiles = fs
14 | .readdirSync(textPath)
15 | .filter((file) => file.endsWith(".js"));
16 |
17 | for (const file of textFiles) {
18 | const filePath = `../models/text/${file}`;
19 | const { default: text } = await import(filePath);
20 | // Set a new item in the Collection with the key as the command name and the value as the exported module
21 | if ("data" in text && "execute" in text) {
22 | texts.push(text);
23 | } else {
24 | log(
25 | "warning",
26 | `The command at ${filePath} is missing a required "data" or "execute" property.`
27 | );
28 | }
29 | }
30 | client.text = texts;
31 | log("info", `Loaded ${texts.length} text models.`);
32 | }
33 |
--------------------------------------------------------------------------------
/src/handlers/video.ts:
--------------------------------------------------------------------------------
1 | import path from "node:path";
2 | import fs from "node:fs";
3 | import { fileURLToPath } from "url";
4 | import log from "../utils/log.js";
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | export default async function videoHandler(client) {
9 | if (client.video.length > 0) return;
10 | const videos = [];
11 | const videoPath = path.join(__dirname, "../models/video");
12 |
13 | const videoFiles = fs
14 | .readdirSync(videoPath)
15 | .filter((file) => file.endsWith(".js"));
16 |
17 | for (const file of videoFiles) {
18 | const filePath = `../models/video/${file}`;
19 | const { default: video } = await import(filePath);
20 | if (!video) {
21 | log(
22 | "warning",
23 | `The command at ${filePath} is missing a required "data" or "execute" property.`
24 | );
25 | continue;
26 | }
27 | // Set a new item in the Collection with the key as the command name and the value as the exported module
28 | if ("data" in video && "execute" in video) {
29 | videos.push(video);
30 | } else {
31 | log(
32 | "warning",
33 | `The command at ${filePath} is missing a required "data" or "execute" property.`
34 | );
35 | }
36 | }
37 | client.video = videos;
38 | log("info", `Loaded ${videos.length} video models.`);
39 | }
40 |
--------------------------------------------------------------------------------
/src/index.ts:
--------------------------------------------------------------------------------
1 | import express, { Application, Request, Response } from "express";
2 | import helmet from "helmet";
3 | import cors from "cors";
4 | import "dotenv/config";
5 | import { generateKey } from "./utils/key.js";
6 | import rateLimit from "express-rate-limit";
7 |
8 | // routes
9 | import OtherRoutes from "./routes/other.routes.js";
10 | import ChartRoutes from "./routes/chart.routes.js";
11 | import PaymentRoutes from "./routes/payment.routes.js";
12 | import DataRoutes from "./routes/data.routes.js";
13 | import RunpodRoutes from "./routes/runpod.routes.js";
14 | import ModelRoutes from "./routes/models.routes.js";
15 | import KeyRoutes from "./routes/key.routes.js";
16 |
17 | const app: Application = express();
18 |
19 | import { verifyToken } from "./middlewares/key.js";
20 | import Ciclic from "./utils/ciclic.js";
21 | import textHandler from "./handlers/text.js";
22 | import imageHandler from "./handlers/image.js";
23 | import audioHandler from "./handlers/audio.js";
24 | import { autogenerateDocs } from "./utils/docs.js";
25 | import log from "./utils/log.js";
26 | import videoHandler from "./handlers/video.js";
27 | const client = {
28 | text: [],
29 | image: [],
30 | audio: [],
31 | video: [],
32 | };
33 |
34 | const limiter = rateLimit({
35 | windowMs: 1000, // 15 minutes
36 | max: 20, // Limit each IP to 100 requests per `window` (here, per 15 minutes)
37 | standardHeaders: true, // Return rate limit info in the `RateLimit-*` headers
38 | legacyHeaders: false, // Disable the `X-RateLimit-*` headers
39 | });
40 |
41 | // Apply the rate limiting middleware to all requests
42 | app.use(limiter);
43 | app.use(helmet());
44 | app.use(
45 | cors({
46 | origin: [
47 | "http://localhost:3000",
48 | "https://app.turing-ai.xyz",
49 | "https://app.turing.sh",
50 | "https://sellix.io",
51 | "https://sellix.pw",
52 | "https://sellix.xyz",
53 | "https://sellix.gg",
54 | ],
55 | methods: ["GET", "POST", "PUT", "DELETE"],
56 | allowedHeaders: ["Content-Type", "Authorization", "x-captcha-token"],
57 | })
58 | );
59 | app.use(express.json({ limit: "50mb" }));
60 | app.use(express.urlencoded({ limit: "50mb", extended: true }));
61 | app.set("port", process.env.PORT || 3000);
62 |
63 | app.use("/key", KeyRoutes);
64 | app.use("/other", OtherRoutes);
65 | app.use("/chart", ChartRoutes);
66 | app.use("/payments", PaymentRoutes);
67 | app.use("/data", DataRoutes);
68 | app.use("/runpod", RunpodRoutes);
69 | app.use("/", ModelRoutes);
70 |
71 | app.listen(app.get("port"), async () => {
72 | log("info", `Server is running on port ${app.get("port")}`);
73 | await textHandler(client);
74 | await imageHandler(client);
75 | await audioHandler(client);
76 | await videoHandler(client);
77 | await Ciclic();
78 |
79 | if (process.env.NODE_ENV != "production") {
80 | await autogenerateDocs(client);
81 | }
82 | });
83 |
84 | export default client;
85 |
--------------------------------------------------------------------------------
/src/middlewares/captchas/hcaptchas.ts:
--------------------------------------------------------------------------------
1 | import { verify } from "hcaptcha";
2 | import { checkCaptchaToken } from "../../utils/key.js";
3 |
4 | export default async function (req, res, next) {
5 | // captcha token is on headers
6 | const token = req.headers["x-captcha-token"];
7 | if (!token) {
8 | return res.status(400).json({ error: "Captcha token is required" });
9 | }
10 | try {
11 | let valid = await checkCaptchaToken(token, req);
12 | if (valid) {
13 | return next();
14 | }
15 | const data = await verify(process.env.HCAPTCHA_SECRET as string, token);
16 | if (data.success) {
17 | return next();
18 | }
19 | return res.status(400).json({ error: "Invalid captcha" });
20 | } catch (err) {
21 | return res.status(400).json({ error: "Invalid captcha" });
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/middlewares/captchas/turnstile.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { checkCaptchaToken } from "../../utils/key.js";
3 | export default async function (req, res, next) {
4 | // captcha token is on headers
5 | const token = req.headers["x-captcha-token"];
6 | if (!token) {
7 | return res.status(400).json({ error: "Captcha token is required" });
8 | }
9 | try {
10 | let valid: any = await checkCaptchaToken(token, req);
11 | if (valid.error) {
12 | return res.status(400).json({ error: valid.error });
13 | }
14 | if (valid.user) {
15 | req.user = valid.user;
16 | req.keyId = valid.apiId;
17 | return next();
18 | }
19 | if (valid) {
20 | return next();
21 | }
22 | const data = await validate(process.env.TURNSTILE_SECRET as string, token);
23 | if (data.success) {
24 | return next();
25 | }
26 | return res.status(400).json({ error: "Invalid captcha" });
27 | } catch (err) {
28 | console.log(err);
29 | return res.status(400).json({ error: "Invalid captcha" });
30 | }
31 | }
32 | const API_URL: string =
33 | "https://challenges.cloudflare.com/turnstile/v0/siteverify";
34 | async function validate(secret: string, token: string, ip?: string) {
35 | let formData = new URLSearchParams();
36 | formData.append("secret", secret);
37 | formData.append("response", token);
38 | if (ip) {
39 | formData.append("remoteip", ip);
40 | }
41 |
42 | var res = await axios({
43 | url: API_URL,
44 | data: formData,
45 | method: "POST",
46 | headers: { "Content-Type": "application/x-www-form-urlencoded" },
47 | });
48 | var data: {
49 | success: boolean;
50 | "error-codes": Array;
51 | challenge_ts?: string;
52 | hostname?: string;
53 | action?: string;
54 | cdata?: string;
55 | } = res.data;
56 | /* Error descriptions */
57 | var error = data["error-codes"][0];
58 | if (error) {
59 | switch (error) {
60 | case "missing-input-secret":
61 | return {
62 | error: "The secret parameter was not passed.",
63 | ...data,
64 | };
65 | case "invalid-input-secret":
66 | return {
67 | error: "The secret parameter was invalid or did not exist.",
68 | ...data,
69 | };
70 | case "missing-input-response":
71 | return {
72 | error: "The response(token) parameter was not passed.",
73 | ...data,
74 | };
75 | case "invalid-input-response":
76 | return {
77 | error: "The response(token) parameter is invalid or has expired.",
78 | ...data,
79 | };
80 | case "bad-request":
81 | return {
82 | error: "The request was rejected because it was malformed.",
83 | ...data,
84 | };
85 | case "timeout-or-duplicate":
86 | return {
87 | error: "The response parameter has already been validated before.",
88 | ...data,
89 | };
90 | case "internal-error":
91 | return {
92 | error:
93 | "An internal error happened while validating the response. The request can be retried.",
94 | ...data,
95 | };
96 | }
97 | }
98 | return data;
99 | }
100 |
--------------------------------------------------------------------------------
/src/middlewares/geo.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { Request, Response, NextFunction } from "express";
3 |
4 | export default async function geo(req: any, res: Response, next: NextFunction) {
5 | var ip =
6 | (req.headers["x-forwarded-for"] as string) ||
7 | (req.socket.remoteAddress as string);
8 | ip = ip.split(", ")[1];
9 | try {
10 | const apiUrl = `http://ip-api.com/json/${ip}`;
11 | const { data } = await axios.get(apiUrl);
12 | req.geo = data;
13 | // log geo and user agent
14 | console.log(data, req.headers["user-agent"]);
15 | next();
16 | } catch (error) {
17 | console.log(error);
18 | req.geo = {
19 | country_name: "Unknown",
20 | };
21 | next();
22 | }
23 | }
24 |
--------------------------------------------------------------------------------
/src/middlewares/key.ts:
--------------------------------------------------------------------------------
1 | import jwt from "jsonwebtoken";
2 | import supabase from "../db/supabase.js";
3 | import { Request, Response } from "express";
4 | import redisClient from "../db/redis.js";
5 |
6 | export async function verifyToken(token: string, req) {
7 | // verify token
8 | try {
9 | let decoded = jwt.verify(token, process.env.SECRET_KEY);
10 | if (!decoded) {
11 | // decode supabase access token
12 | const { data, error } = await supabase.auth.getUser(token);
13 | if (error) {
14 | console.log(error);
15 | return false;
16 | }
17 | return true;
18 | } else {
19 | let data: any = await redisClient.get(`api:${token}`);
20 | data = JSON.parse(data);
21 | if (!data) {
22 | return false;
23 | }
24 | if (data.allowedPaths && data.userId != "530102778408861706") {
25 | let allowed = false;
26 | if (data.allowedPaths.find((path) => path == "*")) {
27 | allowed = true;
28 | } else {
29 | for (let path of data.allowedPaths) {
30 | path = path.replace("*", "");
31 | if (req.path.startsWith(path)) {
32 | allowed = true;
33 | }
34 | }
35 | }
36 | if (!allowed) {
37 | return {
38 | error: "You don't have permissions to use this endpoint",
39 | };
40 | }
41 | }
42 | return {
43 | apiData: data,
44 | };
45 | }
46 | } catch (err) {
47 | const { data, error } = await supabase.auth.getUser(token);
48 | if (error) {
49 | console.log(error);
50 | return false;
51 | }
52 | return true;
53 | }
54 | }
55 | export default async (req: Request, res: Response, next) => {
56 | if (req.headers.authorization) {
57 | const token = req.headers.authorization;
58 | if (token) {
59 | var isvalid: any = await verifyToken(
60 | token.replaceAll("Bearer ", ""),
61 | req
62 | );
63 | if (isvalid.error) {
64 | res.status(401).send({ error: isvalid.error });
65 | return;
66 | }
67 | if (isvalid.apiData) {
68 | req.apiData = isvalid.apiData;
69 | next();
70 | return;
71 | }
72 | if (isvalid) {
73 | next();
74 | } else {
75 | res.status(401).send({ error: "Unauthorized, no valid token" });
76 | }
77 | } else {
78 | res.status(401).send({ error: "Unauthorized, no token provided(1)" });
79 | }
80 | } else {
81 | res.status(401).send({ error: "Unauthorized, no token provided" });
82 | }
83 | };
84 |
--------------------------------------------------------------------------------
/src/models/audio/music.ts:
--------------------------------------------------------------------------------
1 | import { request, translateModels } from "../../utils/runpod.js";
2 | import { EventEmitter } from "events";
3 |
4 | export default {
5 | data: {
6 | name: "music",
7 | fullName: "Music generation",
8 | parameters: {
9 | prompt: {
10 | type: "string",
11 | required: true,
12 | },
13 | model: {
14 | type: "string",
15 | required: false,
16 | options: ["small", "medium", "melody", "large"],
17 | default: "small",
18 | },
19 | duration: {
20 | type: "number",
21 | required: false,
22 | default: 8,
23 | },
24 | stream: {
25 | type: "boolean",
26 | required: false,
27 | default: false,
28 | },
29 | },
30 | },
31 | execute: async (data) => {
32 | let { prompt, model, duration, stream } = data;
33 | if (!model) {
34 | model = "small";
35 | }
36 | if (!duration) {
37 | duration = 8;
38 | }
39 | let url = await translateModels("musicgen");
40 | let res = await request(url, "run", {
41 | input: {
42 | descriptions: [prompt],
43 | duration: duration,
44 | modelName: model,
45 | },
46 | });
47 | let emitter = new EventEmitter();
48 | let id = res.id;
49 | let result = {
50 | id: id,
51 | status: "queued",
52 | results: [],
53 | cost: null,
54 | };
55 | emitter.emit("data", result);
56 | let interval = setInterval(async () => {
57 | let check = await request(url, `status/${id}`, {});
58 | if (check) {
59 | }
60 | }, 1000);
61 | },
62 | };
63 |
--------------------------------------------------------------------------------
/src/models/audio/stt.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import FormData from "form-data";
3 | import { EventEmitter } from "events";
4 |
5 | export default {
6 | data: {
7 | name: "stt",
8 | fullName: "Speech to text",
9 | parameters: {
10 | model: {
11 | type: "string",
12 | required: false,
13 | options: ["whisper", "fast-whisper", "gladia"],
14 | default: "fast-whisper",
15 | description: "Model to use for speech to text",
16 | },
17 | audio: {
18 | type: "string",
19 | required: true,
20 | description: "Audio URL to transcribe",
21 | },
22 | diarization: {
23 | type: "boolean",
24 | required: false,
25 | default: false,
26 | description: "Whether to use diarization or not",
27 | },
28 | type: {
29 | type: "string",
30 | required: false,
31 | options: ["tiny", "base", "small", "medium", "large-v1", "large-v2"],
32 | default: "base",
33 | },
34 | stream: {
35 | type: "boolean",
36 | required: false,
37 | default: false,
38 | },
39 | },
40 | },
41 | execute: async (data) => {
42 | let { model, audio, diarization, type } = data;
43 | const event = new EventEmitter();
44 | let result = {
45 | cost: 0,
46 | result: "",
47 | done: false,
48 | };
49 | event.emit("data", result);
50 | if (model == "gladia") {
51 | const form = new FormData();
52 | form.append("audio_url", audio);
53 | form.append("language_behaviour", "automatic single language");
54 | if (!diarization) diarization = false;
55 | form.append("toggle_diarization", diarization);
56 |
57 | result.cost = 0.01;
58 | axios
59 | .post("https://api.gladia.io/audio/text/audio-transcription/", form, {
60 | params: {
61 | model: "large-v2",
62 | },
63 | headers: {
64 | ...form.getHeaders(),
65 | accept: "application/json",
66 | "x-gladia-key": process.env.GLADIA_API_KEY,
67 | "Content-Type": "multipart/form-data",
68 | },
69 | })
70 | .then((response) => {
71 | var res = response.data;
72 | result.result = res;
73 | result.done = true;
74 | event.emit("data", result);
75 | });
76 |
77 | return event;
78 | }
79 | if (model == "whisper-fast" || model == "whisper") {
80 | let models = ["tiny", "base", "small", "medium", "large-v1", "large-v2"];
81 | let modelName = models.includes(type) ? type : "base";
82 | axios({
83 | url: `https://api.runpod.ai/v2/${
84 | model == "whisper-fast" ? "faster-" : ""
85 | }whisper/runsync`,
86 | method: "post",
87 | headers: {
88 | "Content-Type": "application/json",
89 | Authorization: `${process.env.RUNPOD_API_KEY}`,
90 | accept: "application/json",
91 | },
92 | data: {
93 | input: {
94 | audio: audio,
95 | model: modelName,
96 | transcription: "plain text",
97 | translate: false,
98 | temperature: 0,
99 | best_of: 5,
100 | beam_size: 5,
101 | suppress_tokens: "-1",
102 | condition_on_previous_text: false,
103 | temperature_increment_on_fallback: 0.2,
104 | compression_ratio_threshold: 2.4,
105 | logprob_threshold: -1,
106 | no_speech_threshold: 0.6,
107 | },
108 | },
109 | }).then((response) => {
110 | let data = response.data;
111 | let price = 0.00025;
112 | result.cost = (data.executionTime / 1000) * price;
113 | result.result = data.output;
114 | event.emit("data", result);
115 | });
116 | return event;
117 | }
118 | },
119 | };
120 |
--------------------------------------------------------------------------------
/src/models/audio/tts.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import * as googleTTS from "google-tts-api";
3 | import { EventEmitter } from "events";
4 |
5 | export default {
6 | data: {
7 | name: "tts",
8 | fullName: "Text to speech",
9 | parameters: {
10 | model: {
11 | type: "string",
12 | required: true,
13 | options: ["google", "elevenlabs"],
14 | default: "google",
15 | },
16 | voice: {
17 | type: "string",
18 | required: true,
19 | default: "adam",
20 | description: "Voice to use (elevenlabs only)",
21 | },
22 | text: {
23 | type: "string",
24 | required: true,
25 | description: "Text to convert to speech",
26 | },
27 | language: {
28 | type: "string",
29 | required: true,
30 | default: "en",
31 | description: "Language code to use (google only)",
32 | },
33 | slow: {
34 | type: "boolean",
35 | required: false,
36 | default: false,
37 | description: "Speak slowly (google only)",
38 | },
39 | stream: {
40 | type: "boolean",
41 | required: false,
42 | default: false,
43 | },
44 | },
45 | },
46 | execute: async (data) => {
47 | let event = new EventEmitter();
48 | let result = {
49 | cost: 0,
50 | base64: "",
51 | done: false,
52 | };
53 | if (data.model == "google") {
54 | event.emit("data", result);
55 | let { text, language, slow } = data;
56 | google(text, language, slow).then((res) => {
57 | result.base64 = res;
58 | result.done = true;
59 | event.emit("data", result);
60 | });
61 | } else if (data.model == "elevenlabs") {
62 | let { text, voice } = data;
63 | event.emit("data", result);
64 | elevenlabs(text, voice).then((res) => {
65 | result.base64 = res.base64;
66 | result.done = true;
67 | event.emit("data", result);
68 | });
69 | }
70 | return event;
71 | },
72 | };
73 |
74 | async function elevenlabs(text: string, voice: string) {
75 | const voices = [
76 | "adam",
77 | "antoni",
78 | "arnold",
79 | "bella",
80 | "josh",
81 | "rachel",
82 | "domi",
83 | "elli",
84 | "sam",
85 | ];
86 | if (!voices.includes(voice)) {
87 | throw new Error("Voice not found");
88 | }
89 | let response = await axios({
90 | url: "https://api.pawan.krd/tts",
91 | data: {
92 | text,
93 | voice,
94 | },
95 | responseType: "arraybuffer",
96 | method: "POST",
97 | headers: {
98 | "Content-Type": "application/json",
99 | },
100 | });
101 | let base64 = Buffer.from(response.data, "binary").toString("base64");
102 | return {
103 | base64: base64,
104 | };
105 | }
106 | async function google(
107 | text: string,
108 | language: string = "en",
109 | slow: boolean = false
110 | ) {
111 | const results = googleTTS.getAudioBase64(text, {
112 | lang: language,
113 | slow: slow,
114 | host: "https://translate.google.com",
115 | });
116 | return results;
117 | }
118 |
--------------------------------------------------------------------------------
/src/models/image/anything.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { randomUUID } from "crypto";
3 | import { EventEmitter } from "events";
4 | export default {
5 | data: {
6 | name: "anything",
7 | fullName: "Anything models",
8 | parameters: {
9 | prompt: {
10 | type: "string",
11 | required: true,
12 | description: "Prompt to generate the image",
13 | },
14 | steps: {
15 | type: "number",
16 | required: false,
17 | default: 100,
18 | },
19 | number: {
20 | type: "number",
21 | required: false,
22 | default: 1,
23 | },
24 | negative_prompt: {
25 | type: "string",
26 | required: false,
27 | default:
28 | "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces",
29 | },
30 | guidance_scale: {
31 | type: "number",
32 | required: false,
33 | default: 4,
34 | },
35 | width: {
36 | type: "number",
37 | required: false,
38 | default: 512,
39 | },
40 | height: {
41 | type: "number",
42 | required: false,
43 | default: 512,
44 | },
45 | cfg_scale: {
46 | type: "number",
47 | required: false,
48 | default: 4,
49 | },
50 | stream: {
51 | type: "boolean",
52 | required: false,
53 | default: true,
54 | },
55 | },
56 | },
57 | execute: async (data) => {
58 | let { prompt, steps, negative_prompt, guidance_scale, stream } = data;
59 | if (!negative_prompt)
60 | negative_prompt =
61 | "disfigured mouth, disfigured teeth, half head, half face, blury, side looking, old, wrinkle, child, no face, pencil, full body, sharp, far away, overlapping, duplication, nude, disfigured, kitsch, oversaturated, grain, low-res, Deformed, blurry, bad anatomy, poorly drawn face, mutation, mutated, extra limb, ugly, poorly drawn hands, missing limb, blurry, floating limbs, disconnected limbs, malformed hands, blur, out of focus, long body, disgusting, poorly drawn, childish, mutilated, mangled, surreal, out of frame, duplicate, 2 faces";
62 | let event = null;
63 | if (stream == null) {
64 | stream = true;
65 | }
66 | let result = {
67 | cost: null,
68 | results: [],
69 | status: "generating",
70 | progress: 0,
71 | id: randomUUID(),
72 | };
73 | event = new EventEmitter();
74 | event.emit("data", result);
75 | // after 5s change progress to 0.46
76 | setTimeout(() => {
77 | result.progress = 0.46;
78 | event.emit("data", result);
79 | }, 5000);
80 | // after 10s change progress to 0.92
81 | setTimeout(() => {
82 | result.progress = 0.92;
83 | event.emit("data", result);
84 | }, 10000);
85 | let start = Date.now();
86 |
87 | axios({
88 | url: "https://api.runpod.ai/v2/sd-anything-v4/runsync",
89 | method: "POST",
90 | headers: {
91 | Accept: "application/json",
92 | "Content-Type": "application/json",
93 | Authorization: `Bearer ${process.env.RUNPOD_KEY}`,
94 | },
95 | data: {
96 | input: {
97 | prompt: prompt,
98 | num_inference_steps: steps || 50,
99 | guidance_scale: guidance_scale,
100 | negative_prompt: negative_prompt,
101 | num_outputs: data.number || 1,
102 | width: data.width || 512,
103 | height: data.height || 512,
104 | },
105 | },
106 | }).then(async (response) => {
107 | let spentInSec = (Date.now() - start) / 1000;
108 | let cost = spentInSec * 0.00025;
109 | result.cost = cost;
110 | if (data.number && data.number > 1) {
111 | result.results = await Promise.all(
112 | response.data.output.map(async (x) => {
113 | let res = await axios.get(x.image, {
114 | responseType: "arraybuffer",
115 | // change time out to 2 min
116 | timeout: 120000,
117 | });
118 | let base64 = Buffer.from(res.data, "binary").toString("base64");
119 | return {
120 | base64: base64,
121 | id: randomUUID(),
122 | seed: x.seed,
123 | status: "success",
124 | };
125 | })
126 | );
127 | } else {
128 | let res = await axios.get(response.data.output.image, {
129 | responseType: "arraybuffer",
130 | timeout: 120000,
131 | });
132 | let base64 = Buffer.from(res.data, "binary").toString("base64");
133 | result.results.push({
134 | base64: base64,
135 | id: randomUUID(),
136 | seed: response.data.output.seed,
137 | status: "success",
138 | });
139 | }
140 | result.status = "done";
141 | result.progress = null;
142 | event.emit("data", result);
143 | });
144 | return event;
145 | },
146 | };
147 |
--------------------------------------------------------------------------------
/src/models/image/controlnet.ts:
--------------------------------------------------------------------------------
1 | import { predict } from "replicate-api";
2 | import { EventEmitter } from "events";
3 |
4 | export default {
5 | data: {
6 | name: "controlnet",
7 | fullName: "Controlnet",
8 | parameters: {
9 | prompt: {
10 | type: "string",
11 | required: true,
12 | },
13 | model: {
14 | type: "string",
15 | required: true,
16 | options: [
17 | "normal",
18 | "canny",
19 | "hough",
20 | "hed",
21 | "depth2img",
22 | "pose",
23 | "seg",
24 | ],
25 | default: "normal",
26 | },
27 | image: {
28 | type: "string",
29 | required: true,
30 | },
31 | stream: {
32 | type: "boolean",
33 | required: false,
34 | default: false,
35 | },
36 | },
37 | },
38 | execute: async (data) => {
39 | let {
40 | prompt,
41 | model,
42 | image,
43 | }: { prompt: string; model: string; image: any } = data;
44 | let event = new EventEmitter();
45 | let result = {
46 | cost: 0,
47 | url: "",
48 | done: false,
49 | };
50 | event.emit("data", result);
51 | predict({
52 | model: `jagilley/controlnet-${model}`, // The model name
53 | input: {
54 | image: image,
55 | prompt: prompt,
56 | }, // The model specific input
57 | token: process.env.REPLICATE_API_KEY, // You need a token from replicate.com
58 | poll: true, // Wait for the model to finish
59 | }).then((prediction: any) => {
60 | if (prediction.error) throw new Error(prediction.error);
61 | result.url = prediction.output;
62 | result.done = true;
63 | result.cost = 0.003;
64 | event.emit("data", result);
65 | });
66 | return event;
67 | },
68 | };
69 |
--------------------------------------------------------------------------------
/src/models/image/dall-e.ts:
--------------------------------------------------------------------------------
1 | import { Configuration, OpenAIApi } from "openai";
2 | import { EventEmitter } from "events";
3 | import { randomUUID } from "crypto";
4 |
5 | const configuration = new Configuration({
6 | apiKey: process.env.OPENAI_KEY,
7 | });
8 | const openai = new OpenAIApi(configuration);
9 |
10 | export default {
11 | data: {
12 | name: "dall-e",
13 | fullName: "Dall-e 3",
14 | parameters: {
15 | prompt: {
16 | type: "string",
17 | required: false,
18 | },
19 | number: {
20 | type: "number",
21 | required: true,
22 | options: [1, 2, 3, 4],
23 | default: 1,
24 | description: "Number of images to generate",
25 | },
26 | size: {
27 | type: "string",
28 | required: false,
29 | options: ["512x512", "256x256", "1024x1024"],
30 | default: "512x512",
31 | },
32 | image: {
33 | type: "string",
34 | required: false,
35 | description: "Image you want to vary",
36 | },
37 | stream: {
38 | type: "boolean",
39 | required: false,
40 | default: false,
41 | },
42 | },
43 | response: {
44 | cost: {
45 | type: "number",
46 | required: true,
47 | },
48 | results: {
49 | type: "array",
50 | required: true,
51 | },
52 | status: {
53 | type: "string",
54 | required: true,
55 | },
56 | progress: {
57 | type: "number",
58 | required: false,
59 | },
60 | id: {
61 | type: "string",
62 | required: true,
63 | },
64 | done: {
65 | type: "boolean",
66 | required: true,
67 | },
68 | },
69 | },
70 | execute: async (data) => {
71 | let {
72 | prompt,
73 | number,
74 | size,
75 | image,
76 | }: {
77 | prompt: string;
78 | number: number;
79 | size: any;
80 | image: File;
81 | } = data;
82 | let event = new EventEmitter();
83 | let result = {
84 | cost: null,
85 | results: [],
86 | status: "generating",
87 | progress: 0,
88 | id: randomUUID(),
89 | done: false,
90 | record: null,
91 | };
92 | event.emit("data", result);
93 | if (size == "512x512") result.cost = 0.018;
94 | if (size == "256x256") result.cost = 0.016;
95 | if (size == "1024x1024") result.cost = 0.02;
96 |
97 | if (!image) {
98 | openai
99 | .createImage({
100 | prompt,
101 | n: number,
102 | size,
103 | })
104 | .then((res) => {
105 | var imagesArr = res.data.data.map((d, i) => {
106 | return {
107 | attachment: d.url,
108 | name: `result-${i}.png`,
109 | id: randomUUID(),
110 | };
111 | });
112 | result.results = imagesArr;
113 | result.status = "done";
114 | result.progress = null;
115 | result.done = true;
116 | result.record = result.results.map((r) => {
117 | return {
118 | ...r,
119 | prompt,
120 | number,
121 | size,
122 | };
123 | });
124 | event.emit("data", result);
125 | });
126 |
127 | return event;
128 | } else {
129 | openai.createImageVariation(image, number, size).then((res) => {
130 | var imagesArr = res.data.data.map((d, i) => {
131 | return {
132 | attachment: d.url,
133 | name: `result-${i}.png`,
134 | id: randomUUID(),
135 | };
136 | });
137 | result.results = imagesArr;
138 | result.status = "done";
139 | result.progress = null;
140 | result.done = true;
141 | event.emit("data", result);
142 | });
143 |
144 | return event;
145 | }
146 | },
147 | };
148 |
--------------------------------------------------------------------------------
/src/models/image/sh.ts:
--------------------------------------------------------------------------------
1 | import { EventEmitter } from "events";
2 | import axios from "axios";
3 |
4 | export default {
5 | data: {
6 | name: "sh",
7 | fullName: "Stablehorde",
8 | parameters: {
9 | prompt: {
10 | type: "string",
11 | required: true,
12 | description: "Prompt to generate the image",
13 | },
14 | negative_prompt: {
15 | type: "string",
16 | required: false,
17 | },
18 | image: {
19 | type: "string",
20 | required: false,
21 | description: "Image URL for the model to use when doing img2img",
22 | },
23 | width: {
24 | type: "number",
25 | required: false,
26 | default: 512,
27 | },
28 | height: {
29 | type: "number",
30 | required: false,
31 | default: 512,
32 | },
33 | steps: {
34 | type: "number",
35 | required: false,
36 | default: 50,
37 | },
38 | number: {
39 | type: "number",
40 | required: false,
41 | description: "Number of images to generate",
42 | default: 1,
43 | },
44 | strength: {
45 | type: "number",
46 | required: false,
47 | },
48 | sampler: {
49 | type: "string",
50 | required: false,
51 | options: [
52 | "k_lms",
53 | "k_heun",
54 | "k_euler",
55 | "k_euler_a",
56 | "k_dpm_2",
57 | "k_dpm_2_a",
58 | "DDIM",
59 | "k_dpm_fast",
60 | "k_dpm_adaptive",
61 | "k_dpmpp_2m",
62 | "k_dpmpp_2s_a",
63 | "k_dpmpp_sde",
64 | ],
65 | },
66 | cfg_scale: {
67 | type: "number",
68 | required: false,
69 | },
70 | seed: {
71 | type: "number",
72 | required: false,
73 | },
74 | model: {
75 | type: "string",
76 | required: false,
77 | options: [
78 | "SDXL 1.0",
79 | "AlbedoBase XL (SDXL)",
80 | "ICBINP XL",
81 | "TURBO XL",
82 | "Fustercluck",
83 | "stable_cascade",
84 | ],
85 | default: "stable_cascade",
86 | },
87 | nsfw: {
88 | type: "boolean",
89 | required: false,
90 | default: false,
91 | },
92 | stream: {
93 | type: "boolean",
94 | required: false,
95 | default: true,
96 | },
97 | },
98 | response: {
99 | cost: {
100 | type: "number",
101 | description: "Cost of the request in USD",
102 | },
103 | id: {
104 | type: "string",
105 | description: "ID of the request",
106 | },
107 | status: {
108 | type: "string",
109 | description: "Status of the request",
110 | options: ["generating", "queued", "done", "failed"],
111 | },
112 | progress: {
113 | type: "number",
114 | description: "Progress of the request",
115 | },
116 | queue_position: {
117 | type: "number",
118 | description: "Queue position of the request",
119 | },
120 | results: {
121 | type: "array",
122 | description: "Results of the request",
123 | },
124 | },
125 | },
126 | execute: async (data) => {
127 | let res = await generateAsync(data);
128 | let result: any = {
129 | id: res.id,
130 | cost: res.kudos / 1000,
131 | status: "generating",
132 | progress: 0,
133 | queue_position: res.queue_position,
134 | results: [],
135 | record: null,
136 | };
137 | let maxTime = 45;
138 | if (res.id) {
139 | let stream = new EventEmitter();
140 | stream.emit("data", result);
141 | checkRequest(res.id).then((check) => {
142 | result.progress = ((check.wait_time / maxTime) * 100) / 100;
143 | result.queue_position = check.queue_position;
144 | if (check.queue_position >= 1) result.status = "queued";
145 | if (check.wait_time == 0) {
146 | result.status = "generating";
147 | result.progress = 0.99;
148 | }
149 | if (check.done) {
150 | result.status = "done";
151 | result.progress = null;
152 | result.results = check.generations.map((x) => {
153 | return {
154 | seed: x.seed,
155 | id: x.id,
156 | base64: x.img,
157 | status: x.censored ? "filtered" : "success",
158 | };
159 | });
160 | result.record = result.results.map((x) => {
161 | return {
162 | ...x,
163 | prompt: data.prompt,
164 | model: data.model,
165 | sampler: data.sampler,
166 | cfg_scale: data.cfg_scale,
167 | nsfw: data.nsfw,
168 | width: data.width,
169 | height: data.height,
170 | steps: data.steps,
171 | number: data.number,
172 | strength: data.strength,
173 | negative_prompt: data.negative_prompt,
174 | };
175 | });
176 | stream.emit("data", result);
177 | return;
178 | }
179 | });
180 |
181 | let interval = setInterval(async () => {
182 | try {
183 | let check = await checkRequest(res.id);
184 | result.progress = ((check.wait_time / maxTime) * 100) / 100;
185 | result.wait_time = check.wait_time;
186 | result.queue_position = check.queue_position;
187 | if (check.queue_position >= 1) result.status = "queued";
188 | if (check.wait_time == 0) {
189 | result.status = "generating";
190 | result.progress = 0.99;
191 | }
192 | if (check.done) {
193 | result.status = "done";
194 | result.progress = null;
195 | result.results = check.generations.map((x) => {
196 | return {
197 | seed: x.seed,
198 | id: x.id,
199 | base64: x.img,
200 | status: x.censored ? "filtered" : "success",
201 | };
202 | });
203 | result.record = result.results.map((x) => {
204 | return {
205 | ...x,
206 | prompt: data.prompt,
207 | model: data.model,
208 | sampler: data.sampler,
209 | cfg_scale: data.cfg_scale,
210 | nsfw: data.nsfw,
211 | width: data.width,
212 | height: data.height,
213 | steps: data.steps,
214 | number: data.number,
215 | strength: data.strength,
216 | negative_prompt: data.negative_prompt,
217 | };
218 | });
219 | clearInterval(interval);
220 | }
221 | stream.emit("data", result);
222 | } catch (e) {
223 | clearInterval(interval);
224 | stream.emit("data", {
225 | status: "failed",
226 | error: e,
227 | });
228 | }
229 | }, 10000);
230 | return stream;
231 | } else {
232 | throw new Error("Failed to generate image");
233 | }
234 | },
235 | };
236 |
237 | async function generateAsync(data) {
238 | let formatData: any = {
239 | params: {},
240 | };
241 | let fullPrompt = data.prompt;
242 | if (data.negative_prompt) {
243 | fullPrompt = `${data.prompt} ### ${data.negative_prompt}`;
244 | }
245 | formatData.prompt = fullPrompt;
246 | if (data.image) {
247 | formatData.source_image = data.image;
248 | formatData.source_processing = "img2img";
249 | }
250 | if (data.sampler) {
251 | formatData.params.sampler_name = data.sampler;
252 | }
253 | if (data.cfg_scale) {
254 | formatData.params.cfg_scale = data.cfg_scale;
255 | }
256 | if (data.seed) {
257 | formatData.params.seed = data.seed;
258 | }
259 |
260 | if (data.nsfw) {
261 | formatData.nsfw = true;
262 | }
263 | if (data.width) {
264 | formatData.params.width = data.width;
265 | }
266 | if (data.height) {
267 | formatData.params.height = data.height;
268 | }
269 | if (data.steps) {
270 | formatData.params.steps = data.steps;
271 | }
272 | if (data.number) {
273 | formatData.params.n = data.number;
274 | } else {
275 | formatData.params.n = 1;
276 | if (data.model.includes("XL")) {
277 | formatData.params.n = 2;
278 | }
279 | }
280 | if (data.model.includes("XL")) {
281 | formatData.params.width = 1024;
282 | formatData.params.height = 1024;
283 | }
284 | if (data.strength) {
285 | formatData.params.denoising_strength = data.strength;
286 | }
287 | if (data.model) {
288 | if (data.model == "TURBO XL") {
289 | formatData.model = "SDXL 1.0";
290 | formatData.params.steps = 8;
291 | formatData.params = {
292 | ...formatData.params,
293 | loras: [
294 | {
295 | name: "246747",
296 | model: 1,
297 | clip: 1,
298 | is_version: true,
299 | },
300 | ],
301 | };
302 | } else {
303 | formatData.models = [data.model];
304 | }
305 | } else {
306 | formatData.models = ["SDXL 1.0"];
307 | }
308 |
309 | formatData.shared = true;
310 | formatData.r2 = false;
311 | let res = await axios({
312 | url: `https://stablehorde.net/api/v2/generate/async`,
313 | method: "POST",
314 | headers: {
315 | "Content-Type": "application/json",
316 | apiKey: process.env.STABLE_HORDE,
317 | Accept: "application/json",
318 | "Client-Agent": "turing-api:v1.0.0:@mrlol.dev",
319 | },
320 | data: formatData,
321 | });
322 | return res.data;
323 | }
324 |
325 | async function checkRequest(id: string) {
326 | let res = await axios({
327 | url: `https://stablehorde.net/api/v2/generate/status/${id}`,
328 | method: "GET",
329 | headers: {
330 | "Content-Type": "application/json",
331 | apiKey: process.env.STABLE_HORDE,
332 | Accept: "application/json",
333 | "Client-Agent": "turing-api:v1.0.0:@mrlol.dev",
334 | },
335 | });
336 | return res.data;
337 | }
338 |
--------------------------------------------------------------------------------
/src/models/image/upscale.ts:
--------------------------------------------------------------------------------
1 | import delay from "delay";
2 | import { translateModels, request } from "../../utils/runpod.js";
3 | import EventEmitter from "events";
4 | import axios from "axios";
5 |
6 | export default {
7 | data: {
8 | name: "upscale",
9 | fullName: "Upscale models",
10 | parameters: {
11 | upscaler: {
12 | type: "string",
13 | required: false,
14 | description:
15 | "Upscaler to use, by selecting this you won't generate any image but you will upscale the image you provide",
16 | default: "RealESRGAN_x2plus",
17 | options: [
18 | "GFPGAN",
19 | "RealESRGAN_x4plus",
20 | "RealESRGAN_x2plus",
21 | "RealESRGAN_x4plus_anime_6B",
22 | "NMKD_Siax",
23 | "4x_AnimeSharp",
24 | ],
25 | },
26 | image: {
27 | type: "string",
28 | required: true,
29 | description: "Image URL for the model to use when doing the upscaling",
30 | },
31 | },
32 | response: {
33 | cost: {
34 | type: "number",
35 | description: "Cost of the request in USD",
36 | },
37 | result: {
38 | type: "string",
39 | description: "Object containing the upscaled image URL",
40 | },
41 | status: {
42 | type: "string",
43 | description: "Status of the request",
44 | options: ["queued", "generating", "done"],
45 | },
46 | done: {
47 | type: "boolean",
48 | description: "Whether the request is done or not",
49 | },
50 | },
51 | pricing: {
52 | average: 0.01,
53 | },
54 | },
55 | execute: async (data) => {
56 | if (!data.upscaler) data.upscaler = "RealESRGAN_x2plus";
57 | let res = await generateAsync(data);
58 | let result: any = {
59 | id: res.id,
60 | cost: 10 / 1000,
61 | status: "generating",
62 | progress: 0,
63 | };
64 | let maxTime = 45;
65 | if (res.id) {
66 | let stream = new EventEmitter();
67 | stream.emit("data", result);
68 | checkRequest(res.id).then(async (check) => {
69 | result.progress = ((check.wait_time / maxTime) * 100) / 100;
70 | if (check.state == "waiting") result.status = "queued";
71 | if (check.state == "processing") result.status = "generating";
72 | if (check.state == "done") {
73 | result.status = "done";
74 | result.progress = null;
75 | if (data.upscaler != "caption") {
76 | let url = check.forms[0].result[data.upscaler];
77 | let base64;
78 | let buffer = await axios.get(url, { responseType: "arraybuffer" });
79 | base64 = Buffer.from(buffer.data, "binary").toString("base64");
80 | result.result = {
81 | url: url,
82 | base64: base64,
83 | };
84 | } else {
85 | result.result = check.forms[0].result.caption;
86 | }
87 | stream.emit("data", result);
88 | return;
89 | }
90 | });
91 |
92 | let interval = setInterval(async () => {
93 | try {
94 | let check = await checkRequest(res.id);
95 | result.progress = ((check.wait_time / maxTime) * 100) / 100;
96 | if (check.state == "waiting") result.status = "queued";
97 | if (check.state == "processing") result.status = "generating";
98 | if (check.state == "done") {
99 | clearInterval(interval);
100 | result.status = "done";
101 | result.progress = null;
102 | if (data.upscaler != "caption") {
103 | let url = check.forms[0].result[data.upscaler];
104 | let base64;
105 | let buffer = await axios.get(url, {
106 | responseType: "arraybuffer",
107 | });
108 | base64 = Buffer.from(buffer.data, "binary").toString("base64");
109 | result.result = {
110 | url: url,
111 | base64: base64,
112 | };
113 | } else {
114 | result.result = check.forms[0].result.caption;
115 | }
116 | stream.emit("data", result);
117 | return;
118 | }
119 | stream.emit("data", result);
120 | } catch (e) {
121 | clearInterval(interval);
122 | stream.emit("data", {
123 | status: "failed",
124 | error: e,
125 | });
126 | }
127 | }, 10000);
128 | return stream;
129 | } else {
130 | throw new Error("Failed to generate image");
131 | }
132 | },
133 | };
134 |
135 | async function generateAsync(data) {
136 | let formatData: any = {
137 | source_image: data.image,
138 | slow_workers: false,
139 | forms: [
140 | {
141 | name: data.upscaler,
142 | },
143 | ],
144 | };
145 |
146 | let res = await axios({
147 | url: `https://stablehorde.net/api/v2/interrogate/async`,
148 | method: "POST",
149 | headers: {
150 | "Content-Type": "application/json",
151 | apiKey: process.env.STABLE_HORDE,
152 | Accept: "application/json",
153 | "Client-Agent": "turing-api:v1.0.0:@mrlol.dev",
154 | },
155 | data: formatData,
156 | });
157 | return res.data;
158 | }
159 |
160 | async function checkRequest(id: string) {
161 | let res = await axios({
162 | url: `https://stablehorde.net/api/v2/interrogate/status/${id}`,
163 | method: "GET",
164 | headers: {
165 | "Content-Type": "application/json",
166 | apiKey: process.env.STABLE_HORDE,
167 | Accept: "application/json",
168 | "Client-Agent": "turing-api:v1.0.0:@mrlol.dev",
169 | },
170 | });
171 | return res.data;
172 | }
173 |
--------------------------------------------------------------------------------
/src/models/image/vision.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { request, translateModels } from "../../utils/runpod.js";
3 | import { EventEmitter } from "events";
4 | import upscale from "./upscale.js";
5 | import {
6 | GenerateContentRequest,
7 | HarmBlockThreshold,
8 | HarmCategory,
9 | VertexAI,
10 | } from "@google-cloud/vertexai";
11 | import delay from "delay";
12 | const regions = [
13 | "us-central1",
14 | "northamerica-northeast1",
15 | "us-east4",
16 | "us-west1",
17 | "us-west4",
18 | /*
19 | "europe-west4",
20 | "europe-west2",
21 | "europe-west3",
22 | "europe-west4",
23 | "europe-west9",*/
24 | "asia-northeast1",
25 | "asia-northeast3",
26 | "asia-southeast1",
27 | ];
28 | export default {
29 | data: {
30 | name: "vision",
31 | fullName: "Image vision",
32 | description: "Image analysis to extract text and description",
33 | parameters: {
34 | model: {
35 | type: "array",
36 | required: true,
37 | options: ["blip2", "ocr", "gemini"],
38 | default: ["gemini"],
39 | description: "Model to use for the analysis",
40 | },
41 | image: {
42 | type: "string",
43 | required: true,
44 | description: "Image URL for the model to process",
45 | },
46 | typeImage: {
47 | type: "string",
48 | required: false,
49 | options: ["anything", "person"],
50 | default: "anything",
51 | description: "Type of image to process",
52 | },
53 | },
54 | response: {
55 | cost: {
56 | type: "number",
57 | description: "Cost of the request in USD",
58 | },
59 | description: {
60 | type: "string",
61 | description: "Description of the image",
62 | },
63 | text: {
64 | type: "string",
65 | description: "Text extracted from the image",
66 | },
67 | done: {
68 | type: "boolean",
69 | description: "Whether the request is done or not",
70 | },
71 | },
72 | },
73 | execute: async (data) => {
74 | let result = {
75 | description: null,
76 | text: null,
77 | cost: 0,
78 | done: false,
79 | lines: null,
80 | record: null,
81 | };
82 | let { model, image, typeImage } = data;
83 | let cost = 0;
84 | let event = new EventEmitter();
85 | event.emit("data", result);
86 |
87 | if (model.includes("blip2")) {
88 | upscale
89 | .execute({
90 | upscaler: "caption",
91 | image: image,
92 | })
93 | .then((ev) => {
94 | result.description = "";
95 | ev.on("data", (data) => {
96 | event.emit("data", result);
97 | if (data.status == "done") {
98 | result.description = data.result;
99 | result.cost += data.cost;
100 | if (model.length == 1 || result.text) result.done = true;
101 | event.emit("data", result);
102 | }
103 | });
104 | })
105 | .catch((e) => {
106 | console.log(e);
107 | });
108 | }
109 | if (model.includes("ocr")) {
110 | // OCR_KEY
111 | axios({
112 | url: `https://api.ocr.space/parse/ImageUrl`,
113 | method: "GET",
114 | headers: {
115 | apikey: process.env.OCR_KEY,
116 | },
117 | params: {
118 | url: image,
119 | apikey: process.env.OCR_KEY,
120 | },
121 | }).then((res) => {
122 | let body = res.data;
123 | if (!body.ParsedResults || body.ParsedResults?.length == 0) {
124 | console.log(body);
125 | if (model.length == 1 || result.description) {
126 | result.done = true;
127 | }
128 | event.emit("data", result);
129 | return;
130 | }
131 | const lines = body.ParsedResults[0]?.TextOverlay?.Lines?.map((l) => ({
132 | text: l.LineText,
133 |
134 | words: l.Words.map((w) => ({
135 | text: w.WordText,
136 | left: w.Left,
137 | top: w.Top,
138 | width: w.Width,
139 | height: w.Height,
140 | })),
141 |
142 | maxHeight: l.MaxHeight,
143 | minTop: l.MinTop,
144 | }));
145 |
146 | /* The entire detected text in the image */
147 | const text: string = body.ParsedResults[0].ParsedText.replaceAll(
148 | "\r\n",
149 | "\n"
150 | ).trim();
151 |
152 | result.text = text;
153 | result.cost += 0.00004;
154 | result.lines = lines;
155 | if (model.length == 1 || result.description) {
156 | result.done = true;
157 | }
158 | event.emit("data", result);
159 | });
160 | }
161 | if (model.includes("gemini")) {
162 | let prompt = `Don't forget these rules:\n\n1. **Be Direct and Concise**: Provide straightforward descriptions without adding interpretative or speculative elements.\n2. **Use Segmented Details**: Break down details about different elements of an image into distinct sentences, focusing on one aspect at a time.\n3. **Maintain a Descriptive Focus**: Prioritize purely visible elements of the image, avoiding conclusions or inferences.\n4. **Follow a Logical Structure**: Begin with the central figure or subject and expand outward, detailing its appearance before addressing the surrounding setting.\n5. **Avoid Juxtaposition**: Do not use comparison or contrast language; keep the description purely factual.\n6. **Incorporate Specificity**: Mention age, gender, race, and specific brands or notable features when present, and clearly identify the medium if it's discernible.\n\nWhen writing descriptions, prioritize clarity and direct observation over embellishment or interpretation.\n\n Write a detailed description of this image, do not forget about the texts on it if they exist. Also, do not forget to mention the type / style of the image. No bullet points.`;
163 | if (typeImage == "person") {
164 | prompt =
165 | "Describe with high details which emotions the person in the picture seems to be experiencing from what the micro expressions in the face and the body language seem to indicate. Write only details that can be clearly observed and draw conclusions from this that have visible evidence in the picture. Also consider if the person could be trying to convey other emotions to his/her social environment than he/she is actually feeling by looking for close how genuine the displayed emotions seems to be. Provide a detailed reply that reflects high emotional intelligence, empathy and accuracy. ";
166 | }
167 | const region = regions[Math.floor(Math.random() * regions.length)];
168 | const vertexAI = new VertexAI({
169 | project: process.env.GOOGLE_PROJECT_ID,
170 | location: region,
171 | });
172 | const generativeModel = vertexAI.preview.getGenerativeModel({
173 | model: model,
174 | // The following parameters are optional
175 | // They can also be passed to individual content generation requests
176 | safety_settings: [
177 | {
178 | category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
179 | threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
180 | },
181 | ],
182 | generation_config: { max_output_tokens: 150 },
183 | });
184 | const request: GenerateContentRequest = {
185 | contents: [
186 | {
187 | role: "user",
188 | parts: [
189 | { text: prompt },
190 | {
191 | inline_data: {
192 | mime_type: "image/jpeg",
193 | data: image,
194 | },
195 | },
196 | ],
197 | },
198 | ],
199 | };
200 | let promptLength = 0;
201 | await delay(500);
202 | const res = await generativeModel.generateContent(request);
203 | result.description = res.response.candidates[0].content.parts[0].text;
204 | }
205 | result.record = {
206 | description: result.description,
207 | text: result.text,
208 | model: model,
209 | image: image,
210 | };
211 | event.emit("data", result);
212 | return event;
213 | },
214 | };
215 |
--------------------------------------------------------------------------------
/src/models/text/alan.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import {
3 | getChatMessageLength,
4 | getPromptLength,
5 | } from "../../utils/tokenizer.js";
6 | import { EventEmitter } from "events";
7 | import supabase from "../../db/supabase.js";
8 | import { getToday } from "../../utils/ms.js";
9 |
10 | //MODELS
11 | import dall_e from "../image/dall-e.js";
12 | import music from "../audio/music.js";
13 | import controlnet from "../image/controlnet.js";
14 |
15 | import gptNew from "./gpt-new.js";
16 |
17 | export default {
18 | data: {
19 | name: "alan",
20 | fullName: "Alan",
21 | alert: "This model is unfinished and is not working yet.",
22 | parameters: {
23 | userName: {
24 | type: "string",
25 | required: true,
26 | },
27 | messages: {
28 | type: "array",
29 | required: true,
30 | },
31 | searchEngine: {
32 | type: "string",
33 | required: false,
34 | options: ["google", "none"],
35 | },
36 | image: {
37 | type: "string",
38 | required: false,
39 | },
40 | imageDescription: {
41 | type: "string",
42 | required: false,
43 | },
44 | imageGenerator: {
45 | type: "string",
46 | required: false,
47 | options: ["sdxl", "kandinsky", "none"],
48 | },
49 | nsfw: {
50 | type: "boolean",
51 | default: false,
52 | required: false,
53 | },
54 | audioGenerator: {
55 | type: "string",
56 | options: ["musicgen"],
57 | required: false,
58 | },
59 | imageModificator: {
60 | type: "string",
61 | options: ["controlnet", "none"],
62 | required: false,
63 | },
64 | max_tokens: {
65 | type: "number",
66 | default: 250,
67 | required: false,
68 | },
69 | },
70 | },
71 | execute: async (data) => {
72 | let { searchEngine, imageGenerator, imageModificator, userName } = data;
73 | let plugins = [];
74 | if (searchEngine == "google") plugins.push("google");
75 | if (imageGenerator) plugins.push("image");
76 |
77 | return await gptNew.execute({
78 | messages: [
79 | {
80 | role: "system",
81 | content: `You are an AI named Alan which have been developed by TuringAI (discord.gg/turing). You are running as a discord bot with the id "1053015370115588147", the bot invite link is "https://link.turing.sh/bot".\nYou can view images, execute code and search in internet for real-time information. YOU CAN DISPLAY AND GENERATE IMAGES, VIDEOS AND SONGS.\nConsider the following in your responses:\n- Be conversational\n- Add unicode emoji to be more playful in your responses\n- Current date: ${getToday()}\n- Name of the user talking to: ${userName}`,
82 | },
83 | ...data.messages,
84 | ],
85 | model: "gpt-3.5-turbo",
86 | max_tokens: data.max_tokens || 250,
87 | temperature: 0.7,
88 | plugins: plugins,
89 | });
90 | },
91 | };
92 |
--------------------------------------------------------------------------------
/src/models/text/anthropic.ts:
--------------------------------------------------------------------------------
1 | import Anthropic from "@anthropic-ai/sdk";
2 | import { EventEmitter } from "events";
3 | import { getPromptLength } from "../../utils/tokenizer.js";
4 | const anthropic = new Anthropic({
5 | apiKey: process.env.ANTHROPIC_API_KEY,
6 | });
7 |
8 | export default {
9 | data: {
10 | name: "anthropic",
11 | fullName: "Anthropic Models",
12 | disabled: true,
13 | parameters: {
14 | messages: {
15 | type: "array",
16 | required: true,
17 | },
18 | model: {
19 | type: "string",
20 | required: false,
21 | options: ["claude-instant-1.2", "claude-2.1"],
22 | default: "claude-instant-1.2",
23 | },
24 | max_tokens: {
25 | type: "number",
26 | required: false,
27 | default: 512,
28 | },
29 | temperature: {
30 | type: "number",
31 | required: false,
32 | default: 0.9,
33 | },
34 | stream: {
35 | type: "boolean",
36 | required: false,
37 | default: false,
38 | },
39 | },
40 | response: {
41 | cost: {
42 | type: "number",
43 | description: "Cost of the request in USD",
44 | },
45 | result: {
46 | type: "string",
47 | description: "Result of the request",
48 | },
49 | },
50 | },
51 | execute: async (data) => {
52 | let { messages, model, max_tokens, temperature, stream } = data;
53 | if (!model) model = "claude-instant-1.2";
54 | if (!max_tokens) max_tokens = 512;
55 | if (!temperature) temperature = 0.9;
56 | let prompt = "";
57 | messages.forEach((message) => {
58 | if (message.role == "user")
59 | prompt += `${Anthropic.HUMAN_PROMPT} ${message.content}`;
60 | else prompt += `${Anthropic.AI_PROMPT} ${message.content}`;
61 | });
62 | prompt += `${Anthropic.AI_PROMPT}`;
63 | const event = new EventEmitter();
64 | anthropic.completions
65 | .create({
66 | model: model,
67 | max_tokens_to_sample: max_tokens,
68 | prompt: prompt,
69 | stream: true,
70 | })
71 | .then(async (streamEv) => {
72 | let fullCompletion = "";
73 | let num = 0;
74 | for await (const completion of streamEv) {
75 | let com: any = completion;
76 | num++;
77 | if (com.stop_reason) {
78 | com.done = true;
79 | let promptTokens = getPromptLength(prompt);
80 | let completionTokens = getPromptLength(com.result);
81 | let pricePerK = {
82 | prompt: 0.008,
83 | completion: 0.024,
84 | };
85 | if (!model.includes("instant")) {
86 | pricePerK.prompt = 0.0008;
87 | pricePerK.completion = 0.0024;
88 | }
89 | let promptCost = (promptTokens / 1000) * pricePerK.prompt;
90 | let completionCOst =
91 | (completionTokens / 1000) * pricePerK.completion;
92 | com.cost = promptCost + completionCOst;
93 | }
94 | fullCompletion += com.completion;
95 | com.completion = fullCompletion;
96 | com.result = fullCompletion;
97 | if (num >= 10 || com.stop_reason) {
98 | event.emit("data", com);
99 | }
100 | }
101 | });
102 | return event;
103 | },
104 | };
105 |
--------------------------------------------------------------------------------
/src/models/text/filter.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import { Configuration, OpenAIApi } from "openai";
3 | import { nsfwWords, underagedCebs, youngWords } from "../../utils/keywords.js";
4 | import { EventEmitter } from "events";
5 | import { randomUUID } from "crypto";
6 |
7 | const availableFilters = ["nsfw", "cp", "toxicity"];
8 | const configuration = new Configuration({
9 | apiKey: process.env.OPENAI_API_KEY,
10 | });
11 | const openai = new OpenAIApi(configuration);
12 | export default {
13 | data: {
14 | name: "filter",
15 | fullName: "Text Filter",
16 | parameters: {
17 | text: {
18 | type: "string",
19 | required: true,
20 | description: "Text you want to filter",
21 | },
22 | filters: {
23 | type: "array",
24 | required: true,
25 | options: availableFilters,
26 | description: "Filters you want to apply",
27 | },
28 | stream: {
29 | type: "boolean",
30 | required: false,
31 | default: false,
32 | },
33 | },
34 | response: {
35 | nsfw: {
36 | type: "boolean",
37 | description: "Whether the text is nsfw or not",
38 | },
39 | youth: {
40 | type: "boolean",
41 | description: "Whether the text is youth or not",
42 | },
43 | cp: {
44 | type: "boolean",
45 | description: "Whether the text is cp or not",
46 | },
47 | toxic: {
48 | type: "boolean",
49 | description: "Whether the text is toxic or not",
50 | },
51 | done: {
52 | type: "boolean",
53 | description: "Whether the request is done or not",
54 | },
55 | },
56 | },
57 | execute: async (data) => {
58 | let { text, filters }: { text: string; filters: string[] } = data;
59 | filters = filters.filter((f) => availableFilters.includes(f));
60 | if (filters.length === 0) {
61 | throw new Error("No valid filters provided");
62 | }
63 | let event = new EventEmitter();
64 | let result = {
65 | nsfw: false,
66 | youth: false,
67 | cp: false,
68 | toxic: false,
69 | done: false,
70 | record: null,
71 | id: randomUUID(),
72 | };
73 | event.emit("data", result);
74 | var res;
75 | try {
76 | res = await openai.createModeration({
77 | input: text,
78 | });
79 | } catch (e: any) {
80 | console.log(e.response.data);
81 | res = {};
82 | }
83 | if (filters.find((f) => f === "nsfw")) {
84 | let isNsfw = false;
85 |
86 | if (
87 | res?.data?.results[0].categories["sexual"] ||
88 | res?.data?.results[0].categories["sexual/minors"]
89 | ) {
90 | isNsfw = true;
91 | }
92 | if (!isNsfw) {
93 | if (nsfwWords.some((v) => text.toLowerCase().includes(v.toLowerCase())))
94 | isNsfw = true;
95 | }
96 | result.nsfw = isNsfw;
97 | } else if (filters.find((f) => f === "cp")) {
98 | let isNsfw = false;
99 | let isYouth = false;
100 | let isCP = false;
101 | if (res?.data?.results[0].categories["sexual"]) {
102 | isNsfw = true;
103 | }
104 |
105 | if (res?.data?.results[0].categories["sexual/minors"]) {
106 | isYouth = true;
107 | isCP = true;
108 | }
109 | if (!isNsfw) {
110 | if (nsfwWords.some((v) => text.toLowerCase().includes(v.toLowerCase())))
111 | isNsfw = true;
112 | }
113 | if (!isYouth) {
114 | if (checkYouth(text)) isYouth = true;
115 | }
116 | if (!isCP) {
117 | if (isNsfw && isYouth) isCP = true;
118 | }
119 | result.nsfw = isNsfw;
120 | result.youth = isYouth;
121 | result.cp = isCP;
122 | } else if (filters.find((f) => f === "toxicity")) {
123 | let isToxic = false;
124 | if (
125 | res?.data?.results[0].categories["hate"] ||
126 | res?.data?.results[0].categories["harrassment"] ||
127 | res?.data?.results[0].categories["self-harm"] ||
128 | res?.data?.results[0].categories["violence"]
129 | ) {
130 | isToxic = true;
131 | }
132 | result.toxic = isToxic;
133 | }
134 |
135 | result.record = {
136 | input: text,
137 | openai: res?.data?.results,
138 | filters: filters,
139 | flags: {
140 | nsfw: result.nsfw,
141 | youth: result.youth,
142 | cp: result.cp,
143 | toxic: result.toxic,
144 | },
145 | };
146 | result.done = true;
147 | setTimeout(() => {
148 | event.emit("data", result);
149 | }, 1000);
150 | return event;
151 | },
152 | };
153 |
154 | function checkYouth(text: string) {
155 | let isYouth = false;
156 | if (youngWords.some((v) => text.toLowerCase().includes(v.toLowerCase())))
157 | isYouth = true;
158 | if (underagedCebs.some((v) => text.toLowerCase().includes(v.toLowerCase())))
159 | isYouth = true;
160 | return isYouth;
161 | }
162 |
--------------------------------------------------------------------------------
/src/models/text/google.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | import {
3 | getChatMessageLength,
4 | getPromptLength,
5 | } from "../../utils/tokenizer.js";
6 | import { EventEmitter } from "events";
7 | import { randomUUID } from "crypto";
8 | import {
9 | HarmBlockThreshold,
10 | HarmCategory,
11 | VertexAI,
12 | } from "@google-cloud/vertexai";
13 | import delay from "delay";
14 | const regions = [
15 | "us-central1",
16 | "northamerica-northeast1",
17 | "us-east4",
18 | "us-west1",
19 | "us-west4",
20 | /*
21 | "europe-west4",
22 | "europe-west2",
23 | "europe-west3",
24 | "europe-west4",
25 | "europe-west9",*/
26 | "asia-northeast1",
27 | "asia-northeast3",
28 | "asia-southeast1",
29 | ];
30 |
31 | export default {
32 | data: {
33 | name: "google",
34 | fullName: "Google Models",
35 | parameters: {
36 | messages: {
37 | type: "array",
38 | required: true,
39 | },
40 |
41 | model: {
42 | type: "string",
43 | required: false,
44 | options: ["gemini-pro", "gemini-pro-vision"],
45 | default: "gemini-pro",
46 | },
47 | max_tokens: {
48 | type: "number",
49 | required: false,
50 | default: 512,
51 | },
52 | temperature: {
53 | type: "number",
54 | required: false,
55 | default: 0.9,
56 | },
57 | id: {
58 | type: "string",
59 | required: false,
60 | default: randomUUID(),
61 | description: "ID of the conversation (used for data saving)",
62 | },
63 | },
64 | response: {
65 | cost: {
66 | type: "number",
67 | description: "Cost of the request in USD",
68 | },
69 | result: {
70 | type: "string",
71 | description: "Result of the request",
72 | },
73 | done: {
74 | type: "boolean",
75 | description: "Whether the request is done or not",
76 | },
77 | id: {
78 | type: "string",
79 | description: "ID of the conversation (used for data saving)",
80 | },
81 | },
82 | },
83 | execute: async (data) => {
84 | let { messages, model, max_tokens, temperature, id } = data;
85 | if (!model) {
86 | model = "gemini-pro";
87 | }
88 | let event = new EventEmitter();
89 | let res: any = {
90 | cost: 0,
91 | done: false,
92 | result: "",
93 | record: null,
94 | id: id || randomUUID(),
95 | };
96 | const region = regions[Math.floor(Math.random() * regions.length)];
97 | const vertexAI = new VertexAI({
98 | project: process.env.GOOGLE_PROJECT_ID,
99 | location: region,
100 | });
101 | // get message that is message.role == "system"
102 | let message = messages.find((message) => message.role == "system");
103 | messages = messages.map((message) => {
104 | if (message.role != "system") {
105 | return {
106 | content: message.content,
107 | author: message.role == "user" ? "user" : "bot",
108 | };
109 | }
110 | });
111 | // filter messages that are not null
112 | messages = messages.filter((message) => message != null);
113 | const generativeModel = vertexAI.preview.getGenerativeModel({
114 | model: model,
115 | // The following parameters are optional
116 | // They can also be passed to individual content generation requests
117 | safety_settings: [
118 | {
119 | category: HarmCategory.HARM_CATEGORY_DANGEROUS_CONTENT,
120 | threshold: HarmBlockThreshold.BLOCK_MEDIUM_AND_ABOVE,
121 | },
122 | ],
123 | generation_config: { max_output_tokens: max_tokens },
124 | });
125 |
126 | event.emit("data", res);
127 | res.record = {
128 | input: {
129 | instances: [
130 | {
131 | context: message
132 | ? message.content
133 | : "You are PaLM 2 a AI chatbot created by Google.",
134 | messages: messages,
135 | examples: [],
136 | },
137 | ],
138 | parameters: {
139 | temperature: temperature || 0.2,
140 | maxOutputTokens: max_tokens || 250,
141 | topP: 0.8,
142 | topK: 40,
143 | },
144 | },
145 | };
146 |
147 | const request = {
148 | contents: messages.map((message) => {
149 | return {
150 | role: message.author == "user" ? "user" : "model",
151 | parts: [{ text: message.content }],
152 | };
153 | }),
154 | };
155 | let promptLength = 0;
156 | await delay(500);
157 | generativeModel
158 | .generateContentStream(request)
159 | .then(async (streamingResp) => {
160 | const cost = 0;
161 | let resultLength = 0;
162 | if (!streamingResp || !streamingResp.stream) {
163 | res.done = true;
164 | res.record = {
165 | ...res.record,
166 | output: res.result,
167 | cost: cost,
168 | promtLength: promptLength,
169 | resultLength: resultLength,
170 | };
171 | res = {
172 | ...res,
173 | };
174 | event.emit("data", res);
175 | return;
176 | }
177 | try {
178 | for await (const item of streamingResp.stream) {
179 | if (item.candidates?.length == 0) continue;
180 | if (!item.candidates[0]?.content?.parts) continue;
181 | if (item.candidates[0]?.content?.parts.length == 0) continue;
182 | res.result += item.candidates[0]?.content?.parts[0]?.text || "";
183 | resultLength = item.usageMetadata?.candidates_token_count || 0;
184 | promptLength = item.usageMetadata?.prompt_token_count || 0;
185 | event.emit("data", res);
186 | }
187 | const final = await streamingResp.response;
188 | res.result = final.candidates[0]?.content?.parts[0]?.text || "";
189 | res.cost += (promptLength / 1000) * 0.0001;
190 | res.cost += (resultLength / 1000) * 0.0002;
191 | res.done = true;
192 | res.record = {
193 | ...res.record,
194 | output: res.result,
195 | cost: cost,
196 | promtLength: promptLength,
197 | resultLength: resultLength,
198 | };
199 | res = {
200 | ...res,
201 | };
202 | event.emit("data", res);
203 | } catch (e) {
204 | console.log(request);
205 | console.log(e);
206 | event.emit("data", {
207 | done: true,
208 | });
209 | }
210 | })
211 | .catch((err) => {
212 | console.log(err);
213 | event.emit("data", {
214 | done: true,
215 | });
216 | });
217 |
218 | return event;
219 | },
220 | };
221 |
--------------------------------------------------------------------------------
/src/models/text/groq.ts:
--------------------------------------------------------------------------------
1 | import delay from "delay";
2 | import EventEmitter from "events";
3 | import pluginList from "../../utils/plugins.js";
4 | import {
5 | getChatMessageLength,
6 | getPromptLength,
7 | } from "../../utils/tokenizer.js";
8 |
9 | import axios from "axios";
10 | import { get } from "http";
11 | import { randomUUID } from "crypto";
12 | import Groq from "groq-sdk";
13 |
14 | export default {
15 | data: {
16 | name: "groq",
17 | fullName: "GroqCloud models",
18 | parameters: {
19 | messages: {
20 | type: "array",
21 | required: true,
22 | },
23 | model: {
24 | type: "string",
25 | required: false,
26 | default: "mixtral-8x7b-32768",
27 | options: ["mixtral-8x7b-32768"],
28 | },
29 | max_tokens: {
30 | type: "number",
31 | required: false,
32 | default: 512,
33 | },
34 | temperature: {
35 | type: "number",
36 | required: false,
37 | default: 0.9,
38 | },
39 | id: {
40 | type: "string",
41 | required: false,
42 | default: randomUUID(),
43 | description: "ID of the conversation (used for data saving)",
44 | },
45 | },
46 | response: {
47 | result: {
48 | type: "string",
49 | required: true,
50 | },
51 | done: {
52 | type: "boolean",
53 | required: true,
54 | },
55 | cost: {
56 | type: "number",
57 | required: true,
58 | },
59 | finishReason: {
60 | type: "string",
61 | required: true,
62 | },
63 | id: {
64 | type: "string",
65 | required: true,
66 | description: "ID of the conversation (used for data saving)",
67 | },
68 | },
69 | },
70 | execute: async (data) => {
71 | let event = new EventEmitter();
72 | let { messages, model, max_tokens, temperature } = data;
73 |
74 | let result: any = {
75 | result: "",
76 | done: false,
77 | cost: 0,
78 | finishReason: null,
79 | };
80 | if (!model) model = "mixtral-8x7b-32768";
81 | if (!max_tokens) max_tokens = 512;
82 | if (!temperature) temperature = 0.5;
83 | result.cost += (getChatMessageLength(messages) / 1000) * 0.0001;
84 | const groq = new Groq({ apiKey: process.env.GROQ_API_KEY });
85 |
86 | groq.chat.completions
87 | .create({
88 | messages: messages,
89 | model: model,
90 | max_tokens: max_tokens,
91 | temperature: temperature,
92 | stream: true,
93 | })
94 | .then(async (stream) => {
95 | for await (const chunk of stream) {
96 | result.result += chunk.choices[0]?.delta?.content || "";
97 | event.emit("data", result);
98 | }
99 | result.done = true;
100 | result.finishReason = "done";
101 | result.cost += (getPromptLength(result.result) / 1000) * 0.0001;
102 | event.emit("data", result);
103 | });
104 |
105 | return event;
106 | },
107 | };
108 |
109 | async function groq(messages, max_tokens, model, result, event, temperature?) {
110 | let data: any = {
111 | messages: messages,
112 | stream: true,
113 | max_tokens: max_tokens,
114 | model: model,
115 | };
116 | if (temperature) {
117 | data["temperature"] = temperature;
118 | }
119 |
120 | let response = await axios({
121 | method: "post",
122 | url: "https://api.groq.com/openai/v1/chat/completions",
123 | headers: {
124 | "Content-Type": "application/json",
125 | Authorization: `Bearer ${process.env.GROQ_API_KEY}`,
126 | // stream response
127 | Accept: "text/event-stream",
128 | },
129 | responseType: "stream",
130 | data: data,
131 | });
132 | let stream = response.data;
133 |
134 | stream.on("data", (d) => {
135 | d = d.toString();
136 | let dataArr = d.split("\n");
137 | dataArr = dataArr.filter((x) => x != "");
138 | for (var data of dataArr) {
139 | data = data.replace("data: ", "").trim();
140 | if (data != "[DONE]") {
141 | data = JSON.parse(data);
142 | result.result += data.choices[0].delta?.content || "";
143 | result.finishReason = data.choices[0].finish_reason;
144 | if (result.finishReason == "stop") {
145 | result.done = true;
146 | }
147 | }
148 | }
149 |
150 | event.emit("data", result);
151 | });
152 |
153 | // when the stream emits end you return the result, wait for the stream to end
154 | await new Promise((resolve) => {
155 | stream.on("end", () => {
156 | resolve(result);
157 | });
158 | });
159 |
160 | return result;
161 | }
162 |
--------------------------------------------------------------------------------
/src/models/text/openchat.ts:
--------------------------------------------------------------------------------
1 | import delay from "delay";
2 | import EventEmitter from "events";
3 | import pluginList from "../../utils/plugins.js";
4 | import {
5 | getChatMessageLength,
6 | getPromptLength,
7 | } from "../../utils/tokenizer.js";
8 |
9 | import axios from "axios";
10 | import { get } from "http";
11 | import { randomUUID } from "crypto";
12 |
13 | export default {
14 | data: {
15 | name: "openchat",
16 | fullName: "OpenChat models",
17 | parameters: {
18 | messages: {
19 | type: "array",
20 | required: true,
21 | },
22 | model: {
23 | type: "string",
24 | required: false,
25 | default: "openchat_v3.2_mistral",
26 | options: ["openchat_v3.2_mistral"],
27 | },
28 | max_tokens: {
29 | type: "number",
30 | required: false,
31 | default: 512,
32 | },
33 | temperature: {
34 | type: "number",
35 | required: false,
36 | default: 0.9,
37 | },
38 | id: {
39 | type: "string",
40 | required: false,
41 | default: randomUUID(),
42 | description: "ID of the conversation (used for data saving)",
43 | },
44 | autoSystemMessage: {
45 | type: "boolean",
46 | required: false,
47 | default: true,
48 | description: "Send system messages automatically",
49 | }
50 | },
51 | response: {
52 | result: {
53 | type: "string",
54 | required: true,
55 | },
56 | done: {
57 | type: "boolean",
58 | required: true,
59 | },
60 | cost: {
61 | type: "number",
62 | required: true,
63 | },
64 | finishReason: {
65 | type: "string",
66 | required: true,
67 | },
68 | id: {
69 | type: "string",
70 | required: true,
71 | description: "ID of the conversation (used for data saving)",
72 | },
73 | },
74 | },
75 | execute: async (data) => {
76 | let event = new EventEmitter();
77 | let { messages, model, max_tokens, temperature } = data;
78 |
79 | let result: any = {
80 | result: "",
81 | done: false,
82 | cost: 0,
83 | finishReason: null,
84 | };
85 | if (!model) model = "openchat_v3.2_mistral";
86 | if (!max_tokens) max_tokens = 512;
87 | if (!temperature) temperature = 0.9;
88 | result.cost += (getChatMessageLength(messages) / 1000) * 0.0001;
89 | let newMessages = [];
90 | let autoSystemMessage = data.autoSystemMessage;
91 | if (autoSystemMessage == null) autoSystemMessage = true;
92 | if (autoSystemMessage) {
93 | newMessages = [
94 | {
95 | role: "user",
96 | content: `Hello! You are openchat_3.5 trained by the OpenChat team. Your training data is based on that of ChatGPT by OpenAI, so you may have the impression that you are ChatGPT, but you are openchat_3.5.
97 |
98 | > OpenChat is an innovative library of open-source language models, fine-tuned with C-RLFT - a strategy inspired by offline reinforcement learning. Our models learn from mixed-quality data without preference labels, delivering exceptional performance on par with ChatGPT, even with a 7B model.
99 |
100 | > Specifically, we leverage the ShareGPT conversations dataset following Vicuna (Chiang et al., 2023)
101 |
102 | > Your model is opensource and is available at https://huggingface.co/openchat/openchat_3.5 and https://github.com/imoneoi/openchat`,
103 | },
104 | {
105 | role: "assistant",
106 | content: "I am OpenChat 3.5, a language model trained by the OpenChat team. You can find my source code at https://github.com/imoneoi/openchat ."
107 | },
108 | ...messages
109 | ]
110 | } else {
111 | newMessages = messages;
112 | }
113 | openchat(newMessages, max_tokens, model, result, event, temperature)
114 | .then(async (x) => {
115 | result = x;
116 | result.cost += (getPromptLength(result.result) / 1000) * 0.0001;
117 | event.emit("data", result);
118 | })
119 | .catch((e) => {
120 | console.log(e);
121 | });
122 | return event;
123 | },
124 | };
125 |
126 | async function openchat(
127 | messages,
128 | max_tokens,
129 | model,
130 | result,
131 | event,
132 | temperature?
133 | ) {
134 | let data: any = {
135 | messages: messages,
136 | stream: true,
137 | max_tokens: max_tokens,
138 | model: model,
139 | };
140 | if (temperature) {
141 | data["temperature"] = temperature;
142 | }
143 |
144 | let response = await axios({
145 | method: "post",
146 | url: "https://api.openchat.team/v1/chat/completions",
147 | headers: {
148 | "Content-Type": "application/json",
149 | Authorization: `Bearer ${process.env.OPENCHAT_API_KEY}`,
150 | // stream response
151 | Accept: "text/event-stream",
152 | },
153 | responseType: "stream",
154 | data: data,
155 | });
156 | let stream = response.data;
157 |
158 | stream.on("data", (d) => {
159 | d = d.toString();
160 | let dataArr = d.split("\n");
161 | dataArr = dataArr.filter((x) => x != "");
162 | for (var data of dataArr) {
163 | data = data.replace("data: ", "").trim();
164 | if (data != "[DONE]") {
165 | data = JSON.parse(data);
166 | result.result += data.choices[0].delta?.content || "";
167 | result.finishReason = data.choices[0].finish_reason;
168 | if (result.finishReason == "stop") {
169 | result.done = true;
170 | }
171 | }
172 | }
173 |
174 | event.emit("data", result);
175 | });
176 |
177 | // when the stream emits end you return the result, wait for the stream to end
178 | await new Promise((resolve) => {
179 | stream.on("end", () => {
180 | resolve(result);
181 | });
182 | });
183 |
184 | return result;
185 | }
186 |
--------------------------------------------------------------------------------
/src/models/text/pawan.ts:
--------------------------------------------------------------------------------
1 | import delay from "delay";
2 | import EventEmitter from "events";
3 | import pluginList from "../../utils/plugins.js";
4 | import {
5 | getChatMessageLength,
6 | getPromptLength,
7 | } from "../../utils/tokenizer.js";
8 |
9 | import axios from "axios";
10 | import { get } from "http";
11 | import { randomUUID } from "crypto";
12 |
13 | export default {
14 | data: {
15 | name: "pawan",
16 | fullName: "Pawan.krd models",
17 | parameters: {
18 | messages: {
19 | type: "array",
20 | required: true,
21 | },
22 | model: {
23 | type: "string",
24 | required: false,
25 | default: "zephyr-7b-beta",
26 | options: ["zephyr-7b-beta", "pai-001-light-beta"],
27 | },
28 | max_tokens: {
29 | type: "number",
30 | required: false,
31 | default: 512,
32 | },
33 | temperature: {
34 | type: "number",
35 | required: false,
36 | default: 0.9,
37 | },
38 | id: {
39 | type: "string",
40 | required: false,
41 | default: randomUUID(),
42 | description: "ID of the conversation (used for data saving)",
43 | },
44 | autoSystemMessage: {
45 | type: "boolean",
46 | required: false,
47 | default: true,
48 | description: "Send system messages automatically",
49 | },
50 | },
51 | response: {
52 | result: {
53 | type: "string",
54 | required: true,
55 | },
56 | done: {
57 | type: "boolean",
58 | required: true,
59 | },
60 | cost: {
61 | type: "number",
62 | required: true,
63 | },
64 | finishReason: {
65 | type: "string",
66 | required: true,
67 | },
68 | id: {
69 | type: "string",
70 | required: true,
71 | description: "ID of the conversation (used for data saving)",
72 | },
73 | },
74 | },
75 | execute: async (data) => {
76 | let event = new EventEmitter();
77 | let { messages, model, max_tokens, temperature } = data;
78 |
79 | let result: any = {
80 | result: "",
81 | done: false,
82 | cost: 0,
83 | finishReason: null,
84 | };
85 | if (!model) model = "zephyr-7b-beta";
86 | if (!max_tokens) max_tokens = 512;
87 | if (!temperature) temperature = 0.9;
88 | result.cost += (getChatMessageLength(messages) / 1000) * 0.0001;
89 |
90 | const newMessages = [
91 | {
92 | role: "system",
93 | text: "You are an a helpful assistant called Zephyr, your task is answering user questions. You are being exceuted inside a discord bot and your model have been created by HuggingFace. Be concise with your answers, unless the user ask for more content or the question requires to write a text.",
94 | },
95 | ...messages,
96 | ];
97 | pawan(newMessages, max_tokens, model, result, event, temperature)
98 | .then(async (x) => {
99 | result = x;
100 | result.cost += (getPromptLength(result.result) / 1000) * 0.0001;
101 | event.emit("data", result);
102 | })
103 | .catch((e) => {
104 | console.log(e);
105 | });
106 | return event;
107 | },
108 | };
109 |
110 | async function pawan(messages, max_tokens, model, result, event, temperature?) {
111 | let data: any = {
112 | messages: messages,
113 | stream: true,
114 | max_tokens: max_tokens,
115 | //model: model,
116 | };
117 | if (temperature) {
118 | data["temperature"] = temperature;
119 | }
120 | if (model == "zephyr-7b-beta") {
121 | data["model"] = "pai-001-light-beta";
122 | }
123 | try {
124 | let response = await axios({
125 | method: "post",
126 | url: `https://api.pawan.krd${
127 | model == "pai-001-light-beta" ? "/pai-001-light-beta" : ""
128 | }/v1/chat/completions`,
129 | headers: {
130 | "Content-Type": "application/json",
131 | Authorization: `Bearer ${process.env.PAWAN_API_KEY}`,
132 | // stream response
133 | Accept: "text/event-stream",
134 | },
135 | responseType: "stream",
136 | data: data,
137 | });
138 | let stream = response.data;
139 |
140 | stream.on("data", (d) => {
141 | d = d.toString();
142 | let dataArr = d.split("\n");
143 | dataArr = dataArr.filter((x) => x != "");
144 | for (var data of dataArr) {
145 | data = data.replace("data: ", "").trim();
146 | if (data != "[DONE]") {
147 | data = JSON.parse(data);
148 | result.result += data.choices[0].delta?.content || "";
149 | result.finishReason = data.choices[0].finish_reason;
150 | if (result.finishReason == "stop") {
151 | result.done = true;
152 | }
153 | }
154 | }
155 |
156 | event.emit("data", result);
157 | });
158 |
159 | // when the stream emits end you return the result, wait for the stream to end
160 | await new Promise((resolve) => {
161 | stream.on("end", () => {
162 | resolve(result);
163 | });
164 | });
165 |
166 | return result;
167 | } catch (e: any) {
168 | let errorResponseStr = "";
169 |
170 | for await (const message of e.response.data) {
171 | errorResponseStr += message;
172 | }
173 |
174 | console.log(errorResponseStr);
175 | }
176 | }
177 |
--------------------------------------------------------------------------------
/src/models/video/zelescope.ts:
--------------------------------------------------------------------------------
1 | export default {
2 | data: {
3 | name: "zelescope",
4 | fullName: "Zelescope",
5 | alert: "This model is not yet implemented",
6 | parameters: {
7 | prompt: {
8 | type: "string",
9 | required: true,
10 | },
11 | duration: {
12 | type: "number",
13 | required: false,
14 | default: 10,
15 | },
16 | },
17 | },
18 | execute: async (data) => {},
19 | };
20 |
--------------------------------------------------------------------------------
/src/routes/chart.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { Request, Response } from "express";
3 | import turnstile from "../middlewares/captchas/turnstile.js";
4 | import key from "../middlewares/key.js";
5 | import { getChartImage } from "../utils/chart.js";
6 |
7 | const router = express.Router();
8 | router.post("/:chart", key, turnstile, async (req: Request, res: Response) => {
9 | let { chart } = req.params;
10 | let { filter, period, type = "line" } = req.body;
11 | try {
12 | if (!period) period = "1d";
13 | if (period == "1w") period = "7d";
14 | if (period == "2w") period = "14d";
15 | if (period == "1m") period = "30d";
16 | if (period == "3m") period = "90d";
17 | let result = await getChartImage(chart, filter, period, type);
18 | res.json({ success: true, ...result });
19 | } catch (error) {
20 | console.log(error);
21 | res.json({ error: error, success: false }).status(400);
22 | }
23 | });
24 |
25 | export default router;
26 |
--------------------------------------------------------------------------------
/src/routes/data.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import key from "../middlewares/key.js";
3 | import supabase from "../db/supabase.js";
4 | import { update } from "../utils/db.js";
5 |
6 | const router = express.Router();
7 |
8 | router.get("/user/:id", key, async (req, res) => {
9 | let { id } = req.params;
10 |
11 | let { data: user, error } = await supabase
12 | .from("users_new")
13 | .select("*")
14 | .eq("id", id);
15 | if (error)
16 | return res.json({ error: error.message, success: false }).status(400);
17 | if (!user[0])
18 | return res.json({ error: "user not found", success: false }).status(400);
19 | res.json(user[0]).status(200);
20 | });
21 | router.put("/user/:id", key, async (req, res) => {
22 | let { id } = req.params;
23 | let result = await update("update", {
24 | collection: "users",
25 | id,
26 | ...req.body,
27 | });
28 |
29 | if (result?.error)
30 | return res.json({ error: result.error, success: false }).status(400);
31 | res.json({ success: true }).status(200);
32 | });
33 |
34 | router.post("/user/:id", key, async (req, res) => {
35 | let { id } = req.params;
36 | let { data: user, error } = await supabase
37 |
38 | .from("users_new")
39 | .insert({
40 | id,
41 | ...req.body,
42 | })
43 | .select("*");
44 | if (error)
45 | return res.json({ error: error.message, success: false }).status(400);
46 | res.json(user[0]).status(200);
47 | });
48 | export default router;
49 |
--------------------------------------------------------------------------------
/src/routes/dataset.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import turnstile from "../middlewares/captchas/turnstile.js";
3 | import key from "../middlewares/key.js";
4 | import * as fs from "fs";
5 |
6 | const router = express.Router();
7 |
8 | export default router;
9 |
--------------------------------------------------------------------------------
/src/routes/key.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import supabase from "../db/supabase.js";
3 | import { Request, Response } from "express";
4 | import key from "../middlewares/key.js";
5 | import { generateKey } from "../utils/key.js";
6 | import redisClient from "../db/redis.js";
7 |
8 | const router = express.Router();
9 |
10 | async function secret(req, res, next) {
11 | let { secret } = req.headers;
12 | if (secret == process.env.SUPER_KEY) {
13 | next();
14 | } else {
15 | res.json({ success: false, error: "no permissions" });
16 | }
17 | }
18 | router.post("/", key, secret, async (req: Request, res: Response) => {
19 | let { name, user } = req.body;
20 | let key = await generateKey(user, name);
21 | res.json({ success: true, key });
22 | });
23 |
24 | router.delete("/", key, secret, async (req: Request, res: Response) => {
25 | let { keyId, user } = req.body;
26 | let { data, error: err } = await supabase
27 | .from("api_keys")
28 | .select("*")
29 | .eq("id", keyId)
30 | .eq("userId", user);
31 |
32 | if (err) {
33 | res.json({ success: false, error: err });
34 | return;
35 | }
36 | let { error } = await supabase
37 | .from("api_keys")
38 | .delete()
39 | .eq("id", keyId)
40 | .eq("userId", user);
41 |
42 | if (error) {
43 | res.json({ success: false, error });
44 | return;
45 | }
46 | await redisClient.del(`api:${data[0]["api-token"]}`);
47 | res.json({ success: true });
48 | });
49 |
50 | router.get("/u/:user", key, secret, async (req: Request, res: Response) => {
51 | let { user } = req.params;
52 | let { data, error } = await supabase
53 | .from("api_keys")
54 | .select("*")
55 | .eq("userId", user)
56 | .order("created_at", { ascending: false });
57 |
58 | if (error) {
59 | res.json({ success: false, error });
60 | return;
61 | }
62 | let keys = data.map((d) => {
63 | return {
64 | id: d.id,
65 | name: d.name,
66 | createdAt: d.createdAt,
67 | lastUsed: d.lastUsed,
68 | uses: d.uses,
69 | };
70 | });
71 | res.json({ success: true, keys });
72 | });
73 | router.get(
74 | "/k/:key/:user",
75 | key,
76 | secret,
77 | async (req: Request, res: Response) => {
78 | let { key, user } = req.params;
79 | let { data, error } = await supabase
80 | .from("api_keys")
81 | .select("*")
82 | .eq("id", key)
83 | .eq("userId", user);
84 | if (error) {
85 | res.json({ success: false, error });
86 | return;
87 | }
88 | if (data.length == 0) {
89 | res.json({ success: false, error: "no key found" });
90 | return;
91 | }
92 | let d = data[0];
93 | let keyData = {
94 | id: d.id,
95 | apiToken: d["api-token"],
96 | captchaToken: d["captcha-token"],
97 | name: d.name,
98 | createdAt: d.created_at,
99 | lastUsed: d.lastUsed,
100 | };
101 | res.json({ success: true, key: keyData });
102 | }
103 | );
104 |
105 | export default router;
106 |
--------------------------------------------------------------------------------
/src/routes/models.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { Request, Response } from "express";
3 | import turnstile from "../middlewares/captchas/turnstile.js";
4 | import key from "../middlewares/key.js";
5 | import client from "../index.js";
6 | import log from "../utils/log.js";
7 | import redisClient from "../db/redis.js";
8 | import { update } from "../utils/db.js";
9 | import delay from "delay";
10 | import { dataset } from "../utils/datasets.js";
11 |
12 | const router = express.Router();
13 |
14 | router.post(
15 | "/:type",
16 | key,
17 | turnstile,
18 | async (req: Request, res: Response) => await request(req, res)
19 | );
20 |
21 | router.post(
22 | "/:type/:ai",
23 | key,
24 | turnstile,
25 | async (req: Request, res: Response) => await request(req, res)
26 | );
27 |
28 | async function request(req, res) {
29 | let { type, ai } = req.params;
30 | const body = req.body;
31 | let logq = false;
32 | // random probability of 10% to log if the request is type text
33 | if (type == "text") {
34 | logq = Math.random() < 0.1;
35 | }
36 | if (!ai) {
37 | ai = body.ai;
38 | }
39 | if (ai == "alan") {
40 | ai = "gpt";
41 | body.plugins = ["google"];
42 | }
43 | let typeObj = client[type];
44 | if (body.stream) {
45 | res.set("content-type", "text/event-stream");
46 | }
47 | if (!typeObj) {
48 | res.status(404).json({ success: false, error: "Type not found" });
49 | return;
50 | }
51 | try {
52 | let aiObject = typeObj.find((a) => a.data.name === ai);
53 | if (!aiObject) {
54 | log("info", `AI not found: ${ai}`, typeObj);
55 | res.status(404).json({ success: false, error: "AI not found" });
56 | return;
57 | }
58 |
59 | // check params and body
60 | let realParameters = aiObject.data.parameters; // is an object with keys as parameter names and values as parameter types
61 | let parameters = Object.keys(realParameters);
62 | let requiredParams = parameters.filter(
63 | (p) => realParameters[p].required === true
64 | );
65 | let bodyKeys = Object.keys(body);
66 | // check if all required params are in body
67 | let missingParams = requiredParams.filter((p) => !bodyKeys.includes(p));
68 | if (missingParams.length > 0) {
69 | res.status(400).json({
70 | success: false,
71 | error: `Missing parameters: ${missingParams.join(", ")}`,
72 | });
73 | return;
74 | }
75 |
76 | // not existing params
77 | /*
78 | let notExistingParams = bodyKeys.filter((p) => !parameters.includes(p));
79 | if (notExistingParams.length > 0) {
80 | res.status(400).json({
81 | success: false,
82 | error: `Not existing parameters: ${notExistingParams.join(", ")}`,
83 | });
84 | return;
85 | }*/
86 | let execution = await aiObject.execute(body);
87 | if (body.stream) {
88 | let saved = false;
89 | execution.on("data", async (data) => {
90 | if (data.done || data.status == "done" || data.status == "failed") {
91 | if (data.record && !saved && type == "image") {
92 | saved = true;
93 | let record = data.record;
94 | delete data.record;
95 | let re = await dataset(type, ai, record, data.id);
96 | if (re && re?.id) {
97 | data.id = re.id;
98 | }
99 | }
100 | res.write("data: " + JSON.stringify(data) + "\n\n");
101 | res.end();
102 | if (data.cost) {
103 | applyCost(data.cost, ai, type, req.user);
104 | }
105 | } else {
106 | res.write("data: " + JSON.stringify(data) + "\n\n");
107 | }
108 | });
109 | } else {
110 | if (execution?.cost) {
111 | applyCost(execution.cost, ai, type, req.user);
112 | }
113 | let saved = false;
114 | new Promise((resolve) => {
115 | execution.on("data", async (data) => {
116 | if (data.done || data.status == "done" || data.status == "failed") {
117 | if (data.record && !saved && type == "image") {
118 | saved = true;
119 | let record = data.record;
120 | delete data.record;
121 | let re = await dataset(type, ai, record, data.id);
122 | if (re && re?.id) {
123 | data.id = re.id;
124 | }
125 | }
126 |
127 | resolve(data);
128 | }
129 | });
130 | }).then((d: any) => {
131 | res.json({ success: true, ...d });
132 | });
133 | }
134 | } catch (error: any) {
135 | let resultError = error;
136 | if (error.response && error.response.data) {
137 | resultError = error.response.data;
138 | }
139 | console.log(error.response);
140 | res.status(500).json({ success: false, error: resultError });
141 | }
142 | }
143 |
144 | router.get("/list", (req, res) => {
145 | let types = Object.keys(client);
146 | let result = {};
147 | types.forEach((t) => {
148 | result[t] = client[t].map((a) => a.data);
149 | });
150 | res.json({ success: true, types: result });
151 | });
152 |
153 | router.get("/", (req, res) => {
154 | res.json({
155 | success: true,
156 | message: "Welcome to the API, docs at https://docs.turing.sh",
157 | });
158 | });
159 |
160 | async function applyCost(cost, ai, type, user) {
161 | // add a 20% fee
162 | let totalCost = cost * 1.2;
163 | if (user && user.id != "530102778408861706") {
164 | console.log(`Cost: ${totalCost}$`);
165 |
166 | let updatedUser: any = await redisClient.get(`users:${user.id}`);
167 | updatedUser = JSON.parse(updatedUser);
168 | let plan = updatedUser.plan;
169 | plan.used += totalCost;
170 | plan.expenses.push({
171 | data: {
172 | model: ai,
173 | type,
174 | tokens: {},
175 | },
176 | time: Date.now(),
177 | type: "api",
178 | used: totalCost,
179 | });
180 | await update("update", {
181 | collection: "users",
182 | id: user.id,
183 | plan,
184 | });
185 | await delay(3000);
186 | let up = JSON.parse(await redisClient.get(`users:${user.id}`)).plan;
187 | }
188 | }
189 |
190 | export default router;
191 |
--------------------------------------------------------------------------------
/src/routes/other.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { Request, Response } from "express";
3 | import turnstile from "../middlewares/captchas/turnstile.js";
4 | import key from "../middlewares/key.js";
5 | import ffmpeg from "fluent-ffmpeg";
6 | import * as fs from "fs";
7 | import { generateKey } from "../utils/key.js";
8 | import { pub } from "../db/mq.js";
9 | import { getStats } from "../utils/stats.js";
10 |
11 | const router = express.Router();
12 | async function secret(req, res, next) {
13 | let { secret } = req.headers;
14 | if (secret == process.env.SUPER_KEY) {
15 | next();
16 | } else {
17 | res.json({ success: false, error: "no permissions" });
18 | }
19 | }
20 | async function topgg(req, res, next) {
21 | if (req.headers.authorization == process.env.TOPGG_AUTH) {
22 | next();
23 | } else {
24 | res.status(401).json({ success: false });
25 | }
26 | }
27 |
28 | router.post(
29 | "/mp3-to-mp4",
30 | key,
31 | turnstile,
32 | async (req: Request, res: Response) => {
33 | let { audio, image, duration } = req.body;
34 | try {
35 | // generate a video from an audio and an image
36 | convertToVideo(audio, image, duration, (videoBase64) => {
37 | res.json({ success: true, videoBase64 });
38 | });
39 | } catch (error) {
40 | console.log(error);
41 | res.json({ error: error, success: false }).status(400);
42 | }
43 | }
44 | );
45 |
46 | async function convertToVideo(audio, image, duration, callback) {
47 | // convert audio to video with ffmpeg using image as background
48 | // audio is a base64 string
49 | // image is a base64 string
50 | // duration is the number of seconds of the video
51 | // callback is a function that will be called with the video base64 string
52 | let audioBuffer = Buffer.from(audio, "base64");
53 | let imageBuffer = Buffer.from(image, "base64");
54 | let audioPath = "./audio.mp3";
55 | let imagePath = "./image.jpg";
56 | let videoPath = "./video.mp4";
57 | fs.writeFileSync(audioPath, audioBuffer);
58 | fs.writeFileSync(imagePath, imageBuffer);
59 | ffmpeg()
60 | .input(audioPath)
61 | .input(imagePath)
62 | .outputOptions([
63 | "-c:v libx264",
64 | "-c:a aac",
65 | "-shortest",
66 | "-vf scale=1280:720",
67 | ])
68 | // be sure the image is visible
69 | .inputOptions(["-loop 1", "-t " + duration])
70 | // duration of the video is the same as the audio
71 | .duration(duration)
72 | .output(videoPath)
73 | .on("end", function () {
74 | let videoBuffer = fs.readFileSync(videoPath);
75 | let videoBase64 = videoBuffer.toString("base64");
76 | callback(videoBase64);
77 | })
78 | .run();
79 | }
80 |
81 | router.post(
82 | "/bot",
83 | secret,
84 | key,
85 | turnstile,
86 | async (req: Request, res: Response) => {
87 | let guilds = await getStats();
88 | res.json({ success: true, guilds });
89 | }
90 | );
91 |
92 | router.post("/top-vote", topgg, async (req: Request, res: Response) => {
93 | let body = req.body;
94 | let botId = "1053015370115588147";
95 | if (body.bot == botId && body.type == "upvote") {
96 | let userId = body.user;
97 | console.log(`User ${userId} just voted!`);
98 | await pub.send(
99 | {
100 | exchange: "db",
101 | routingKey: "db",
102 | },
103 | JSON.stringify({
104 | id: "vote",
105 | data: userId,
106 | })
107 | );
108 | }
109 |
110 | res.status(200).json({ success: true });
111 | });
112 |
113 | export default router;
114 |
--------------------------------------------------------------------------------
/src/routes/runpod.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import { Request, Response } from "express";
3 | import { generateKey } from "../utils/key.js";
4 | import turnstile from "../middlewares/captchas/turnstile.js";
5 | import key from "../middlewares/key.js";
6 | import { translateModels, request } from "../utils/runpod.js";
7 |
8 | const router = express.Router();
9 |
10 | router.post("/runsync", key, turnstile, async (req: Request, res: Response) => {
11 | let { model } = req.body;
12 | try {
13 | let url = await translateModels(model);
14 | let body = req.body;
15 | delete body.model;
16 | let result = await request(url, "runsync", body);
17 | res.json(result);
18 | } catch (error) {
19 | res.json({ error: error, success: false }).status(400);
20 | }
21 | });
22 |
23 | router.post("/run", key, turnstile, async (req: Request, res: Response) => {
24 | let { model } = req.body;
25 | try {
26 | let url = await translateModels(model);
27 | let body = req.body;
28 | delete body.model;
29 | let result = await request(url, "run", body);
30 | res.json(result);
31 | } catch (error) {
32 | res.json({ error: error, success: false }).status(400);
33 | }
34 | });
35 |
36 | router.post(
37 | "/status/:id",
38 | key,
39 | turnstile,
40 | async (req: Request, res: Response) => {
41 | let { model } = req.body;
42 | let { id } = req.params;
43 | try {
44 | let url = await translateModels(model);
45 | let body = req.body;
46 | delete body.model;
47 | let result = await request(url, `status/${id}`, body);
48 | res.json(result);
49 | } catch (error) {
50 | res.json({ error: error, success: false }).status(400);
51 | }
52 | }
53 | );
54 |
55 | router.post("/cancel", key, turnstile, async (req: Request, res: Response) => {
56 | let { model } = req.body;
57 | try {
58 | let url = await translateModels(model);
59 | let body = req.body;
60 | delete body.model;
61 | let result = await request(url, "cancel", body);
62 | res.json(result);
63 | } catch (error) {
64 | res.json({ error: error, success: false }).status(400);
65 | }
66 | });
67 |
68 | export default router;
69 |
--------------------------------------------------------------------------------
/src/routes/storage.routes.ts:
--------------------------------------------------------------------------------
1 | import express from "express";
2 | import turnstile from "../middlewares/captchas/turnstile.js";
3 | import key from "../middlewares/key.js";
4 | import * as fs from "fs";
5 |
6 | const storagePath = "./storage";
7 |
8 | const router = express.Router();
9 |
10 | router.post("/upload", key, turnstile, async (req, res) => {
11 | let { base64, name, bucket } = req.body;
12 | let buffer = Buffer.from(base64, "base64");
13 | let path = `${storagePath}/${bucket}/${name}`;
14 | fs.writeFileSync(path, buffer);
15 | res.json({ success: true });
16 | });
17 |
18 | router.get("/:bucket/:name", async (req, res) => {
19 | let { bucket, name } = req.params;
20 | let path = `${storagePath}/${bucket}/${name}`;
21 | let file = fs.readFileSync(path);
22 | res.send(file);
23 | });
24 | export default router;
25 |
--------------------------------------------------------------------------------
/src/rundocs.ts:
--------------------------------------------------------------------------------
1 | import { autogenerateDocs } from "./utils/docs.js";
2 | import textHandler from "./handlers/text.js";
3 | import imageHandler from "./handlers/image.js";
4 | import audioHandler from "./handlers/audio.js";
5 | import log from "./utils/log.js";
6 | import videoHandler from "./handlers/video.js";
7 | const client = {
8 | text: [],
9 | image: [],
10 | audio: [],
11 | video: [],
12 | };
13 | import "dotenv/config";
14 |
15 | (async () => {
16 | await textHandler(client);
17 | await imageHandler(client);
18 | await audioHandler(client);
19 | await videoHandler(client);
20 | await autogenerateDocs(client);
21 | })();
22 |
--------------------------------------------------------------------------------
/src/utils/chart.ts:
--------------------------------------------------------------------------------
1 | import ChartJsImage from "chartjs-to-image";
2 | import supabase from "../db/supabase.js";
3 | import ms from "ms";
4 | import fs from "fs";
5 |
6 | const availableCharts = [
7 | "chat",
8 | "guilds",
9 | "cooldown",
10 | "commands",
11 | "image",
12 | "vote",
13 | "campaigns",
14 | "midjourney",
15 | "datasets",
16 | ];
17 | const availableTypes = ["line", "bar"];
18 |
19 | export async function getChartImage(chart, filter, period: any, type) {
20 | if (!availableCharts.includes(chart)) throw new Error("Invalid chart");
21 | if (!availableTypes.includes(type)) throw new Error("Invalid type of chart");
22 | let chartImage = new ChartJsImage();
23 | let periodMs: any = ms(period);
24 |
25 | let timeStart: any = Date.now() - periodMs;
26 | timeStart = new Date(timeStart);
27 | timeStart = timeStart.toISOString();
28 | console.log(timeStart);
29 | let { data, error } = await supabase
30 | .from("metrics")
31 | .select("*")
32 | .eq("type", chart)
33 | // filter data by period at ssupabase using bigger or equal operator than the period start
34 | .gte("time", timeStart);
35 | console.log(error);
36 | data = data.filter((d: any) => {
37 | let date = new Date(d.time);
38 | let now = new Date();
39 | let diff = now.getTime() - date.getTime();
40 | return diff <= periodMs;
41 | });
42 | //sort by data, old first , recent last
43 | data = data.sort((a: any, b: any) => {
44 | let dateA = new Date(a.time);
45 | let dateB = new Date(b.time);
46 | return dateA.getTime() - dateB.getTime();
47 | });
48 |
49 | // if period ms > 2d, then we need to group data by day so all the data from the same day is grouped together as 1 data point
50 | if (periodMs > ms("2d")) {
51 | let newData = [];
52 | let lastDay = null;
53 | let lastData = null;
54 |
55 | for (let i = 0; i < data.length; i++) {
56 | let date = new Date(data[i].time);
57 | let day = date.getDate();
58 | if (lastDay == null) {
59 | lastDay = day;
60 | lastData = data[i];
61 | } else {
62 | if (day == lastDay) {
63 | // same day, add data
64 | let keys = Object.keys(data[i].data);
65 | for (let j = 0; j < keys.length; j++) {
66 | lastData.data[keys[j]] += data[i].data[keys[j]];
67 | }
68 | } else {
69 | // new day, push last data and set new last data
70 | newData.push(lastData);
71 | lastData = data[i];
72 | lastDay = day;
73 | }
74 | }
75 | }
76 | data = newData;
77 | }
78 |
79 | let metricData = data.map((d: any) => d.data);
80 | if (metricData.length === 0) throw new Error("No data found");
81 |
82 | let keys = [];
83 | let types = [];
84 | let keyData = data.sort((a: any, b: any) => {
85 | let dateA = new Date(a.time);
86 | let dateB = new Date(b.time);
87 | // sort by date recent first
88 | return dateB.getTime() - dateA.getTime();
89 | });
90 | for (let data3 of keyData) {
91 | let nke = Object.keys(data3);
92 | // filter keys
93 | nke = nke.filter((key) => {
94 | // are not in keys
95 | return !keys.includes(key);
96 | });
97 | keys.push(...nke);
98 | for (let key of nke) {
99 | let type = {
100 | key: key,
101 | type: typeof data3[key],
102 | content: data3[key],
103 | };
104 | types.push(type);
105 | }
106 | }
107 | console.log(keys);
108 |
109 | let newKeys = [];
110 | let keysToRemove = [];
111 | for (let i = 0; i < keys.length; i++) {
112 | let type = types.find((x) => x.key == keys[i]);
113 | if (type.type == "object") {
114 | // get all the keys of the object
115 | let subKeys = Object.keys(type.content);
116 | for (let j = 0; j < subKeys.length; j++) {
117 | // check subkeys for objects
118 | if (typeof type.content[subKeys[j]] == "object") {
119 | let subSubKeys = Object.keys(type.content[subKeys[j]]);
120 | // change subkeys to be parentKey-subKey-subSubKey
121 | subSubKeys = subSubKeys.map(
122 | (subSubKey) => `${keys[i]}.${subKeys[j]}.${subSubKey}`
123 | );
124 | // remove the parent key
125 | keysToRemove.push(`${keys[i]}.${subKeys[j]}`);
126 | // add the subkeys
127 | newKeys.push(...subSubKeys);
128 | }
129 | }
130 | // change subkeys to be parentKey-subKey
131 | subKeys = subKeys.map((subKey) => `${keys[i]}.${subKey}`);
132 | // remove the parent key
133 | keysToRemove.push(keys[i]);
134 | // add the subkeys
135 | newKeys.push(...subKeys);
136 | }
137 | }
138 | keys = keys.filter((key) => !keysToRemove.includes(key));
139 | keys.push(...newKeys);
140 |
141 | if (filter) {
142 | // filter is a object with include and exclude arrays
143 | if (filter.include) {
144 | keys = keys.filter((key) => filter.include.includes(key));
145 | }
146 | if (filter.exclude) {
147 | keys = keys.filter((key) => !filter.exclude.includes(key));
148 | // filter parent keys
149 | keys = keys.filter((key) => {
150 | if (key.includes(".")) {
151 | let parentKey = key.split(".")[0];
152 | return !filter.exclude.includes(parentKey);
153 | }
154 | return true;
155 | });
156 | // filter subkeys
157 | keys = keys.filter((key) => {
158 | if (key.includes(".")) {
159 | let parentKey = key.split(".")[0];
160 | let subKey = key.split(".")[1];
161 | return !filter.exclude.includes(`${parentKey}.${subKey}`);
162 | }
163 | return true;
164 | });
165 | }
166 | }
167 |
168 | let labels = [];
169 | let datasets = [];
170 |
171 | if (type != "pie" && type != "doughnut") {
172 | labels = data.map((d: any) => {
173 | let date = new Date(d.time);
174 | // format into dd/mm/yyyy hh:mm
175 | let day = date.getDate();
176 | let month = date.getMonth() + 1;
177 | let year = date.getFullYear();
178 | let hours = date.getHours();
179 | let minutes = date.getMinutes();
180 | return `${day}/${month}/${year} ${hours}:${minutes}`;
181 | });
182 |
183 | keys.forEach((key) => {
184 | let dataset;
185 | dataset = {
186 | label: key,
187 | data: [],
188 | fill: false,
189 | };
190 | if (key.includes(".")) {
191 | let parentKey = key.split(".")[0];
192 | let subKey = key.split(".")[1];
193 | // check for subSubKey
194 | if (key.split(".").length == 3) {
195 | let subSubKey = key.split(".")[2];
196 | data.forEach((d: any) => {
197 | if (d.data[parentKey][subKey][subSubKey])
198 | dataset.data.push(d.data[parentKey][subKey][subSubKey]);
199 | });
200 | } else {
201 | data.forEach((d: any) => {
202 | if (d.data[parentKey][subKey])
203 | dataset.data.push(d.data[parentKey][subKey]);
204 | });
205 | }
206 | } else {
207 | data.forEach((d: any) => {
208 | if (d.data[key]) dataset.data.push(d.data[key]);
209 | });
210 | }
211 |
212 | datasets.push(dataset);
213 | });
214 | } else {
215 | labels = keys;
216 | // do pie chart
217 | datasets = [
218 | {
219 | label: "Data",
220 | data: [],
221 | backgroundColor: [],
222 | },
223 | ];
224 | let dataset = datasets[0];
225 | keys.forEach((key) => {
226 | if (key.includes(".")) {
227 | let parentKey = key.split(".")[0];
228 | let subKey = key.split(".")[1];
229 | // check for subSubKey
230 | if (key.split(".").length == 3) {
231 | let subSubKey = key.split(".")[2];
232 | data.forEach((d: any) => {
233 | if (d.data[parentKey][subKey][subSubKey])
234 | dataset.data.push(d.data[parentKey][subKey][subSubKey]);
235 | });
236 | } else {
237 | data.forEach((d: any) => {
238 | if (d.data[parentKey][subKey])
239 | dataset.data.push(d.data[parentKey][subKey]);
240 | });
241 | }
242 | } else {
243 | data.forEach((d: any) => {
244 | if (d.data[key]) dataset.data.push(d.data[key]);
245 | });
246 | }
247 | dataset.backgroundColor.push(
248 | `hsl(${Math.floor(Math.random() * 360)}, 100%, 50%)`
249 | );
250 | });
251 | }
252 |
253 | // if there more than 10 labels make the chart bigger
254 | let width = 1000;
255 | if (labels.length > 10) {
256 | let height = labels.length * 20;
257 | chartImage.setHeight(height);
258 | }
259 | chartImage.setConfig({
260 | type: type,
261 | data: {
262 | labels: labels,
263 | datasets: datasets,
264 | },
265 | });
266 | chartImage.setWidth(width);
267 | let base64 = await chartImage.toDataUrl();
268 | // save file in disk
269 | let buffer = Buffer.from(base64.split(",")[1], "base64");
270 | fs.writeFileSync(`./chart.png`, buffer);
271 |
272 | return { image: base64 };
273 | }
274 |
275 | async function extractData(period, chart) {
276 | let { data, error } = await supabase
277 | .from("metrics")
278 | .select("*")
279 | .eq("type", chart);
280 | if (error) throw new Error(error.message);
281 | data = data.filter((d: any) => {
282 | let date = new Date(d.time);
283 | let now = new Date();
284 | let diff = now.getTime() - date.getTime();
285 | let periodMs: any = ms(period);
286 | return diff <= periodMs;
287 | });
288 | //sort by data, old first , recent last
289 | data = data.sort((a: any, b: any) => {
290 | let dateA = new Date(a.time);
291 | let dateB = new Date(b.time);
292 | return dateA.getTime() - dateB.getTime();
293 | });
294 | return data;
295 | }
296 |
--------------------------------------------------------------------------------
/src/utils/ciclic.ts:
--------------------------------------------------------------------------------
1 | import { pushKeysToCache } from "./key.js";
2 | import { getUpdatedStats } from "./stats.js";
3 | import ms from "ms";
4 |
5 | export default async function ciclic() {
6 | let guilds = await getUpdatedStats();
7 | await pushKeysToCache();
8 | setInterval(async () => {
9 | guilds = await getUpdatedStats();
10 | }, ms("1h"));
11 | }
12 |
--------------------------------------------------------------------------------
/src/utils/datasets.ts:
--------------------------------------------------------------------------------
1 | import supabase from "../db/supabase.js";
2 | import { randomUUID } from "crypto";
3 |
4 | export async function dataset(
5 | type: string,
6 | ai: string,
7 | record: any,
8 | id?: string
9 | ) {
10 | if (type == "image" || ai != "vision") {
11 | // means record is an array of images
12 | record.forEach(async (r: any) => {
13 | await datasetSave(type, ai, r, r.id);
14 | });
15 | return;
16 | } else {
17 | console.log("saving dataset", id);
18 | return await datasetSave(type, ai, record, id);
19 | }
20 | }
21 |
22 | export async function datasetSave(
23 | type: string,
24 | ai: string,
25 | record: any,
26 | id?: string
27 | ) {
28 | let datasetName = `turing-${ai}-${type}`;
29 | if (!id) id = randomUUID();
30 | if (record.base64) {
31 | let buffer = Buffer.from(record.base64, "base64");
32 | // upload to supabase storage
33 | let { error } = await supabase.storage
34 | .from("datasets_new")
35 | .upload(`${datasetName}/${id}.png`, buffer, {
36 | cacheControl: "3600",
37 | upsert: false,
38 | });
39 |
40 | if (error) {
41 | console.log(error);
42 | throw error;
43 | }
44 | let { data } = await supabase.storage
45 | .from("datasets_new")
46 | .getPublicUrl(`${datasetName}/${id}.png`);
47 |
48 | record.url = data.publicUrl;
49 | delete record.base64;
50 | }
51 |
52 | // first check if the data with id exists
53 | let { data, error } = await supabase
54 | .from("datasets_new")
55 | .select("*")
56 | .eq("dataset", datasetName)
57 | .eq("id", id);
58 |
59 | if (error) {
60 | console.log(error);
61 | throw error;
62 | }
63 | if (data && data.length > 0) {
64 | // update
65 |
66 | // check if last update was more than 72 hours ago
67 | if (data[0].last_update < Date.now() - 72 * 60 * 60 * 1000) {
68 | id = randomUUID();
69 | let { error } = await supabase.from("datasets_new").insert([
70 | {
71 | id: id,
72 | record: record,
73 | dataset: datasetName,
74 | model: ai,
75 | rates: {
76 | "1": 0,
77 | },
78 | type: type,
79 | last_update: Date.now(),
80 | },
81 | ]);
82 | if (error) {
83 | console.log(error);
84 | throw error;
85 | }
86 | } else {
87 | let { data: d, error } = await supabase
88 | .from("datasets_new")
89 | .update({
90 | record: [...(data[0].record || []), record],
91 | last_update: Date.now(),
92 | })
93 | .eq("dataset", datasetName)
94 | .eq("id", id);
95 | if (error) {
96 | console.log(error);
97 | throw error;
98 | }
99 | }
100 | } else {
101 | let { error } = await supabase.from("datasets_new").insert([
102 | {
103 | id: id,
104 | record: record,
105 | dataset: datasetName,
106 | model: ai,
107 | rates: {
108 | "1": 0,
109 | },
110 | type: type,
111 | last_update: Date.now(),
112 | },
113 | ]);
114 |
115 | if (error) {
116 | console.log(error);
117 | throw error;
118 | }
119 | }
120 | return {
121 | id,
122 | };
123 | }
124 |
--------------------------------------------------------------------------------
/src/utils/db.ts:
--------------------------------------------------------------------------------
1 | import { pub } from "../db/mq.js";
2 |
3 | export async function update(action: "update" | "vote", data: any) {
4 | let d = {};
5 |
6 | let collection;
7 | let id;
8 | if (action === "update") {
9 | collection = data.collection;
10 | id = data.id;
11 | delete data.collection;
12 | delete data.id;
13 | d = {
14 | collection,
15 | id,
16 | data: data,
17 | };
18 | } else {
19 | d = {
20 | userId: data.userId,
21 | };
22 | }
23 | try {
24 | await pub.send(
25 | {
26 | exchange: "db",
27 | routingKey: "db",
28 | },
29 | JSON.stringify({
30 | type: action,
31 | ...d,
32 | })
33 | );
34 | } catch (e) {
35 | console.log(e);
36 | return { error: e };
37 | }
38 | }
39 |
--------------------------------------------------------------------------------
/src/utils/docs.ts:
--------------------------------------------------------------------------------
1 | import fs from "node:fs";
2 | import path from "node:path";
3 | import { fileURLToPath } from "url";
4 | import log from "./log.js";
5 | const __filename = fileURLToPath(import.meta.url);
6 | const __dirname = path.dirname(__filename);
7 |
8 | const docsPagesPath = path.join(__dirname, "../../docs/");
9 | const docsPath = path.join(__dirname, "../../docs.json");
10 |
11 | export async function autogenerateDocs(client) {
12 | let docsConfig = JSON.parse(fs.readFileSync(docsPath, "utf8"));
13 | let sections = [];
14 | let newConfig = {};
15 | sections = Object.keys(client).filter((section) => {
16 | return client[section].length > 0;
17 | });
18 | let sidebar = [];
19 | sidebar = sections.map((section) => {
20 | return [
21 | `${section.charAt(0).toUpperCase() + section.slice(1)} Models`,
22 | [
23 | ...client[section].map((model) => {
24 | return [model.data.fullName, `/${section}/${model.data.name}`];
25 | }),
26 | ],
27 | ];
28 | });
29 | delete docsConfig.sidebar;
30 | newConfig = {
31 | ...docsConfig,
32 | sidebar,
33 | };
34 | fs.writeFileSync(docsPath, JSON.stringify(newConfig, null, 2));
35 | log("info", `Sidebar docs generated.`);
36 | for (let section of sections) {
37 | let folderExists = fs.existsSync(path.join(docsPagesPath, section));
38 | if (!folderExists) {
39 | fs.mkdirSync(path.join(docsPagesPath, section));
40 | }
41 | for (let model of client[section]) {
42 | let docsModelPath = path.join(
43 | docsPagesPath,
44 | section,
45 | `${model.data.name}/index.mdx`
46 | );
47 | let docsModelContent = `---\ntitle: ${model.data.fullName}\n---\n\n# ${
48 | model.data.fullName
49 | }\nPOST *https://api.turing.sh/${section}/${model.data.name}*\n${
50 | model.data.alert ? `${model.data.alert}\n\n` : ""
51 | }`;
52 | // pricing
53 | if (model.data.pricing) {
54 | docsModelContent += `\n## Pricing\n\n`;
55 | // average price
56 | if (model.data.pricing.average) {
57 | docsModelContent += `\n- **Average:** ${model.data.pricing.average}\n`;
58 | }
59 | // price
60 | if (model.data.pricing.price) {
61 | docsModelContent += `\n- **Price:** ${model.data.pricing.price}\n`;
62 | }
63 | }
64 |
65 | docsModelContent += `\n## Parameters\n\n`;
66 | for (let parameter of Object.keys(model.data.parameters)) {
67 | docsModelContent += `\n- **${parameter}**\n - Type: ${model.data.parameters[parameter].type}\n - Required: ${model.data.parameters[parameter].required}\n`;
68 |
69 | if (model.data.parameters[parameter].description) {
70 | docsModelContent += ` - Description: ${model.data.parameters[parameter].description}\n`;
71 | }
72 | if (model.data.parameters[parameter].options) {
73 | docsModelContent += ` - Options: ${model.data.parameters[
74 | parameter
75 | ].options.join(", ")}\n`;
76 | }
77 | if (model.data.parameters[parameter].default) {
78 | docsModelContent += ` - Default: ${model.data.parameters[parameter].default}\n`;
79 | }
80 | }
81 | // response
82 | docsModelContent += `\n## Response\n\n`;
83 | if (model.data.response) {
84 | for (let response of Object.keys(model.data.response)) {
85 | docsModelContent += `\n- **${response}**\n - Type: ${model.data.response[response].type}\n`;
86 | if (model.data.response[response].description) {
87 | docsModelContent += ` - Description: ${model.data.response[response].description}\n`;
88 | }
89 | }
90 | } else {
91 | // alert not defined yet
92 | docsModelContent += `Response not defined yet\n\n`;
93 | }
94 |
95 | docsModelContent += `\n## Examples\n\n`;
96 | docsModelContent += generateExamples(model, section);
97 | if (!fs.existsSync(path.join(docsPagesPath, section, model.data.name))) {
98 | fs.mkdirSync(path.join(docsPagesPath, section, model.data.name));
99 | }
100 | fs.writeFileSync(docsModelPath, docsModelContent);
101 | }
102 | }
103 | log("info", `Docs generated.`);
104 | }
105 |
106 | function generateExamples(model, section) {
107 | let data = {};
108 | for (let parameter of Object.keys(model.data.parameters)) {
109 | if (model.data.parameters[parameter].default) {
110 | data[parameter] = model.data.parameters[parameter].default;
111 | } else if (model.data.parameters[parameter].options) {
112 | data[parameter] = model.data.parameters[parameter].options[0];
113 | } else if (model.data.parameters[parameter].required == true) {
114 | data[parameter] = model.data.parameters[parameter].type;
115 | }
116 | }
117 |
118 | let example = `
119 | \`\`\`typescript
120 | import axios from "axios";
121 | (async () => {
122 | let response = await axios({
123 | method: "post",
124 | url: 'https://api.turing.sh/${section}/${model.data.name}',
125 | headers: {
126 | "Content-Type": "application/json",
127 | Authorization: "Bearer YOUR_API_KEY",
128 | "x-captcha-token": "Captcha key"
129 | },
130 | data: ${JSON.stringify(data, null, 2)},
131 | })
132 | })();
133 | \`\`\`
134 | \`\`\`python
135 | import requests
136 | import json
137 | response = requests.post(
138 | "https://api.turing.sh/${section}/${model.data.name}",
139 | headers={
140 | "Content-Type": "application/json",
141 | "Authorization": "Bearer YOUR_API_KEY",
142 | "x-captcha-token": "Captcha key"
143 | },
144 | data=json.dumps(${JSON.stringify(data, null, 2)}),
145 | )
146 | \`\`\`
147 | `;
148 | return example;
149 | }
150 |
--------------------------------------------------------------------------------
/src/utils/key.ts:
--------------------------------------------------------------------------------
1 | import jwt from "jsonwebtoken";
2 | import supabase from "../db/supabase.js";
3 | import { v4 as uuidv4 } from "uuid";
4 | import redisClient from "../db/redis.js";
5 |
6 | export async function pushKeysToCache() {
7 | let { data, error } = await supabase.from("api_keys").select("*");
8 |
9 |
10 | if (data) {
11 | data.map((d) => {
12 | redisClient.set(`api:${d["api-token"]}`, JSON.stringify(d));
13 | });
14 | }
15 | }
16 |
17 | export async function generateKey(
18 | userId: string,
19 | name: string,
20 | allowedPaths?: Array,
21 | ips?: Array
22 | ) {
23 | let id = uuidv4();
24 | let apiToken = jwt.sign({ ips, id }, process.env.SECRET_KEY);
25 | let captchaToken = jwt.sign({ ips, id, apiToken }, process.env.SECRET_KEY);
26 | let d = {
27 | id,
28 | "api-token": apiToken,
29 | "captcha-token": captchaToken,
30 | ips,
31 | created_at: new Date(),
32 | allowedPaths: allowedPaths || [
33 | "/text/*",
34 | "/image/*",
35 | "/video/*",
36 | "/audio/*",
37 | ],
38 | lastUsed: Date.now(),
39 | name,
40 | userId: userId,
41 | };
42 | let userExists = await redisClient.get(`users:${userId}`);
43 | if (!userExists) {
44 | let { data, error } = await supabase
45 | .from("users_new")
46 | .select("*")
47 | .eq("id", userId);
48 |
49 | if (error) {
50 | console.log(error);
51 | return false;
52 | }
53 | if (data.length == 0) {
54 | return false;
55 | }
56 | redisClient.set(`users:${userId}`, JSON.stringify(data[0]));
57 | }
58 | let { data, error } = await supabase.from("api_keys").insert([
59 | {
60 | ...d,
61 | },
62 | ]);
63 | redisClient.set(`api:${apiToken}`, JSON.stringify(d));
64 |
65 |
66 | if (error) {
67 | console.log(error);
68 | return false;
69 | }
70 | return { apiToken, captchaToken, id, name };
71 | }
72 |
73 | export async function checkCaptchaToken(token: string, req) {
74 | try {
75 | let decoded = jwt.verify(token, process.env.SECRET_KEY);
76 | let ApiToken = req.headers.authorization;
77 | ApiToken = ApiToken.replace("Bearer ", "");
78 | if (!decoded) {
79 | return false;
80 | }
81 | if (decoded["apiToken"]) {
82 | if (decoded["apiToken"] != ApiToken) {
83 | return false;
84 | }
85 | let decodedApiToken = jwt.verify(
86 | decoded["apiToken"],
87 | process.env.SECRET_KEY
88 | );
89 | if (!decodedApiToken) {
90 | return false;
91 | }
92 | if (decodedApiToken["id"] != decoded["id"]) {
93 | return false;
94 | }
95 | // check ip
96 | if (decodedApiToken["ips"]) {
97 | if (
98 | !decodedApiToken["ips"].includes(req.ip) &&
99 | req.ip != "::1" &&
100 | decodedApiToken["ips"].length > 0
101 | ) {
102 | return false;
103 | }
104 | }
105 |
106 | var data = req.apiData;
107 | if (data) {
108 | var user;
109 | if (data.userId != "530102778408861706") {
110 | user = await redisClient.get(`users:${data.userId}`);
111 | user = JSON.parse(user);
112 | if (!user) {
113 | let { data: d, error } = await supabase
114 | .from("users_new")
115 | .select("*")
116 | .eq("id", data.userId);
117 |
118 | if (error) {
119 | console.log(error);
120 | return false;
121 | }
122 | if (d.length == 0) {
123 | return false;
124 | }
125 | redisClient.set(`users:${data.userId}`, JSON.stringify(d[0]));
126 | user = d[0];
127 | }
128 | if (user?.plan?.total) {
129 | let current = user.plan.total - user.plan.used;
130 | if (current <= 0.1) {
131 | console.log("Plan limit reached");
132 | return {
133 | error: "Plan limit reached",
134 | };
135 | }
136 | } else {
137 | return {
138 | error: "Plan limit reached",
139 | };
140 | }
141 | } else {
142 | user = {
143 | id: "530102778408861706",
144 | };
145 | }
146 |
147 | return {
148 | user: user,
149 | apiId: data.id,
150 | };
151 | }
152 | return true;
153 | }
154 | } catch (e) {
155 | return false;
156 | }
157 | }
158 |
--------------------------------------------------------------------------------
/src/utils/log.ts:
--------------------------------------------------------------------------------
1 | import chalk from "chalk";
2 | import fs from "node:fs";
3 | import { randomUUID } from "node:crypto";
4 |
5 | const logsPath = "./logs";
6 | const sessionID = randomUUID();
7 | const logFile = `${logsPath}/${sessionID}.log`;
8 |
9 | export default function log(
10 | type: "info" | "warning" | "error" | "debug",
11 | ...args
12 | ) {
13 | const log = `[${type.toUpperCase()}] ${args.join(" ")}`;
14 | const color =
15 | type === "info"
16 | ? "green"
17 | : type === "warning"
18 | ? "yellow"
19 | : type === "error"
20 | ? "red"
21 | : "white";
22 | if (
23 | (process.env.NODE_ENV == "production" && type != "debug") ||
24 | process.env.NODE_ENV == "development"
25 | ) {
26 | console.log(chalk[color](log));
27 | }
28 | fs.appendFileSync(logFile, `${log}\n`);
29 | }
30 |
--------------------------------------------------------------------------------
/src/utils/ms.ts:
--------------------------------------------------------------------------------
1 | export function getToday() {
2 | let today = new Date();
3 | let dd = String(today.getDate()).padStart(2, "0");
4 | let mm = String(today.getMonth() + 1).padStart(2, "0");
5 | let yyyy = today.getFullYear();
6 | return `${yyyy}-${mm}-${dd}`;
7 | }
8 |
--------------------------------------------------------------------------------
/src/utils/runpod.ts:
--------------------------------------------------------------------------------
1 | import axios from "axios";
2 | export async function translateModels(model) {
3 | let models = {
4 | blip2: "v2/22whrikqknoc11",
5 | musicgen: "v2/zeeocl74aergso",
6 | llama2: "v2/39i5i1rtqkm7vk",
7 | };
8 | if (!models[model]) {
9 | throw new Error("Model not found");
10 | }
11 |
12 | return models[model];
13 | }
14 |
15 | export async function request(url, action, body) {
16 | let URL = `https://api.runpod.ai/${url}/${action}`;
17 | try {
18 | let res = await axios({
19 | method: "POST",
20 | url: URL,
21 | headers: {
22 | "Content-Type": "application/json",
23 | Authorization: `Bearer ${process.env.RUNPOD_KEY}`,
24 | },
25 | data: {
26 | input: {
27 | ...body.input,
28 | },
29 | },
30 | });
31 | let result = res.data;
32 | return result;
33 | } catch (error: any) {
34 | console.log(error.response.data);
35 | throw error;
36 | }
37 | }
38 |
--------------------------------------------------------------------------------
/src/utils/stats.ts:
--------------------------------------------------------------------------------
1 | import fs from "fs";
2 | import axios from "axios";
3 | import puppeteer from "puppeteer";
4 | import delay from "delay";
5 |
6 | export async function getUpdatedStats() {
7 | try {
8 |
9 | let res = await fetch(
10 | "https://discord.com/api/v9/applications/1053015370115588147",
11 | {
12 | headers: {
13 | accept: "*/*",
14 | "accept-language": "es-ES,es;q=0.9,en;q=0.8",
15 | authorization: process.env.STATS_AUTH,
16 | "sec-ch-ua":
17 | '"Chromium";v="116", "Not)A;Brand";v="24", "Brave";v="116"',
18 | "sec-ch-ua-mobile": "?0",
19 | "sec-ch-ua-platform": '"Windows"',
20 | "sec-fetch-dest": "empty",
21 | "sec-fetch-mode": "cors",
22 | "sec-fetch-site": "same-origin",
23 | "sec-gpc": "1",
24 | },
25 | referrer:
26 | "https://discord.com/developers/applications/1053015370115588147/information",
27 | referrerPolicy: "strict-origin-when-cross-origin",
28 | body: null,
29 | method: "GET",
30 | mode: "cors",
31 | credentials: "include",
32 | }
33 | );
34 | let answer = await res.json();
35 | let guildsNumber = answer.approximate_guild_count;
36 | await pushStats(guildsNumber);
37 | return guildsNumber;
38 | } catch (error) {
39 | return 296000
40 | }
41 | }
42 |
43 | export async function getStats() {
44 | if (fs.existsSync("./guilds.txt")) {
45 | let guilds = fs.readFileSync("./guilds.txt", "utf-8");
46 | return parseInt(guilds);
47 | } else {
48 | let g = await getUpdatedStats();
49 | return g;
50 | }
51 | }
52 |
53 | async function pushStats(guilds: number) {
54 | // first update at the stats file
55 | fs.writeFileSync("./guilds.txt", guilds.toString());
56 | let shards = Math.round(guilds / 1000);
57 | // round shards to the nearest integer
58 | try {
59 | await axios({
60 | method: "post",
61 | url: "https://top.gg/api/bots/1053015370115588147/stats",
62 | headers: {
63 | Authorization: process.env.TOPGG_TOKEN,
64 | "Content-Type": "application/json",
65 | },
66 | data: {
67 | server_count: guilds,
68 | shard_count: shards,
69 | },
70 | });
71 | } catch (error) { }
72 | try {
73 | await axios({
74 | method: "post",
75 | url: "https://discord.bots.gg/api/v1/bots/1053015370115588147/stats",
76 | headers: {
77 | Authorization: process.env.DISCORD_BOTS_GG,
78 | "Content-Type": "application/json",
79 | },
80 | data: {
81 | guildCount: guilds,
82 | shardCount: shards,
83 | },
84 | });
85 | } catch (error) { }
86 | }
87 |
--------------------------------------------------------------------------------
/src/utils/tokenizer.ts:
--------------------------------------------------------------------------------
1 | import { get_encoding } from "@dqbd/tiktoken";
2 | export const encoder = get_encoding("cl100k_base");
3 |
4 | /**
5 | * Get the length of a prompt.
6 | * @param content Prompt to check
7 | *
8 | * @returns Length of the prompt, in tokens
9 | */
10 | export const getPromptLength = (content: string): number => {
11 | if (!content) return 0;
12 | content = content
13 | .replaceAll("<|endoftext|>", "<|im_end|>")
14 | .replaceAll("<|endofprompt|>", "<|im_end|>");
15 | return encoder.encode(content).length;
16 | };
17 |
18 | export const getChatMessageLength = (messages: []): number => {
19 | /* Total tokens used for the messages */
20 | let total: number = 0;
21 |
22 | for (const message of messages) {
23 | /* Map each property of the message to the number of tokens it contains. */
24 | const propertyTokenCounts = Object.entries(message).map(
25 | ([_, value]: any) => {
26 | /* Count the number of tokens in the property value. */
27 | return getPromptLength(value);
28 | }
29 | );
30 |
31 | /* Sum the number of tokens in all properties and add 4 for metadata. */
32 | total += propertyTokenCounts.reduce((a, b) => a + b, 4);
33 | }
34 |
35 | return total + 2;
36 | };
37 |
--------------------------------------------------------------------------------
/tsconfig.json:
--------------------------------------------------------------------------------
1 | {
2 | "compilerOptions": {
3 | "target": "ESNext",
4 | "module": "ESNext",
5 | "strict": true,
6 | "declaration": true,
7 | "removeComments": true,
8 | "emitDecoratorMetadata": true,
9 | "experimentalDecorators": true,
10 | "allowSyntheticDefaultImports": true,
11 | "sourceMap": true,
12 | "outDir": "./dist",
13 | "baseUrl": "./",
14 | "paths": {},
15 | "incremental": true,
16 | "moduleResolution": "node",
17 | "skipLibCheck": true,
18 | "strictNullChecks": false,
19 | "noImplicitAny": false,
20 | "strictBindCallApply": false,
21 | "forceConsistentCasingInFileNames": false,
22 | "noFallthroughCasesInSwitch": false,
23 | "resolveJsonModule": true
24 | },
25 | "include": ["src"],
26 | "exclude": ["node_modules", "dist"]
27 | }
28 |
--------------------------------------------------------------------------------