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

XFEstudio/gpt4free

Fix deprecated construct method, fix unittests

20ad0802
Heiner Lohaus <hlohaus@users.noreply.github.com>
提交于

代码差异

3 个文件 +39 -32
Modified etc/unittest/backend.py +1 -1
@@ -35,7 +35,7 @@ class TestBackendApi(unittest.TestCase):
35 35
36 36 def test_get_providers(self):
37 37 response = self.api.get_providers()
38 self.assertIsInstance(response, dict)
38 self.assertIsInstance(response, list)
39 39 self.assertTrue(len(response) > 0)
40 40
41 41 def test_search(self):
Modified g4f/client/__init__.py +10 -10
@@ -74,7 +74,7 @@ def iter_response(
74 74 finish_reason = "stop"
75 75
76 76 if stream:
77 yield ChatCompletionChunk.construct(chunk, None, completion_id, int(time.time()))
77 yield ChatCompletionChunk.model_construct(chunk, None, completion_id, int(time.time()))
78 78
79 79 if finish_reason is not None:
80 80 break
@@ -84,12 +84,12 @@ def iter_response(
84 84 finish_reason = "stop" if finish_reason is None else finish_reason
85 85
86 86 if stream:
87 yield ChatCompletionChunk.construct(None, finish_reason, completion_id, int(time.time()))
87 yield ChatCompletionChunk.model_construct(None, finish_reason, completion_id, int(time.time()))
88 88 else:
89 89 if response_format is not None and "type" in response_format:
90 90 if response_format["type"] == "json_object":
91 91 content = filter_json(content)
92 yield ChatCompletion.construct(content, finish_reason, completion_id, int(time.time()))
92 yield ChatCompletion.model_construct(content, finish_reason, completion_id, int(time.time()))
93 93
94 94 # Synchronous iter_append_model_and_provider function
95 95 def iter_append_model_and_provider(response: ChatCompletionResponseType) -> ChatCompletionResponseType:
@@ -138,7 +138,7 @@ async def async_iter_response(
138 138 finish_reason = "stop"
139 139
140 140 if stream:
141 yield ChatCompletionChunk.construct(chunk, None, completion_id, int(time.time()))
141 yield ChatCompletionChunk.model_construct(chunk, None, completion_id, int(time.time()))
142 142
143 143 if finish_reason is not None:
144 144 break
@@ -146,12 +146,12 @@ async def async_iter_response(
146 146 finish_reason = "stop" if finish_reason is None else finish_reason
147 147
148 148 if stream:
149 yield ChatCompletionChunk.construct(None, finish_reason, completion_id, int(time.time()))
149 yield ChatCompletionChunk.model_construct(None, finish_reason, completion_id, int(time.time()))
150 150 else:
151 151 if response_format is not None and "type" in response_format:
152 152 if response_format["type"] == "json_object":
153 153 content = filter_json(content)
154 yield ChatCompletion.construct(content, finish_reason, completion_id, int(time.time()))
154 yield ChatCompletion.model_construct(content, finish_reason, completion_id, int(time.time()))
155 155 finally:
156 156 await safe_aclose(response)
157 157
@@ -422,7 +422,7 @@ class Images:
422 422 last_provider = get_last_provider(True)
423 423 if response_format == "url":
424 424 # Return original URLs without saving locally
425 images = [Image.construct(url=image, revised_prompt=response.alt) for image in response.get_list()]
425 images = [Image.model_construct(url=image, revised_prompt=response.alt) for image in response.get_list()]
426 426 else:
427 427 # Save locally for None (default) case
428 428 images = await copy_images(response.get_list(), response.get("cookies"), proxy)
@@ -430,11 +430,11 @@ class Images:
430 430 async def process_image_item(image_file: str) -> Image:
431 431 with open(os.path.join(images_dir, os.path.basename(image_file)), "rb") as file:
432 432 image_data = base64.b64encode(file.read()).decode()
433 return Image.construct(b64_json=image_data, revised_prompt=response.alt)
433 return Image.model_construct(b64_json=image_data, revised_prompt=response.alt)
434 434 images = await asyncio.gather(*[process_image_item(image) for image in images])
435 435 else:
436 images = [Image.construct(url=f"/images/{os.path.basename(image)}", revised_prompt=response.alt) for image in images]
437 return ImagesResponse.construct(
436 images = [Image.model_construct(url=f"/images/{os.path.basename(image)}", revised_prompt=response.alt) for image in images]
437 return ImagesResponse.model_construct(
438 438 created=int(time.time()),
439 439 data=images,
440 440 model=last_provider.get("model") if model is None else model,
Modified g4f/client/stubs.py +28 -21
@@ -10,7 +10,7 @@ try:
10 10 except ImportError:
11 11 class BaseModel():
12 12 @classmethod
13 def construct(cls, **data):
13 def model_construct(cls, **data):
14 14 new = cls()
15 15 for key, value in data.items():
16 16 setattr(new, key, value)
@@ -19,6 +19,13 @@ except ImportError:
19 19 def __init__(self, **config):
20 20 pass
21 21
22 class BaseModel(BaseModel):
23 @classmethod
24 def model_construct(cls, **data):
25 if hasattr(super(), "model_construct"):
26 return super().model_construct(**data)
27 return cls.construct(**data)
28
22 29 class ChatCompletionChunk(BaseModel):
23 30 id: str
24 31 object: str
@@ -28,21 +35,21 @@ class ChatCompletionChunk(BaseModel):
28 35 choices: List[ChatCompletionDeltaChoice]
29 36
30 37 @classmethod
31 def construct(
38 def model_construct(
32 39 cls,
33 40 content: str,
34 41 finish_reason: str,
35 42 completion_id: str = None,
36 43 created: int = None
37 44 ):
38 return super().construct(
45 return super().model_construct(
39 46 id=f"chatcmpl-{completion_id}" if completion_id else None,
40 47 object="chat.completion.cunk",
41 48 created=created,
42 49 model=None,
43 50 provider=None,
44 choices=[ChatCompletionDeltaChoice.construct(
45 ChatCompletionDelta.construct(content),
51 choices=[ChatCompletionDeltaChoice.model_construct(
52 ChatCompletionDelta.model_construct(content),
46 53 finish_reason
47 54 )]
48 55 )
@@ -52,8 +59,8 @@ class ChatCompletionMessage(BaseModel):
52 59 content: str
53 60
54 61 @classmethod
55 def construct(cls, content: str):
56 return super().construct(role="assistant", content=content)
62 def model_construct(cls, content: str):
63 return super().model_construct(role="assistant", content=content)
57 64
58 65 class ChatCompletionChoice(BaseModel):
59 66 index: int
@@ -61,8 +68,8 @@ class ChatCompletionChoice(BaseModel):
61 68 finish_reason: str
62 69
63 70 @classmethod
64 def construct(cls, message: ChatCompletionMessage, finish_reason: str):
65 return super().construct(index=0, message=message, finish_reason=finish_reason)
71 def model_construct(cls, message: ChatCompletionMessage, finish_reason: str):
72 return super().model_construct(index=0, message=message, finish_reason=finish_reason)
66 73
67 74 class ChatCompletion(BaseModel):
68 75 id: str
@@ -78,21 +85,21 @@ class ChatCompletion(BaseModel):
78 85 }])
79 86
80 87 @classmethod
81 def construct(
88 def model_construct(
82 89 cls,
83 90 content: str,
84 91 finish_reason: str,
85 92 completion_id: str = None,
86 93 created: int = None
87 94 ):
88 return super().construct(
95 return super().model_construct(
89 96 id=f"chatcmpl-{completion_id}" if completion_id else None,
90 97 object="chat.completion",
91 98 created=created,
92 99 model=None,
93 100 provider=None,
94 choices=[ChatCompletionChoice.construct(
95 ChatCompletionMessage.construct(content),
101 choices=[ChatCompletionChoice.model_construct(
102 ChatCompletionMessage.model_construct(content),
96 103 finish_reason
97 104 )],
98 105 usage={
@@ -107,8 +114,8 @@ class ChatCompletionDelta(BaseModel):
107 114 content: str
108 115
109 116 @classmethod
110 def construct(cls, content: Optional[str]):
111 return super().construct(role="assistant", content=content)
117 def model_construct(cls, content: Optional[str]):
118 return super().model_construct(role="assistant", content=content)
112 119
113 120 class ChatCompletionDeltaChoice(BaseModel):
114 121 index: int
@@ -116,8 +123,8 @@ class ChatCompletionDeltaChoice(BaseModel):
116 123 finish_reason: Optional[str]
117 124
118 125 @classmethod
119 def construct(cls, delta: ChatCompletionDelta, finish_reason: Optional[str]):
120 return super().construct(index=0, delta=delta, finish_reason=finish_reason)
126 def model_construct(cls, delta: ChatCompletionDelta, finish_reason: Optional[str]):
127 return super().model_construct(index=0, delta=delta, finish_reason=finish_reason)
121 128
122 129 class Image(BaseModel):
123 130 url: Optional[str]
@@ -125,8 +132,8 @@ class Image(BaseModel):
125 132 revised_prompt: Optional[str]
126 133
127 134 @classmethod
128 def construct(cls, url: str = None, b64_json: str = None, revised_prompt: str = None):
129 return super().construct(**filter_none(
135 def model_construct(cls, url: str = None, b64_json: str = None, revised_prompt: str = None):
136 return super().model_construct(**filter_none(
130 137 url=url,
131 138 b64_json=b64_json,
132 139 revised_prompt=revised_prompt
@@ -139,10 +146,10 @@ class ImagesResponse(BaseModel):
139 146 created: int
140 147
141 148 @classmethod
142 def construct(cls, data: List[Image], created: int = None, model: str = None, provider: str = None):
149 def model_construct(cls, data: List[Image], created: int = None, model: str = None, provider: str = None):
143 150 if created is None:
144 151 created = int(time())
145 return super().construct(
152 return super().model_construct(
146 153 data=data,
147 154 model=model,
148 155 provider=provider,