返回提交历史
Modified
.gitignore
+2
-0
Added
g4f/local/__init__.py
+109
-0
Added
g4f/local/core/engine.py
+42
-0
Added
g4f/local/core/models.py
+86
-0
Added
g4f/local/models/model-here
+1
-0
XFEstudio/gpt4free
~ | support local llm inference
b7342b1f
代码差异
5 个文件
+240
-0
@@ -50,3 +50,5 @@ prv.py
50
50
x.js
51
51
x.py
52
52
info.txt
53
local.py
54
*.gguf
@@ -0,0 +1,109 @@
1
import random, string, time, re
2
3
from ..typing import Union, Iterator, Messages
4
from ..stubs import ChatCompletion, ChatCompletionChunk
5
from .core.engine import LocalProvider
6
from .core.models import models
7
8
IterResponse = Iterator[Union[ChatCompletion, ChatCompletionChunk]]
9
10
def read_json(text: str) -> dict:
11
match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text)
12
if match:
13
return match.group("code")
14
return text
15
16
def iter_response(
17
response: Iterator[str],
18
stream: bool,
19
response_format: dict = None,
20
max_tokens: int = None,
21
stop: list = None
22
) -> IterResponse:
23
24
content = ""
25
finish_reason = None
26
completion_id = ''.join(random.choices(string.ascii_letters + string.digits, k=28))
27
for idx, chunk in enumerate(response):
28
content += str(chunk)
29
if max_tokens is not None and idx + 1 >= max_tokens:
30
finish_reason = "length"
31
first = -1
32
word = None
33
if stop is not None:
34
for word in list(stop):
35
first = content.find(word)
36
if first != -1:
37
content = content[:first]
38
break
39
if stream and first != -1:
40
first = chunk.find(word)
41
if first != -1:
42
chunk = chunk[:first]
43
else:
44
first = 0
45
if first != -1:
46
finish_reason = "stop"
47
if stream:
48
yield ChatCompletionChunk(chunk, None, completion_id, int(time.time()))
49
if finish_reason is not None:
50
break
51
finish_reason = "stop" if finish_reason is None else finish_reason
52
if stream:
53
yield ChatCompletionChunk(None, finish_reason, completion_id, int(time.time()))
54
else:
55
if response_format is not None and "type" in response_format:
56
if response_format["type"] == "json_object":
57
content = read_json(content)
58
yield ChatCompletion(content, finish_reason, completion_id, int(time.time()))
59
60
def filter_none(**kwargs):
61
for key in list(kwargs.keys()):
62
if kwargs[key] is None:
63
del kwargs[key]
64
return kwargs
65
66
class LocalClient():
67
def __init__(
68
self,
69
**kwargs
70
) -> None:
71
self.chat: Chat = Chat(self)
72
73
@staticmethod
74
def list_models():
75
return list(models.keys())
76
77
class Completions():
78
def __init__(self, client: LocalClient):
79
self.client: LocalClient = client
80
81
def create(
82
self,
83
messages: Messages,
84
model: str,
85
stream: bool = False,
86
response_format: dict = None,
87
max_tokens: int = None,
88
stop: Union[list[str], str] = None,
89
**kwargs
90
) -> Union[ChatCompletion, Iterator[ChatCompletionChunk]]:
91
92
stop = [stop] if isinstance(stop, str) else stop
93
response = LocalProvider.create_completion(
94
model, messages, stream,
95
**filter_none(
96
max_tokens=max_tokens,
97
stop=stop,
98
),
99
**kwargs
100
)
101
response = iter_response(response, stream, response_format, max_tokens, stop)
102
return response if stream else next(response)
103
104
class Chat():
105
completions: Completions
106
107
def __init__(self, client: LocalClient):
108
self.completions = Completions(client)
109
@@ -0,0 +1,42 @@
1
import os
2
3
from gpt4all import GPT4All
4
from .models import models
5
6
class LocalProvider:
7
@staticmethod
8
def create_completion(model, messages, stream, **kwargs):
9
if model not in models:
10
raise ValueError(f"Model '{model}' not found / not yet implemented")
11
12
model = models[model]
13
model_dir = os.path.join(os.path.dirname(os.path.abspath(__file__)), '../models/')
14
full_model_path = os.path.join(model_dir, model['path'])
15
16
if not os.path.isfile(full_model_path):
17
print(f"Model file '{full_model_path}' not found.")
18
download = input(f'Do you want to download {model["path"]} ? [y/n]')
19
20
if download in ['y', 'Y']:
21
GPT4All.download_model(model['path'], model_dir)
22
else:
23
raise ValueError(f"Model '{model['path']}' not found.")
24
25
model = GPT4All(model_name=model['path'],
26
n_threads=8,
27
verbose=False,
28
allow_download=False,
29
model_path=model_dir)
30
31
system_template = next((message['content'] for message in messages if message['role'] == 'system'),
32
'A chat between a curious user and an artificial intelligence assistant.')
33
34
prompt_template = 'USER: {0}\nASSISTANT: '
35
conversation = '\n'.join(f"{msg['role'].upper()}: {msg['content']}" for msg in messages) + "\nASSISTANT: "
36
37
with model.chat_session(system_template, prompt_template):
38
if stream:
39
for token in model.generate(conversation, streaming=True):
40
yield token
41
else:
42
yield model.generate(conversation)
@@ -0,0 +1,86 @@
1
models = {
2
"mistral-7b": {
3
"path": "mistral-7b-openorca.gguf2.Q4_0.gguf",
4
"ram": "8",
5
"prompt": "<|im_start|>user\n%1<|im_end|>\n<|im_start|>assistant\n",
6
"system": "<|im_start|>system\nYou are MistralOrca, a large language model trained by Alignment Lab AI. For multi-step problems, write out your reasoning for each step.\n<|im_end|>"
7
},
8
"mistral-7b-instruct": {
9
"path": "mistral-7b-instruct-v0.1.Q4_0.gguf",
10
"ram": "8",
11
"prompt": "[INST] %1 [/INST]",
12
"system": None
13
},
14
"gpt4all-falcon": {
15
"path": "gpt4all-falcon-newbpe-q4_0.gguf",
16
"ram": "8",
17
"prompt": "### Instruction:\n%1\n### Response:\n",
18
"system": None
19
},
20
"orca-2": {
21
"path": "orca-2-13b.Q4_0.gguf",
22
"ram": "16",
23
"prompt": None,
24
"system": None
25
},
26
"wizardlm-13b": {
27
"path": "wizardlm-13b-v1.2.Q4_0.gguf",
28
"ram": "16",
29
"prompt": None,
30
"system": None
31
},
32
"nous-hermes-llama2": {
33
"path": "nous-hermes-llama2-13b.Q4_0.gguf",
34
"ram": "16",
35
"prompt": "### Instruction:\n%1\n### Response:\n",
36
"system": None
37
},
38
"gpt4all-13b-snoozy": {
39
"path": "gpt4all-13b-snoozy-q4_0.gguf",
40
"ram": "16",
41
"prompt": None,
42
"system": None
43
},
44
"mpt-7b-chat": {
45
"path": "mpt-7b-chat-newbpe-q4_0.gguf",
46
"ram": "8",
47
"prompt": "<|im_start|>user\n%1<|im_end|>\n<|im_start|>assistant\n",
48
"system": "<|im_start|>system\n- You are a helpful assistant chatbot trained by MosaicML.\n- You answer questions.\n- You are excited to be able to help the user, but will refuse to do anything that could be considered harmful to the user.\n- You are more than just an information source, you are also able to write poetry, short stories, and make jokes.<|im_end|>"
49
},
50
"orca-mini-3b": {
51
"path": "orca-mini-3b-gguf2-q4_0.gguf",
52
"ram": "4",
53
"prompt": "### User:\n%1\n### Response:\n",
54
"system": "### System:\nYou are an AI assistant that follows instruction extremely well. Help as much as you can.\n\n"
55
},
56
"replit-code-3b": {
57
"path": "replit-code-v1_5-3b-newbpe-q4_0.gguf",
58
"ram": "4",
59
"prompt": "%1",
60
"system": None
61
},
62
"starcoder": {
63
"path": "starcoder-newbpe-q4_0.gguf",
64
"ram": "4",
65
"prompt": "%1",
66
"system": None
67
},
68
"rift-coder-7b": {
69
"path": "rift-coder-v0-7b-q4_0.gguf",
70
"ram": "8",
71
"prompt": "%1",
72
"system": None
73
},
74
"all-MiniLM-L6-v2": {
75
"path": "all-MiniLM-L6-v2-f16.gguf",
76
"ram": "1",
77
"prompt": None,
78
"system": None
79
},
80
"mistral-7b-german": {
81
"path": "em_german_mistral_v01.Q4_0.gguf",
82
"ram": "8",
83
"prompt": "USER: %1 ASSISTANT: ",
84
"system": "Du bist ein hilfreicher Assistent. "
85
}
86
}
@@ -0,0 +1 @@
1
.