Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
25 changes: 24 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -295,12 +295,35 @@ model = GenericLoraKbitModel('<model_path>')
```
Replace `<model_path>` with a local directory or a Hugging Face model like `mistralai/Mistral-7B-Instruct-v0.2`.

### Cloud Text‑Generation APIs

xTuring also ships cloud API wrappers for synthetic‑data generation and self‑instruct workflows.

| Provider | Key | Default model |
| -- | -- | -- |
| OpenAI | openai, openai_davinci, openai_chat | davinci / gpt-3.5-turbo |
| Cohere | cohere, cohere_medium | medium |
| Claude | claude, claude_3_sonnet | claude-3-sonnet |
| MiniMax | minimax, minimax_m2_7, minimax_m2_7_highspeed | MiniMax-M2.7 / MiniMax-M2.7-highspeed |

```python
from xturing.model_apis import MiniMaxM27

api = MiniMaxM27(api_key="your-minimax-api-key")
results = api.generate_text(
prompts=["Explain quantum computing for beginners."],
max_tokens=256,
temperature=0.7,
)
print(results[0]["response"]["choices"][0]["text"])
```

## 📈 Roadmap
- [x] Support for `LLaMA`, `LLaMA 2`, `GPT-J`, `GPT-2`, and `GPT-OSS` models
- [x] Dataset generation using self-instruction
- [x] Low-precision LoRA fine-tuning and unsupervised fine-tuning
- [x] INT8 low-precision fine-tuning support
- [x] OpenAI, Cohere, and Claude model APIs for dataset generation
- [x] OpenAI, Cohere, Claude, and MiniMax model APIs for dataset generation
- [x] Added fine-tuned checkpoints for some models to the hub
- [x] INT4 LLaMA LoRA fine-tuning demo
- [x] INT4 LLaMA LoRA fine-tuning with INT4 generation
Expand Down
10 changes: 10 additions & 0 deletions src/xturing/model_apis/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,14 +2,24 @@
from xturing.model_apis.claude import ClaudeSonnet, ClaudeTextGenerationAPI
from xturing.model_apis.cohere import CohereTextGenerationAPI
from xturing.model_apis.cohere import Medium as CohereMedium
from xturing.model_apis.minimax import (
MiniMaxM27,
MiniMaxM27HighSpeed,
MiniMaxTextGenerationAPI,
)
from xturing.model_apis.openai import ChatGPT as OpenAIChatGPT
from xturing.model_apis.openai import Davinci as OpenAIDavinci
from xturing.model_apis.openai import OpenAITextGenerationAPI

BaseApi.add_to_registry(OpenAITextGenerationAPI.config_name, OpenAITextGenerationAPI)
BaseApi.add_to_registry(CohereTextGenerationAPI.config_name, CohereTextGenerationAPI)
BaseApi.add_to_registry(ClaudeTextGenerationAPI.config_name, ClaudeTextGenerationAPI)
BaseApi.add_to_registry(
MiniMaxTextGenerationAPI.config_name, MiniMaxTextGenerationAPI
)
BaseApi.add_to_registry(OpenAIDavinci.config_name, OpenAIDavinci)
BaseApi.add_to_registry(OpenAIChatGPT.config_name, OpenAIChatGPT)
BaseApi.add_to_registry(CohereMedium.config_name, CohereMedium)
BaseApi.add_to_registry(ClaudeSonnet.config_name, ClaudeSonnet)
BaseApi.add_to_registry(MiniMaxM27.config_name, MiniMaxM27)
BaseApi.add_to_registry(MiniMaxM27HighSpeed.config_name, MiniMaxM27HighSpeed)
157 changes: 157 additions & 0 deletions src/xturing/model_apis/minimax.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,157 @@
import time
from datetime import datetime

try:
from openai import OpenAI
from openai import APIConnectionError as OpenAIAPIConnectionError
from openai import APIError as OpenAIAPIError
from openai import RateLimitError as OpenAIRateLimitError
except ModuleNotFoundError as import_err: # pragma: no cover - optional dependency
OpenAI = None
OpenAIAPIError = OpenAIAPIConnectionError = OpenAIRateLimitError = Exception
_OPENAI_IMPORT_ERROR = import_err
else: # pragma: no cover - dependency import paths exercised in runtime envs
_OPENAI_IMPORT_ERROR = None

from xturing.model_apis.base import TextGenerationAPI

_MINIMAX_BASE_URL = "https://api.minimax.io/v1"


class MiniMaxTextGenerationAPI(TextGenerationAPI):
config_name = "minimax"

def __init__(self, model, api_key, request_batch_size=1):
openai_cls = self._ensure_dependency()
super().__init__(
engine=model, api_key=api_key, request_batch_size=request_batch_size
)
self._client = openai_cls(
api_key=api_key, base_url=_MINIMAX_BASE_URL
)

@staticmethod
def _ensure_dependency():
import importlib

module = importlib.import_module(__name__)
openai_cls = getattr(module, "OpenAI", None)
if openai_cls is None:
openai_import_error = getattr(module, "_OPENAI_IMPORT_ERROR", None)
message = (
"The openai SDK is required for MiniMaxTextGenerationAPI. "
"Install it with `pip install openai`."
)
raise ModuleNotFoundError(message) from openai_import_error
return openai_cls

def _clamp_temperature(self, temperature):
if temperature is not None and temperature <= 0.0:
return 0.01
return temperature

def _make_request(self, prompt, max_tokens, temperature, top_p, stop_sequences):
params = {
"model": self.engine,
"max_tokens": max_tokens,
"temperature": self._clamp_temperature(temperature),
"messages": [{"role": "user", "content": prompt}],
}
if top_p is not None:
params["top_p"] = top_p
if stop_sequences:
params["stop"] = stop_sequences
return self._client.chat.completions.create(**params)

@staticmethod
def _render_response(response):
if response is None:
return None
choice = response.choices[0] if response.choices else None
if choice is None:
return None
text = choice.message.content or ""
predicts = {
"choices": [
{
"text": text,
"finish_reason": choice.finish_reason or "stop",
}
]
}
return predicts

def generate_text(
self,
prompts,
max_tokens,
temperature,
top_p=None,
frequency_penalty=None,
presence_penalty=None,
stop_sequences=None,
logprobs=None,
n=1,
best_of=1,
retries=3,
**kwargs,
):
if not isinstance(prompts, list):
prompts = [prompts]

results = []
for prompt in prompts:
response = None
retry_cnt = 0
backoff_time = 30
while retry_cnt <= retries:
try:
response = self._make_request(
prompt=prompt,
max_tokens=max_tokens,
temperature=temperature,
top_p=top_p,
stop_sequences=stop_sequences,
)
break
except (
OpenAIAPIError,
OpenAIAPIConnectionError,
OpenAIRateLimitError,
) as e:
print(f"MiniMaxError: {e}.")
print(f"Retrying in {backoff_time} seconds...")
time.sleep(backoff_time)
backoff_time *= 1.5
retry_cnt += 1

data = {
"prompt": prompt,
"response": self._render_response(response),
"created_at": str(datetime.now()),
}
results.append(data)

return results


class MiniMaxM27(MiniMaxTextGenerationAPI):
config_name = "minimax_m2_7"

def __init__(self, api_key, request_batch_size=1):
super().__init__(
model="MiniMax-M2.7",
api_key=api_key,
request_batch_size=request_batch_size,
)


class MiniMaxM27HighSpeed(MiniMaxTextGenerationAPI):
config_name = "minimax_m2_7_highspeed"

def __init__(self, api_key, request_batch_size=1):
super().__init__(
model="MiniMax-M2.7-highspeed",
api_key=api_key,
request_batch_size=request_batch_size,
)
Loading