mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
refactor: update model mappings, error handling, and file utils
- Changed `generate_commit_message` return to `.strip("`").strip()` in `commit.py`
- Added new model mappings in `PollinationsAI.py`, including `gpt-4.1`, `gpt-4.1-mini`, and `deepseek-r1-distill-*`
- Removed `print` debug statement from `PollinationsAI.py` request payload
- Replaced temp file handling in `MarkItDown.py` with `get_tempfile` utility
- Added `get_tempfile` function to `files.py` for consistent tempfile creation
- Added `gpt-4.1` to `text_models` list in `models.py`
- Added `ModelNotSupportedError` to exception handling in `OpenaiChat.py`
- Updated message content creation to use `to_string()` in `OpenaiChat.py`
- Wrapped `get_model()` in try-except to ignore `ModelNotSupportedError` in `OpenaiChat.py`
- Adjusted `convert` endpoint in `api/__init__.py` to accept optional `provider` param
- Refactored `/api/markitdown` to reuse `convert()` handler in `api/__init__.py
This commit is contained in:
parent
dc0705c082
commit
e238ca3a58
7 changed files with 46 additions and 33 deletions
|
|
@ -201,7 +201,7 @@ def generate_commit_message(diff_text: str, model: str = DEFAULT_MODEL) -> Optio
|
|||
spinner = None
|
||||
content.append(chunk.choices[0].delta.content)
|
||||
print(chunk.choices[0].delta.content, end="", flush=True)
|
||||
return "".join(content).strip().strip("`")
|
||||
return "".join(content).strip("`").strip()
|
||||
except Exception as e:
|
||||
# Stop spinner if it's running
|
||||
if 'spinner' in locals() and spinner:
|
||||
|
|
|
|||
|
|
@ -59,6 +59,11 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
|
|||
"gpt-4o-mini": "openai",
|
||||
"gpt-4": "openai-large",
|
||||
"gpt-4o": "openai-large",
|
||||
"gpt-4.1": "openai",
|
||||
"gpt-4.1-nano": "openai",
|
||||
"gpt-4.1-mini": "openai-large",
|
||||
"gpt-4.1-xlarge": "openai-xlarge",
|
||||
"o4-mini": "openai-reasoning",
|
||||
"qwen-2.5-coder-32b": "qwen-coder",
|
||||
"llama-3.3-70b": "llama",
|
||||
"llama-4-scout": "llamascout",
|
||||
|
|
@ -67,10 +72,12 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
|
|||
"llama-3.3-70b": "llama-scaleway",
|
||||
"phi-4": "phi",
|
||||
"deepseek-r1": "deepseek-reasoning-large",
|
||||
"deepseek-r1": "deepseek-reasoning",
|
||||
"deepseek-r1-distill-llama-70b": "deepseek-reasoning-large",
|
||||
"deepseek-r1-distill-qwen-32b": "deepseek-reasoning",
|
||||
"deepseek-v3": "deepseek",
|
||||
"llama-3.2-11b": "llama-vision",
|
||||
"gpt-4o-audio": "openai-audio",
|
||||
"gpt-4o-audio-preview": "openai-audio",
|
||||
|
||||
### Image Models ###
|
||||
"sdxl-turbo": "turbo",
|
||||
|
|
@ -331,7 +338,6 @@ class PollinationsAI(AsyncGeneratorProvider, ProviderModelMixin):
|
|||
"cache": cache,
|
||||
**extra_parameters
|
||||
})
|
||||
print(f"Requesting {url} with data: {data}")
|
||||
async with session.post(url, json=data) as response:
|
||||
await raise_for_status(response)
|
||||
if response.headers["content-type"].startswith("text/plain"):
|
||||
|
|
|
|||
|
|
@ -1,7 +1,5 @@
|
|||
from __future__ import annotations
|
||||
|
||||
import tempfile
|
||||
import shutil
|
||||
import os
|
||||
|
||||
try:
|
||||
|
|
@ -11,6 +9,7 @@ except ImportError:
|
|||
has_markitdown = False
|
||||
|
||||
from ...typing import AsyncResult, Messages, MediaListType
|
||||
from ...tools.files import get_tempfile
|
||||
from ..base_provider import AsyncGeneratorProvider, ProviderModelMixin
|
||||
|
||||
class MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):
|
||||
|
|
@ -26,17 +25,15 @@ class MarkItDown(AsyncGeneratorProvider, ProviderModelMixin):
|
|||
) -> AsyncResult:
|
||||
md = MaItDo()
|
||||
for file, filename in media:
|
||||
text = None
|
||||
try:
|
||||
text = md.convert(file, stream_info=StreamInfo(filename=filename)).text_content
|
||||
text = md.convert(file, stream_info=StreamInfo(filename=filename) if filename else None).text_content
|
||||
except TypeError:
|
||||
# Copy SpooledTemporaryFile to a NamedTemporaryFile
|
||||
copyfile = tempfile.NamedTemporaryFile(suffix=filename, delete=False)
|
||||
shutil.copyfileobj(file, copyfile)
|
||||
copyfile.close()
|
||||
file.close()
|
||||
# Use the NamedTemporaryFile for conversion
|
||||
text = md.convert(copyfile.name, stream_info=StreamInfo(filename=filename)).text_content
|
||||
os.remove(copyfile.name)
|
||||
copyfile = get_tempfile(file, filename)
|
||||
try:
|
||||
text = md.convert(copyfile).text_content
|
||||
finally:
|
||||
os.remove(copyfile)
|
||||
text = text.split("### Audio Transcript:\n")[-1]
|
||||
if text:
|
||||
yield text
|
||||
|
|
@ -23,11 +23,11 @@ from ...requests.raise_for_status import raise_for_status
|
|||
from ...requests import StreamSession
|
||||
from ...requests import get_nodriver
|
||||
from ...image import ImageRequest, to_image, to_bytes, is_accepted_format
|
||||
from ...errors import MissingAuthError, NoValidHarFileError
|
||||
from ...errors import MissingAuthError, NoValidHarFileError, ModelNotSupportedError
|
||||
from ...providers.response import JsonConversation, FinishReason, SynthesizeData, AuthResult, ImageResponse, ImagePreview
|
||||
from ...providers.response import Sources, TitleGeneration, RequestLogin, Reasoning
|
||||
from ...tools.media import merge_media
|
||||
from ..helper import format_cookies, format_image_prompt
|
||||
from ..helper import format_cookies, format_image_prompt, to_string
|
||||
from ..openai.models import default_model, default_image_model, models, image_models, text_models
|
||||
from ..openai.har_file import get_request_config
|
||||
from ..openai.har_file import RequestConfig, arkReq, arkose_url, start_url, conversation_url, backend_url, backend_anon_url
|
||||
|
|
@ -221,7 +221,7 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
|
|||
messages = [{
|
||||
"id": str(uuid.uuid4()),
|
||||
"author": {"role": message["role"]},
|
||||
"content": {"content_type": "text", "parts": [message["content"]]},
|
||||
"content": {"content_type": "text", "parts": [to_string(message["content"])]},
|
||||
"metadata": {"serialization_metadata": {"custom_symbol_offsets": []}, **({"system_hints": system_hints} if system_hints else {})},
|
||||
"create_time": time.time(),
|
||||
} for message in messages]
|
||||
|
|
@ -356,7 +356,10 @@ class OpenaiChat(AsyncAuthedProvider, ProviderModelMixin):
|
|||
except Exception as e:
|
||||
debug.error("OpenaiChat: Upload image failed")
|
||||
debug.error(e)
|
||||
model = cls.get_model(model)
|
||||
try:
|
||||
model = cls.get_model(model)
|
||||
except ModelNotSupportedError:
|
||||
pass
|
||||
if conversation is None:
|
||||
conversation = Conversation(None, str(uuid.uuid4()), getattr(auth_result, "cookies", {}).get("oai-did"))
|
||||
else:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
default_model = "auto"
|
||||
default_image_model = "dall-e-3"
|
||||
image_models = [default_image_model]
|
||||
text_models = [default_model, "gpt-4", "gpt-4.5", "gpt-4o", "gpt-4o-mini", "o1", "o1-preview", "o1-mini", "o3-mini", "o3-mini-high"]
|
||||
text_models = [default_model, "gpt-4", "gpt-4.1", "gpt-4.5", "gpt-4o", "gpt-4o-mini", "o1", "o1-preview", "o1-mini", "o3-mini", "o3-mini-high"]
|
||||
vision_models = text_models
|
||||
models = text_models + image_models
|
||||
|
|
@ -494,28 +494,20 @@ class Api:
|
|||
}
|
||||
@self.app.post("/v1/audio/transcriptions", responses=responses)
|
||||
@self.app.post("/api/{path_provider}/audio/transcriptions", responses=responses)
|
||||
@self.app.post("/api/markitdown", responses=responses)
|
||||
async def convert(
|
||||
file: UploadFile,
|
||||
model: Annotated[Optional[str], Form()] = None,
|
||||
provider: Annotated[Optional[str], Form()] = "MarkItDown",
|
||||
path_provider: str = None,
|
||||
prompt: Annotated[Optional[str], Form()] = "Transcribe this audio",
|
||||
api_key: Annotated[Optional[str], Form()] = None,
|
||||
credentials: Annotated[HTTPAuthorizationCredentials, Depends(Api.security)] = None
|
||||
model: Annotated[Optional[str], Form()] = None,
|
||||
provider: Annotated[Optional[str], Form()] = None,
|
||||
prompt: Annotated[Optional[str], Form()] = "Transcribe this audio"
|
||||
):
|
||||
if credentials is not None and credentials.credentials != "secret":
|
||||
api_key = credentials.credentials
|
||||
try:
|
||||
response = await self.client.chat.completions.create(
|
||||
messages=prompt,
|
||||
model=model,
|
||||
provider=provider if path_provider is None else path_provider,
|
||||
media=[[file.file, file.filename]],
|
||||
modalities=["text"],
|
||||
**filter_none(
|
||||
provider=provider if path_provider is None else path_provider,
|
||||
api_key=api_key
|
||||
)
|
||||
modalities=["text"]
|
||||
)
|
||||
return {"text": response.choices[0].message.content, "model": response.model, "provider": response.provider}
|
||||
except (ModelNotFoundError, ProviderNotFoundError) as e:
|
||||
|
|
@ -528,6 +520,12 @@ class Api:
|
|||
logger.exception(e)
|
||||
return ErrorResponse.from_exception(e, None, HTTP_500_INTERNAL_SERVER_ERROR)
|
||||
|
||||
@self.app.post("/api/markitdown", responses=responses)
|
||||
async def markitdown(
|
||||
file: UploadFile
|
||||
):
|
||||
return await convert(file, "MarkItDown")
|
||||
|
||||
responses = {
|
||||
HTTP_200_OK: {"class": FileResponse},
|
||||
HTTP_401_UNAUTHORIZED: {"model": ErrorResponseModel},
|
||||
|
|
|
|||
|
|
@ -13,6 +13,8 @@ import zipfile
|
|||
import asyncio
|
||||
import hashlib
|
||||
import base64
|
||||
import tempfile
|
||||
import shutil
|
||||
|
||||
try:
|
||||
import PyPDF2
|
||||
|
|
@ -579,3 +581,10 @@ async def get_async_streaming(bucket_dir: str, delete_files = False, refine_chun
|
|||
if event_stream:
|
||||
yield f'data: {json.dumps({"error": {"message": str(e)}})}\n\n'
|
||||
raise e
|
||||
|
||||
def get_tempfile(file, suffix):
|
||||
copyfile = tempfile.NamedTemporaryFile(suffix=suffix, delete=False)
|
||||
shutil.copyfileobj(file, copyfile)
|
||||
copyfile.close()
|
||||
file.close()
|
||||
return copyfile.name
|
||||
Loading…
Add table
Add a link
Reference in a new issue