Files
2026-07-13 13:24:13 +08:00

148 lines
6.4 KiB
Python

import requests
import json
from typing import List, Iterable, Tuple, Union
from omegaconf.listconfig import ListConfig
from general_util.logger import get_child_logger
logger = get_child_logger("VLLM")
def post_http_request(api_url: str,
n: int = 1,
max_tokens: int = 16,
temperature: float = 0.0,
use_beam_search: bool = False,
stream: bool = False,
stop: List[str] = ["</s>"],
**kwargs) -> requests.Response:
headers = {"User-Agent": "MERIt Test Client"}
# headers = {
# "accept": "application/json",
# "content-type": "application/json",
#
# }
if "TOGETHER_API_KEY" in kwargs:
headers["authorization"] = f"Bearer {kwargs.pop('TOGETHER_API_KEY')}"
p_load = {
"n": n,
"use_beam_search": use_beam_search,
"temperature": temperature,
"max_tokens": max_tokens,
"stream": stream,
"stop": stop,
}
p_load.update(kwargs)
response = requests.post(api_url, headers=headers, json=p_load, stream=True)
return response
def get_streaming_response(response: requests.Response) -> Iterable[List[str]]:
for chunk in response.iter_lines(chunk_size=8192,
decode_unicode=False,
delimiter=b"\0"):
if chunk:
data = json.loads(chunk.decode("utf-8"))
output = data["text"]
yield output
def get_response(response: requests.Response) -> Tuple[str, str]:
data = json.loads(response.content)
output = data["text"]
return output, data
class VLLMRequestGenerator:
def __init__(self, api_url: str, n: int = 1, max_tokens: int = 1024, use_beam_search: bool = False, stream: bool = False,
temperature: float = 0.0, stop: Union[List[str], ListConfig] = ["</s>"], **kwargs):
self.api_url = api_url
self.n = n
self.max_tokens = max_tokens
self.use_beam_search = use_beam_search
self.stream = stream
self.stop = stop if isinstance(stop, list) else list(stop)
self.temperature = temperature
self.kwargs = kwargs
self.max_retry = 10
print(self.kwargs)
def __call__(self, prompt: str) -> str:
re_try = 0
max_tokens = self.max_tokens
while True:
if "completions" not in self.api_url:
response, content = get_response(post_http_request(prompt=prompt,
api_url=self.api_url,
n=self.n,
max_tokens=max_tokens,
temperature=self.temperature,
use_beam_search=self.use_beam_search,
stream=self.stream,
stop=self.stop,
**self.kwargs))[0]
response = response.replace(prompt, "")
# TODO: Add error processing here (need to remove `get_response` method)
elif "/chat/completions" in self.api_url:
if not isinstance(prompt, list):
prompt = [{"role": "user", "content": prompt}]
response = post_http_request(messages=prompt,
api_url=self.api_url,
n=self.n,
max_tokens=max_tokens,
temperature=self.temperature,
use_beam_search=self.use_beam_search,
stream=self.stream,
stop=self.stop,
**self.kwargs)
if response.status_code != 200:
logger.warning(response.json())
response = response.content.decode('utf-8')
if "maximum context length" in response:
max_tokens -= 100
re_try += 1
logger.warning("max_tokens reduced to: {}".format(max_tokens))
response = ""
else:
re_try = 0
outputs = []
for item in json.loads(response.content)["choices"]:
outputs.append(item["message"]["content"].replace(prompt[-1]["content"], ""))
if len(outputs) == 1:
response = outputs[0]
else:
response = outputs
else:
response = post_http_request(prompt=prompt,
api_url=self.api_url,
n=self.n,
max_tokens=max_tokens,
temperature=self.temperature,
use_beam_search=self.use_beam_search,
stream=self.stream,
stop=self.stop,
**self.kwargs)
if response.status_code != 200:
logger.warning(response.json())
response = response.content.decode('utf-8')
if "maximum context length" in response:
max_tokens -= 100
re_try += 1
logger.warning("max_tokens reduced to: {}".format(max_tokens))
response = ""
else:
re_try = 0
outputs = []
for item in json.loads(response.content)["choices"]:
outputs.append(item["text"].replace(prompt, ""))
if len(outputs) == 1:
response = outputs[0]
else:
response = outputs
if re_try == 0 or re_try > self.max_retry:
break
return response