Spaces:
Sleeping
Sleeping
Switch to serverless worker by default (PR #2 from lukestanley/serverless_json_llm)
Browse files- .gitignore +1 -0
- app.py +32 -22
- chill.py +7 -0
- docker-compose.yml +11 -0
- runpod.dockerfile +31 -0
- runpod_handler.py +41 -0
- serverless.md +64 -0
- serverless_local_test.py +28 -0
- utils.py +50 -12
.gitignore
CHANGED
@@ -1 +1,2 @@
|
|
1 |
.aider*
|
|
|
|
1 |
.aider*
|
2 |
+
.cache
|
app.py
CHANGED
@@ -1,34 +1,44 @@
|
|
|
|
1 |
from os import system as run
|
2 |
from subprocess import check_output
|
3 |
|
4 |
import gradio as gr
|
5 |
|
6 |
-
|
7 |
-
|
8 |
-
|
9 |
-
|
10 |
-
|
11 |
-
|
12 |
-
|
13 |
-
|
14 |
-
|
15 |
-
|
16 |
-
|
17 |
-
|
18 |
-
|
19 |
-
|
20 |
-
|
21 |
-
|
22 |
-
|
23 |
-
|
24 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
25 |
|
26 |
# Now chill can import llama-cpp-python without an error:
|
27 |
from chill import improvement_loop
|
28 |
|
29 |
|
30 |
-
def
|
|
|
31 |
return str(improvement_loop(text))
|
32 |
|
33 |
-
demo = gr.Interface(fn=
|
34 |
-
demo.launch(max_threads=1)
|
|
|
1 |
+
from os import environ as env
|
2 |
from os import system as run
|
3 |
from subprocess import check_output
|
4 |
|
5 |
import gradio as gr
|
6 |
|
7 |
+
|
8 |
+
def inference_binary_check():
|
9 |
+
# Without a GPU, we need to re-install llama-cpp-python to avoid an error.
|
10 |
+
# We use a shell command to detect if we have an NVIDIA GPU available:
|
11 |
+
use_gpu = True
|
12 |
+
try:
|
13 |
+
command = "nvidia-debugdump --list|grep Device"
|
14 |
+
output = str(check_output(command, shell=True).decode())
|
15 |
+
if "NVIDIA" in output and "ID" in output:
|
16 |
+
print("NVIDIA GPU detected.")
|
17 |
+
except Exception as e:
|
18 |
+
print("No NVIDIA GPU detected, using CPU. GPU check result:", e)
|
19 |
+
use_gpu = False
|
20 |
+
|
21 |
+
if use_gpu:
|
22 |
+
print("GPU detected, existing GPU focused llama-cpp-python should work.")
|
23 |
+
else:
|
24 |
+
print("Avoiding error by re-installing non-GPU llama-cpp-python build because no GPU was detected.")
|
25 |
+
run('pip uninstall llama-cpp-python -y')
|
26 |
+
run('pip install git+https://github.com/lukestanley/llama-cpp-python.git@expose_json_grammar_convert_function --upgrade --no-cache-dir --force-reinstall')
|
27 |
+
print("llama-cpp-python re-installed, will now attempt to load.")
|
28 |
+
|
29 |
+
|
30 |
+
LLM_WORKER = env.get("LLM_WORKER", "runpod")
|
31 |
+
|
32 |
+
if LLM_WORKER == "http" or LLM_WORKER == "in_memory":
|
33 |
+
inference_binary_check()
|
34 |
|
35 |
# Now chill can import llama-cpp-python without an error:
|
36 |
from chill import improvement_loop
|
37 |
|
38 |
|
39 |
+
def chill_out(text):
|
40 |
+
print("Got this input:", text)
|
41 |
return str(improvement_loop(text))
|
42 |
|
43 |
+
demo = gr.Interface(fn=chill_out, inputs="text", outputs="text")
|
44 |
+
demo.launch(max_threads=1, share=True)
|
chill.py
CHANGED
@@ -114,6 +114,13 @@ def print_iteration_result(iteration, overall_score, time_used):
|
|
114 |
def improvement_loop(input_text):
|
115 |
global original_text
|
116 |
global last_edit
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
117 |
original_text = input_text
|
118 |
|
119 |
for iteration in range(1, max_iterations + 1):
|
|
|
114 |
def improvement_loop(input_text):
|
115 |
global original_text
|
116 |
global last_edit
|
117 |
+
global suggestions
|
118 |
+
global start_time
|
119 |
+
global max_iterations
|
120 |
+
suggestions = []
|
121 |
+
last_edit = ""
|
122 |
+
start_time = time.time()
|
123 |
+
max_iterations = 20
|
124 |
original_text = input_text
|
125 |
|
126 |
for iteration in range(1, max_iterations + 1):
|
docker-compose.yml
ADDED
@@ -0,0 +1,11 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
version: '3.8'
|
2 |
+
services:
|
3 |
+
runpod:
|
4 |
+
build:
|
5 |
+
context: .
|
6 |
+
dockerfile: runpod.dockerfile
|
7 |
+
volumes:
|
8 |
+
- ./.cache:/runpod-volume/.cache
|
9 |
+
- ./test.sh:/test.sh
|
10 |
+
command: /test.sh
|
11 |
+
entrypoint: /usr/bin/python3
|
runpod.dockerfile
ADDED
@@ -0,0 +1,31 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Base image -> https://github.com/runpod/containers/blob/main/official-templates/base/Dockerfile
|
2 |
+
# DockerHub -> https://hub.docker.com/r/runpod/base/tags
|
3 |
+
FROM runpod/base:0.4.0-cuda11.8.0
|
4 |
+
|
5 |
+
# Base image sets HuggingFace cache directory to use Runpod's shared cache for efficiency:
|
6 |
+
ENV HF_HOME="/runpod-volume/.cache/huggingface/"
|
7 |
+
# Also pre-downloading models may speed up start times while
|
8 |
+
# increasing image size, but could be worth it for some use cases.
|
9 |
+
|
10 |
+
RUN python3.11 -m pip install --upgrade pip && \
|
11 |
+
python3.11 -m pip install runpod==1.6.0
|
12 |
+
|
13 |
+
RUN python3.11 -m pip install pytest cmake \
|
14 |
+
scikit-build setuptools pydantic-settings \
|
15 |
+
huggingface_hub hf_transfer \
|
16 |
+
pydantic pydantic_settings \
|
17 |
+
llama-cpp-python
|
18 |
+
|
19 |
+
# Install llama-cpp-python (build with cuda)
|
20 |
+
ENV CMAKE_ARGS="-DLLAMA_CUBLAS=on"
|
21 |
+
RUN python3.11 -m pip install git+https://github.com/lukestanley/llama-cpp-python.git@expose_json_grammar_convert_function --upgrade --no-cache-dir --force-reinstall
|
22 |
+
|
23 |
+
ADD runpod_handler.py .
|
24 |
+
ADD chill.py .
|
25 |
+
ADD utils.py .
|
26 |
+
ADD promptObjects.py .
|
27 |
+
|
28 |
+
ENV REPO_ID="TheBloke/phi-2-GGUF"
|
29 |
+
ENV MODEL_FILE="phi-2.Q2_K.gguf"
|
30 |
+
CMD python3.11 -u /runpod_handler.py
|
31 |
+
|
runpod_handler.py
ADDED
@@ -0,0 +1,41 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import runpod
|
2 |
+
from os import environ as env
|
3 |
+
import json
|
4 |
+
from pydantic import BaseModel, Field
|
5 |
+
class Movie(BaseModel):
|
6 |
+
title: str = Field(..., title="The title of the movie")
|
7 |
+
year: int = Field(..., title="The year the movie was released")
|
8 |
+
director: str = Field(..., title="The director of the movie")
|
9 |
+
genre: str = Field(..., title="The genre of the movie")
|
10 |
+
plot: str = Field(..., title="Plot summary of the movie")
|
11 |
+
|
12 |
+
def pydantic_model_to_json_schema(pydantic_model_class):
|
13 |
+
schema = pydantic_model_class.model_json_schema()
|
14 |
+
|
15 |
+
# Optional example field from schema, is not needed for the grammar generation
|
16 |
+
if "example" in schema:
|
17 |
+
del schema["example"]
|
18 |
+
|
19 |
+
json_schema = json.dumps(schema)
|
20 |
+
return json_schema
|
21 |
+
default_schema_example = """{ "title": ..., "year": ..., "director": ..., "genre": ..., "plot":...}"""
|
22 |
+
default_schema = pydantic_model_to_json_schema(Movie)
|
23 |
+
default_prompt = f"Instruct: \nOutput a JSON object in this format: {default_schema_example} for the following movie: The Matrix\nOutput:\n"
|
24 |
+
from utils import llm_stream_sans_network_simple
|
25 |
+
def handler(job):
|
26 |
+
""" Handler function that will be used to process jobs. """
|
27 |
+
job_input = job['input']
|
28 |
+
filename=env.get("MODEL_FILE", "mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf")
|
29 |
+
prompt = job_input.get('prompt', default_prompt)
|
30 |
+
schema = job_input.get('schema', default_schema)
|
31 |
+
print("got this input", str(job_input))
|
32 |
+
print("prompt", prompt )
|
33 |
+
print("schema", schema )
|
34 |
+
output = llm_stream_sans_network_simple(prompt, schema)
|
35 |
+
#print("got this output", str(output))
|
36 |
+
return output
|
37 |
+
|
38 |
+
runpod.serverless.start({
|
39 |
+
"handler": handler,
|
40 |
+
#"return_aggregate_stream": True
|
41 |
+
})
|
serverless.md
ADDED
@@ -0,0 +1,64 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
Fast severless GPU inference with RunPod
|
2 |
+
==============================
|
3 |
+
|
4 |
+
This partly GPT-4 generated document explains the integration of Runpod with Docker, including testing the Runpod Dockerfile with Docker Compose, building and pushing the image to Docker Hub, and how `app.py` makes use of it. I skimmed it and added stuff to it, as a note to myself and others.
|
5 |
+
|
6 |
+
# Motivation
|
7 |
+
Fast inference is useful. Usually an existing hosted provider would be good for this, but I was worried about getting blocked given that we need to translate some spicy text input, the concern is that it could get flagged, and result in accounts being blocked.
|
8 |
+
Also I needed something that could infer with JSON typed output, that matches particular schemas, and fast. So I found RunPod's "serverless" GPU, service.
|
9 |
+
It can be used by chill.py and app.py, as one of the worker options.
|
10 |
+
|
11 |
+
|
12 |
+
## Testing with Docker Compose
|
13 |
+
|
14 |
+
To test the Runpod Dockerfile, you can use Docker Compose which simplifies the process of running multi-container Docker applications. Here's how you can test it:
|
15 |
+
|
16 |
+
1. Ensure you have Docker and Docker Compose installed on your system.
|
17 |
+
2. Navigate to the directory containing the `docker-compose.yml` file.
|
18 |
+
3. Run the following command to build and start the container:
|
19 |
+
```
|
20 |
+
docker-compose up --build
|
21 |
+
```
|
22 |
+
4. The above command will build the image as defined in `runpod.dockerfile` and start a container with the configuration specified in `docker-compose.yml`, it will automatically run a test, that matches the format expected from the llm_stream_serverless client (in utils.py), though without the network layer in play.
|
23 |
+
|
24 |
+
|
25 |
+
# Direct testing with Docker, without Docker-Compose:
|
26 |
+
|
27 |
+
Something like this worked for me:
|
28 |
+
|
29 |
+
```sudo docker run --gpus all -it -v "$(pwd)/.cache:/runpod-volume/.cache/huggingface/" lukestanley/test:translate2 bash```
|
30 |
+
Note the cache mount. This saves re-downloading the LLMs!
|
31 |
+
|
32 |
+
|
33 |
+
## Building and Pushing to Docker Hub
|
34 |
+
|
35 |
+
After testing and ensuring that everything works as expected, you can build the Docker image and push it to Docker Hub for deployment. Here are the steps:
|
36 |
+
|
37 |
+
1. Log in to Docker Hub from your command line using `docker login --username [yourusername]`.
|
38 |
+
2. Build the Docker image with a tag:
|
39 |
+
```
|
40 |
+
docker build -t yourusername/yourimagename:tag -f runpod.dockerfile .
|
41 |
+
```
|
42 |
+
3. Once the image is built, push it to Docker Hub:
|
43 |
+
```
|
44 |
+
docker push yourusername/yourimagename:tag
|
45 |
+
```
|
46 |
+
4. Replace `yourusername`, `yourimagename`, and `tag` with your Docker Hub username, the name you want to give to your image, and the tag respectively.
|
47 |
+
|
48 |
+
# Runpod previsioning:
|
49 |
+
You'll need an account on Runpod with credit.
|
50 |
+
You'll need a serverless GPU endpoint setting up using your Docker image setup here:
|
51 |
+
https://www.runpod.io/console/serverless
|
52 |
+
It has a Flashboot feature that seems like Firecracker with GPU support, it might be using Cloud Hypervisor under the hood, currently Firecracker has no GPU support. Fly.io also has something similar, with Cloud Hypervisor.
|
53 |
+
You'll need the secret saved somewhere securely. This will likely end up as a securely treated env var for use by app.py later.
|
54 |
+
You'll also need the endpoint ID.
|
55 |
+
|
56 |
+
## Runpod Integration in `app.py`
|
57 |
+
|
58 |
+
The `app.py` file is a Gradio interface that makes use of the Runpod integration to perform inference. It checks for the presence of a GPU and installs the appropriate version of `llama-cpp-python`. Depending on the environment variable `LLM_WORKER`, it uses either the Runpod serverless API, an HTTP server, or loads the model into memory for inference.
|
59 |
+
|
60 |
+
The `greet` function in `app.py` calls `improvement_loop` from the `chill` module, which based on an environment variable, will use the Runpod worker, that is used to process the input text and generate improved text based on the model's output.
|
61 |
+
|
62 |
+
The Gradio interface is then launched with `demo.launch()`, making the application accessible via a web interface, which can be shared publicly.
|
63 |
+
|
64 |
+
Note: Ensure that the necessary environment variables such as `LLM_WORKER`, `REPO_ID`, and `MODEL_FILE` are set correctly for the integration to work properly.
|
serverless_local_test.py
ADDED
@@ -0,0 +1,28 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
#!/usr/bin/env python3
|
2 |
+
import os, json
|
3 |
+
|
4 |
+
# Define your JSON and prompt as Python dictionaries and strings
|
5 |
+
schema = {
|
6 |
+
"properties": {
|
7 |
+
"title": {"title": "The title of the movie", "type": "string"},
|
8 |
+
"year": {"title": "The year the movie was released", "type": "integer"},
|
9 |
+
"director": {"title": "The director of the movie", "type": "string"},
|
10 |
+
"genre": {"title": "The genre of the movie", "type": "string"},
|
11 |
+
"plot": {"title": "Plot summary of the movie", "type": "string"}
|
12 |
+
},
|
13 |
+
"required": ["title", "year", "director", "genre", "plot"],
|
14 |
+
"title": "Movie",
|
15 |
+
"type": "object"
|
16 |
+
}
|
17 |
+
|
18 |
+
movie ="Toy Story"
|
19 |
+
prompt = "Instruct: Output a JSON object in this format: { \"title\": ..., \"year\": ..., \"director\": ..., \"genre\": ..., \"plot\":...} for the following movie: "+movie+"\nOutput:\n"
|
20 |
+
|
21 |
+
# Construct the JSON input string
|
22 |
+
json_input = json.dumps({"input": {"schema": json.dumps(schema), "prompt": prompt}})
|
23 |
+
print(json_input)
|
24 |
+
# Define the command to execute your Python script with the JSON string
|
25 |
+
command = f'python3.11 runpod_handler.py --test_input \'{json_input}\''
|
26 |
+
|
27 |
+
# Execute the command
|
28 |
+
os.system(command)
|
utils.py
CHANGED
@@ -1,12 +1,12 @@
|
|
1 |
import json
|
2 |
from os import environ as env
|
3 |
from typing import Any, Dict, Union
|
4 |
-
import requests
|
5 |
|
|
|
6 |
from huggingface_hub import hf_hub_download
|
7 |
-
from llama_cpp import Llama, LlamaGrammar, json_schema_to_gbnf
|
8 |
|
9 |
-
|
|
|
10 |
# 1. Use the HTTP server (USE_HTTP_SERVER=True), this is good for development
|
11 |
# when you want to change the logic of the translator without restarting the server.
|
12 |
# 2. Load the model into memory
|
@@ -15,28 +15,38 @@ from llama_cpp import Llama, LlamaGrammar, json_schema_to_gbnf
|
|
15 |
# to the OpenAI API but adds a unique "grammar" parameter.
|
16 |
# The real OpenAI API has other ways to set the output format.
|
17 |
# It's possible to switch to another LLM API by changing the llm_streaming function.
|
|
|
|
|
18 |
|
19 |
URL = "http://localhost:5834/v1/chat/completions"
|
20 |
in_memory_llm = None
|
|
|
21 |
|
22 |
-
|
23 |
-
|
|
|
|
|
|
|
24 |
LLM_MODEL_PATH = env.get("LLM_MODEL_PATH", None)
|
25 |
-
|
26 |
MAX_TOKENS = int(env.get("MAX_TOKENS", 1000))
|
27 |
TEMPERATURE = float(env.get("TEMPERATURE", 0.3))
|
28 |
|
|
|
|
|
29 |
if LLM_MODEL_PATH and len(LLM_MODEL_PATH) > 0:
|
30 |
print(f"Using local model from {LLM_MODEL_PATH}")
|
31 |
-
|
32 |
print("No local LLM_MODEL_PATH environment variable set. We need a model, downloading model from HuggingFace Hub")
|
33 |
LLM_MODEL_PATH =hf_hub_download(
|
34 |
repo_id=env.get("REPO_ID", "TheBloke/Mixtral-8x7B-Instruct-v0.1-GGUF"),
|
35 |
filename=env.get("MODEL_FILE", "mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf"),
|
36 |
)
|
37 |
print(f"Model downloaded to {LLM_MODEL_PATH}")
|
|
|
|
|
38 |
|
39 |
-
if in_memory_llm is None and
|
40 |
print("Loading model into memory. If you didn't want this, set the USE_HTTP_SERVER environment variable to 'true'.")
|
41 |
in_memory_llm = Llama(model_path=LLM_MODEL_PATH, n_ctx=CONTEXT_SIZE, n_gpu_layers=N_GPU_LAYERS, verbose=True)
|
42 |
|
@@ -141,9 +151,37 @@ def llm_stream_sans_network(
|
|
141 |
json_output = json.loads(output_text)
|
142 |
return json_output
|
143 |
|
144 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
145 |
prompt = replace_text(prompt, replacements)
|
146 |
-
if
|
147 |
-
return
|
148 |
-
|
149 |
return llm_streaming(prompt, model_class)
|
|
|
|
|
|
1 |
import json
|
2 |
from os import environ as env
|
3 |
from typing import Any, Dict, Union
|
|
|
4 |
|
5 |
+
import requests
|
6 |
from huggingface_hub import hf_hub_download
|
|
|
7 |
|
8 |
+
|
9 |
+
# There are 3 ways to use the LLM model currently used:
|
10 |
# 1. Use the HTTP server (USE_HTTP_SERVER=True), this is good for development
|
11 |
# when you want to change the logic of the translator without restarting the server.
|
12 |
# 2. Load the model into memory
|
|
|
15 |
# to the OpenAI API but adds a unique "grammar" parameter.
|
16 |
# The real OpenAI API has other ways to set the output format.
|
17 |
# It's possible to switch to another LLM API by changing the llm_streaming function.
|
18 |
+
# 3. Use the RunPod API, which is a paid service with severless GPU functions.
|
19 |
+
# See serverless.md for more information.
|
20 |
|
21 |
URL = "http://localhost:5834/v1/chat/completions"
|
22 |
in_memory_llm = None
|
23 |
+
worker_options = ["runpod", "http", "in_memory"]
|
24 |
|
25 |
+
LLM_WORKER = env.get("LLM_WORKER", "runpod")
|
26 |
+
if LLM_WORKER not in worker_options:
|
27 |
+
raise ValueError(f"Invalid worker: {LLM_WORKER}")
|
28 |
+
N_GPU_LAYERS = int(env.get("N_GPU_LAYERS", -1)) # Default to -1, use all layers if available
|
29 |
+
CONTEXT_SIZE = int(env.get("CONTEXT_SIZE", 2048))
|
30 |
LLM_MODEL_PATH = env.get("LLM_MODEL_PATH", None)
|
31 |
+
|
32 |
MAX_TOKENS = int(env.get("MAX_TOKENS", 1000))
|
33 |
TEMPERATURE = float(env.get("TEMPERATURE", 0.3))
|
34 |
|
35 |
+
performing_local_inference = (LLM_WORKER == "in_memory" or LLM_WORKER == "http")
|
36 |
+
|
37 |
if LLM_MODEL_PATH and len(LLM_MODEL_PATH) > 0:
|
38 |
print(f"Using local model from {LLM_MODEL_PATH}")
|
39 |
+
if performing_local_inference and not LLM_MODEL_PATH:
|
40 |
print("No local LLM_MODEL_PATH environment variable set. We need a model, downloading model from HuggingFace Hub")
|
41 |
LLM_MODEL_PATH =hf_hub_download(
|
42 |
repo_id=env.get("REPO_ID", "TheBloke/Mixtral-8x7B-Instruct-v0.1-GGUF"),
|
43 |
filename=env.get("MODEL_FILE", "mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf"),
|
44 |
)
|
45 |
print(f"Model downloaded to {LLM_MODEL_PATH}")
|
46 |
+
if LLM_WORKER == "http" or LLM_WORKER == "in_memory":
|
47 |
+
from llama_cpp import Llama, LlamaGrammar, json_schema_to_gbnf
|
48 |
|
49 |
+
if in_memory_llm is None and LLM_WORKER == "in_memory":
|
50 |
print("Loading model into memory. If you didn't want this, set the USE_HTTP_SERVER environment variable to 'true'.")
|
51 |
in_memory_llm = Llama(model_path=LLM_MODEL_PATH, n_ctx=CONTEXT_SIZE, n_gpu_layers=N_GPU_LAYERS, verbose=True)
|
52 |
|
|
|
151 |
json_output = json.loads(output_text)
|
152 |
return json_output
|
153 |
|
154 |
+
|
155 |
+
def llm_stream_serverless(prompt,model):
|
156 |
+
RUNPOD_ENDPOINT_ID = env.get("RUNPOD_ENDPOINT_ID")
|
157 |
+
RUNPOD_API_KEY = env.get("RUNPOD_API_KEY")
|
158 |
+
url = f"https://api.runpod.ai/v2/{RUNPOD_ENDPOINT_ID}/runsync"
|
159 |
+
|
160 |
+
headers = {
|
161 |
+
'Content-Type': 'application/json',
|
162 |
+
'Authorization': f'Bearer {RUNPOD_API_KEY}'
|
163 |
+
}
|
164 |
+
|
165 |
+
schema = model.schema()
|
166 |
+
data = {
|
167 |
+
'input': {
|
168 |
+
'schema': json.dumps(schema),
|
169 |
+
'prompt': prompt
|
170 |
+
}
|
171 |
+
}
|
172 |
+
|
173 |
+
response = requests.post(url, json=data, headers=headers)
|
174 |
+
result = response.json()
|
175 |
+
print(result)
|
176 |
+
output = result['output'].replace("model:mixtral-8x7b-instruct-v0.1.Q4_K_M.gguf\n", "")
|
177 |
+
# TODO: remove replacement once new version of runpod is deployed
|
178 |
+
return json.loads(output)
|
179 |
+
|
180 |
+
def query_ai_prompt(prompt, replacements, model_class):
|
181 |
prompt = replace_text(prompt, replacements)
|
182 |
+
if LLM_WORKER == "runpod":
|
183 |
+
return llm_stream_serverless(prompt, model_class)
|
184 |
+
if LLM_WORKER == "http":
|
185 |
return llm_streaming(prompt, model_class)
|
186 |
+
if LLM_WORKER == "in_memory":
|
187 |
+
return llm_stream_sans_network(prompt, model_class)
|