XFE Git
XFE Studio Git
Git 首页 全局搜索
XFE 主站 文档 NuGet
公开
关注 0 Fork 0 Star 1
返回提交历史

XFEstudio/gpt4free

Update client

b913a8f2
H Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

1 个文件 +239 -0
Added g4f/client/async.py +239 -0
@@ -0,0 +1,239 @@
1 from __future__ import annotations
2
3 import re
4 import os
5 import time
6 import random
7 import string
8
9 from .stubs import ChatCompletion, ChatCompletionChunk, Image, ImagesResponse
10 from .typing import Union, Iterator, Messages, ImageType
11 from .providers.types import BaseProvider, ProviderType, FinishReason
12 from .image import ImageResponse as ImageProviderResponse
13 from .errors import NoImageResponseError, RateLimitError, MissingAuthError
14 from . import get_model_and_provider, get_last_provider
15
16 from .Provider.BingCreateImages import BingCreateImages
17 from .Provider.needs_auth import Gemini, OpenaiChat
18 from .Provider.You import You
19
20 def read_json(text: str) -> dict:
21 """
22 Parses JSON code block from a string.
23
24 Args:
25 text (str): A string containing a JSON code block.
26
27 Returns:
28 dict: A dictionary parsed from the JSON code block.
29 """
30 match = re.search(r"```(json|)\n(?P<code>[\S\s]+?)\n```", text)
31 if match:
32 return match.group("code")
33 return text
34
35 def iter_response(
36 response: iter[str],
37 stream: bool,
38 response_format: dict = None,
39 max_tokens: int = None,
40 stop: list = None
41 ) -> IterResponse:
42 content = ""
43 finish_reason = None
44 completion_id = ''.join(random.choices(string.ascii_letters + string.digits, k=28))
45 for idx, chunk in enumerate(response):
46 if isinstance(chunk, FinishReason):
47 finish_reason = chunk.reason
48 break
49 content += str(chunk)
50 if max_tokens is not None and idx + 1 >= max_tokens:
51 finish_reason = "length"
52 first = -1
53 word = None
54 if stop is not None:
55 for word in list(stop):
56 first = content.find(word)
57 if first != -1:
58 content = content[:first]
59 break
60 if stream and first != -1:
61 first = chunk.find(word)
62 if first != -1:
63 chunk = chunk[:first]
64 else:
65 first = 0
66 if first != -1:
67 finish_reason = "stop"
68 if stream:
69 yield ChatCompletionChunk(chunk, None, completion_id, int(time.time()))
70 if finish_reason is not None:
71 break
72 finish_reason = "stop" if finish_reason is None else finish_reason
73 if stream:
74 yield ChatCompletionChunk(None, finish_reason, completion_id, int(time.time()))
75 else:
76 if response_format is not None and "type" in response_format:
77 if response_format["type"] == "json_object":
78 content = read_json(content)
79 yield ChatCompletion(content, finish_reason, completion_id, int(time.time()))
80
81 def iter_append_model_and_provider(response: IterResponse) -> IterResponse:
82 last_provider = None
83 for chunk in response:
84 last_provider = get_last_provider(True) if last_provider is None else last_provider
85 chunk.model = last_provider.get("model")
86 chunk.provider = last_provider.get("name")
87 yield chunk
88
89 class Client():
90
91 def __init__(
92 self,
93 api_key: str = None,
94 proxies: Proxies = None,
95 provider: ProviderType = None,
96 image_provider: ImageProvider = None,
97 **kwargs
98 ) -> None:
99 self.api_key: str = api_key
100 self.proxies: Proxies = proxies
101 self.chat: Chat = Chat(self, provider)
102 self.images: Images = Images(self, image_provider)
103
104 def get_proxy(self) -> Union[str, None]:
105 if isinstance(self.proxies, str):
106 return self.proxies
107 elif self.proxies is None:
108 return os.environ.get("G4F_PROXY")
109 elif "all" in self.proxies:
110 return self.proxies["all"]
111 elif "https" in self.proxies:
112 return self.proxies["https"]
113
114 def filter_none(**kwargs):
115 for key in list(kwargs.keys()):
116 if kwargs[key] is None:
117 del kwargs[key]
118 return kwargs
119
120 class Completions():
121 def __init__(self, client: Client, provider: ProviderType = None):
122 self.client: Client = client
123 self.provider: ProviderType = provider
124
125 def create(
126 self,
127 messages: Messages,
128 model: str,
129 provider: ProviderType = None,
130 stream: bool = False,
131 response_format: dict = None,
132 max_tokens: int = None,
133 stop: Union[list[str], str] = None,
134 api_key: str = None,
135 ignored : list[str] = None,
136 ignore_working: bool = False,
137 ignore_stream: bool = False,
138 **kwargs
139 ) -> Union[ChatCompletion, Iterator[ChatCompletionChunk]]:
140 model, provider = get_model_and_provider(
141 model,
142 self.provider if provider is None else provider,
143 stream,
144 ignored,
145 ignore_working,
146 ignore_stream,
147 **kwargs
148 )
149 stop = [stop] if isinstance(stop, str) else stop
150 response = provider.create_completion(
151 model, messages, stream,
152 **filter_none(
153 proxy=self.client.get_proxy(),
154 max_tokens=max_tokens,
155 stop=stop,
156 api_key=self.client.api_key if api_key is None else api_key
157 ),
158 **kwargs
159 )
160 response = iter_response(response, stream, response_format, max_tokens, stop)
161 response = iter_append_model_and_provider(response)
162 return response if stream else next(response)
163
164 class Chat():
165 completions: Completions
166
167 def __init__(self, client: Client, provider: ProviderType = None):
168 self.completions = Completions(client, provider)
169
170 class ImageModels():
171 gemini = Gemini
172 openai = OpenaiChat
173 you = You
174
175 def __init__(self, client: Client) -> None:
176 self.client = client
177 self.default = BingCreateImages(proxy=self.client.get_proxy())
178
179 def get(self, name: str, default: ImageProvider = None) -> ImageProvider:
180 return getattr(self, name) if hasattr(self, name) else default or self.default
181
182 def iter_image_response(response: Iterator) -> Union[ImagesResponse, None]:
183 for chunk in list(response):
184 if isinstance(chunk, ImageProviderResponse):
185 return ImagesResponse([Image(image) for image in chunk.get_list()])
186
187 def create_image(client: Client, provider: ProviderType, prompt: str, model: str = "", **kwargs) -> Iterator:
188 prompt = f"create a image with: {prompt}"
189 return provider.create_completion(
190 model,
191 [{"role": "user", "content": prompt}],
192 True,
193 proxy=client.get_proxy(),
194 **kwargs
195 )
196
197 class Images():
198 def __init__(self, client: Client, provider: ImageProvider = None):
199 self.client: Client = client
200 self.provider: ImageProvider = provider
201 self.models: ImageModels = ImageModels(client)
202
203 def generate(self, prompt, model: str = None, **kwargs) -> ImagesResponse:
204 provider = self.models.get(model, self.provider)
205 if isinstance(provider, type) and issubclass(provider, BaseProvider):
206 response = create_image(self.client, provider, prompt, **kwargs)
207 else:
208 try:
209 response = list(provider.create(prompt))
210 except (RateLimitError, MissingAuthError) as e:
211 # Fallback for default provider
212 if self.provider is None:
213 response = create_image(self.client, self.models.you, prompt, model or "dall-e", **kwargs)
214 else:
215 raise e
216 image = iter_image_response(response)
217 if image is None:
218 raise NoImageResponseError()
219 return image
220
221 def create_variation(self, image: ImageType, model: str = None, **kwargs):
222 provider = self.models.get(model, self.provider)
223 result = None
224 if isinstance(provider, type) and issubclass(provider, BaseProvider):
225 response = provider.create_completion(
226 "",
227 [{"role": "user", "content": "create a image like this"}],
228 True,
229 image=image,
230 proxy=self.client.get_proxy(),
231 **kwargs
232 )
233 for chunk in response:
234 if isinstance(chunk, ImageProviderResponse):
235 result = ([chunk.images] if isinstance(chunk.images, str) else chunk.images)
236 result = ImagesResponse([Image(image)for image in result])
237 if result is None:
238 raise NoImageResponseError()
239 return result