summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--g4f/Provider/Ai4Chat.py3
-rw-r--r--g4f/Provider/Mhystical.py6
-rw-r--r--g4f/Provider/you/har_file.py8
-rw-r--r--g4f/__init__.py9
-rw-r--r--g4f/api/__init__.py8
-rw-r--r--g4f/api/_logging.py36
-rw-r--r--g4f/gui/server/api.py6
-rw-r--r--g4f/image.py11
-rw-r--r--g4f/providers/base_provider.py2
-rw-r--r--requirements.txt1
-rw-r--r--setup.py2
11 files changed, 56 insertions, 36 deletions
diff --git a/g4f/Provider/Ai4Chat.py b/g4f/Provider/Ai4Chat.py
index 9f9874bb..56b47e5c 100644
--- a/g4f/Provider/Ai4Chat.py
+++ b/g4f/Provider/Ai4Chat.py
@@ -9,6 +9,7 @@ from ..typing import AsyncResult, Messages
from .base_provider import AsyncGeneratorProvider, ProviderModelMixin
from .helper import format_prompt
+logger = logging.getLogger(__name__)
class Ai4Chat(AsyncGeneratorProvider, ProviderModelMixin):
label = "AI4Chat"
@@ -84,5 +85,5 @@ class Ai4Chat(AsyncGeneratorProvider, ProviderModelMixin):
yield clean_message
except Exception as e:
- logging.exception("Error while calling AI 4Chat API: %s", e)
+ logger.exception("Error while calling AI 4Chat API: %s", e)
yield f"Error: {e}"
diff --git a/g4f/Provider/Mhystical.py b/g4f/Provider/Mhystical.py
index 44b32604..2aa98ebc 100644
--- a/g4f/Provider/Mhystical.py
+++ b/g4f/Provider/Mhystical.py
@@ -18,6 +18,8 @@ from .helper import format_prompt
"""
+logger = logging.getLogger(__name__)
+
class Mhystical(AsyncGeneratorProvider, ProviderModelMixin):
url = "https://api.mhystical.cc"
api_endpoint = "https://api.mhystical.cc/v1/completions"
@@ -84,5 +86,5 @@ class Mhystical(AsyncGeneratorProvider, ProviderModelMixin):
message_content = json_response["choices"][0]["message"]["content"]
return message_content
except (KeyError, IndexError, json.JSONDecodeError) as e:
- logging.error("Error parsing response: %s", e)
- return "Error: Failed to parse response from API." \ No newline at end of file
+ logger.error("Error parsing response: %s", e)
+ return "Error: Failed to parse response from API."
diff --git a/g4f/Provider/you/har_file.py b/g4f/Provider/you/har_file.py
index 71d741fd..40bf3882 100644
--- a/g4f/Provider/you/har_file.py
+++ b/g4f/Provider/you/har_file.py
@@ -11,7 +11,7 @@ from ...cookies import get_cookies_dir
from ...errors import MissingRequirementsError
from ... import debug
-logging.basicConfig(level=logging.ERROR)
+logger = logging.getLogger(__name__)
class NoValidHarFileError(Exception):
...
@@ -81,14 +81,14 @@ async def get_telemetry_ids(proxy: str = None) -> list:
return [await create_telemetry_id(proxy)]
except NoValidHarFileError as e:
if debug.logging:
- logging.error(e)
+ logger.error(e)
try:
from nodriver import start
except ImportError:
raise MissingRequirementsError('Add .har file from you.com or install "nodriver" package | pip install -U nodriver')
if debug.logging:
- logging.error('Getting telemetry_id for you.com with nodriver')
+ logger.error('Getting telemetry_id for you.com with nodriver')
browser = page = None
try:
@@ -112,4 +112,4 @@ async def get_telemetry_ids(proxy: str = None) -> list:
await browser.stop()
except Exception as e:
if debug.logging:
- logging.error(e)
+ logger.error(e)
diff --git a/g4f/__init__.py b/g4f/__init__.py
index d77fe760..f59a1446 100644
--- a/g4f/__init__.py
+++ b/g4f/__init__.py
@@ -1,6 +1,7 @@
from __future__ import annotations
import os
+import logging
from . import debug, version
from .models import Model
@@ -12,6 +13,14 @@ from .providers.types import ProviderType
from .providers.base_provider import AsyncGeneratorProvider
from .client.service import get_model_and_provider, get_last_provider
+#Configure "g4f" logger
+logger = logging.getLogger(__name__)
+log_handler = logging.StreamHandler()
+log_handler.setFormatter(logging.Formatter(logging.BASIC_FORMAT))
+logger.addHandler(log_handler)
+
+logger.setLevel(logging.ERROR)
+
class ChatCompletion:
@staticmethod
def create(model : Union[Model, str],
diff --git a/g4f/api/__init__.py b/g4f/api/__init__.py
index b9591b20..e7f87260 100644
--- a/g4f/api/__init__.py
+++ b/g4f/api/__init__.py
@@ -22,6 +22,8 @@ from g4f.client import Client, ChatCompletion, ChatCompletionChunk, ImagesRespon
from g4f.typing import Messages
from g4f.cookies import read_cookie_files
+logger = logging.getLogger(__name__)
+
def create_app(g4f_api_key: str = None):
app = FastAPI()
@@ -204,14 +206,14 @@ class Api:
except GeneratorExit:
pass
except Exception as e:
- logging.exception(e)
+ logger.exception(e)
yield f'data: {format_exception(e, config)}\n\n'
yield "data: [DONE]\n\n"
return StreamingResponse(streaming(), media_type="text/event-stream")
except Exception as e:
- logging.exception(e)
+ logger.exception(e)
return Response(content=format_exception(e, config), status_code=500, media_type="application/json")
@self.app.post("/v1/images/generate")
@@ -226,7 +228,7 @@ class Api:
response_data = [{"url": image.url, "b64_json": image.b64_json} for image in response.data]
return JSONResponse({"data": response_data})
except Exception as e:
- logging.exception(e)
+ logger.exception(e)
return Response(content=format_exception(e, config), status_code=500, media_type="application/json")
@self.app.post("/v1/completions")
diff --git a/g4f/api/_logging.py b/g4f/api/_logging.py
index e91dff76..884d7529 100644
--- a/g4f/api/_logging.py
+++ b/g4f/api/_logging.py
@@ -1,6 +1,6 @@
import sys,logging
-from loguru import logger
+#from loguru import logger
def __exception_handle(e_type, e_value, e_traceback):
if issubclass(e_type, KeyboardInterrupt):
@@ -9,24 +9,24 @@ def __exception_handle(e_type, e_value, e_traceback):
sys.__excepthook__(e_type, e_value, e_traceback)
-class __InterceptHandler(logging.Handler):
- def emit(self, record):
- try:
- level = logger.level(record.levelname).name
- except ValueError:
- level = record.levelno
-
- frame, depth = logging.currentframe(), 2
- while frame.f_code.co_filename == logging.__file__:
- frame = frame.f_back
- depth += 1
-
- logger.opt(depth=depth, exception=record.exc_info).log(
- level, record.getMessage()
- )
+#class __InterceptHandler(logging.Handler):
+# def emit(self, record):
+# try:
+# level = logger.level(record.levelname).name
+# except ValueError:
+# level = record.levelno
+#
+# frame, depth = logging.currentframe(), 2
+# while frame.f_code.co_filename == logging.__file__:
+# frame = frame.f_back
+# depth += 1
+
+# logger.opt(depth=depth, exception=record.exc_info).log(
+# level, record.getMessage()
+# )
def hook_except_handle():
sys.excepthook = __exception_handle
-def hook_logging(**kwargs):
- logging.basicConfig(handlers=[__InterceptHandler()], **kwargs)
+#def hook_logging(**kwargs):
+# logging.basicConfig(handlers=[__InterceptHandler()], **kwargs)
diff --git a/g4f/gui/server/api.py b/g4f/gui/server/api.py
index 7aac650a..dafcb5d4 100644
--- a/g4f/gui/server/api.py
+++ b/g4f/gui/server/api.py
@@ -19,6 +19,8 @@ from g4f.Provider import ProviderType, __providers__, __map__
from g4f.providers.base_provider import ProviderModelMixin, FinishReason
from g4f.providers.conversation import BaseConversation
+logger = logging.getLogger(__name__)
+
# Define the directory for generated images
images_dir = "./generated_images"
@@ -155,7 +157,7 @@ class Api:
conversations[provider][conversation_id] = chunk
yield self._format_json("conversation", conversation_id)
elif isinstance(chunk, Exception):
- logging.exception(chunk)
+ logger.exception(chunk)
yield self._format_json("message", get_error_message(chunk))
elif isinstance(chunk, ImagePreview):
yield self._format_json("preview", chunk.to_string())
@@ -165,7 +167,7 @@ class Api:
elif not isinstance(chunk, FinishReason):
yield self._format_json("content", str(chunk))
except Exception as e:
- logging.exception(e)
+ logger.exception(e)
yield self._format_json('error', get_error_message(e))
async def _copy_images(self, images: list[str], cookies: Optional[Cookies] = None):
diff --git a/g4f/image.py b/g4f/image.py
index 6561b83a..556ec43d 100644
--- a/g4f/image.py
+++ b/g4f/image.py
@@ -23,6 +23,11 @@ EXTENSIONS_MAP: dict[str, str] = {
"image/webp": "webp",
}
+def fix_url(url:str) -> str:
+ """ replace ' ' by '+' (to be markdown compliant)"""
+ return url.replace(" ","+")
+
+
def to_image(image: ImageType, is_svg: bool = False) -> Image:
"""
Converts the input image to a PIL Image object.
@@ -212,12 +217,12 @@ def format_images_markdown(images: Union[str, list], alt: str, preview: Union[st
str: The formatted markdown string.
"""
if isinstance(images, str):
- result = f"[![{alt}]({preview.replace('{image}', images) if preview else images})]({images})"
+ result = f"[![{alt}]({fix_url(preview.replace('{image}', images) if preview else images)})]({fix_url(images)})"
else:
if not isinstance(preview, list):
preview = [preview.replace('{image}', image) if preview else image for image in images]
result = "\n".join(
- f"[![#{idx+1} {alt}]({preview[idx]})]({image})"
+ f"[![#{idx+1} {alt}]({fix_url(preview[idx])})]({fix_url(image)})"
#f'[<img src="{preview[idx]}" width="200" alt="#{idx+1} {alt}">]({image})'
for idx, image in enumerate(images)
)
@@ -302,4 +307,4 @@ class ImageRequest:
self.options = options
def get(self, key: str):
- return self.options.get(key) \ No newline at end of file
+ return self.options.get(key)
diff --git a/g4f/providers/base_provider.py b/g4f/providers/base_provider.py
index a03dcbba..5d48f2e0 100644
--- a/g4f/providers/base_provider.py
+++ b/g4f/providers/base_provider.py
@@ -248,7 +248,7 @@ class AsyncGeneratorProvider(AsyncProvider):
str: The created result as a string.
"""
return "".join([
- chunk async for chunk in cls.create_async_generator(model, messages, stream=False, **kwargs)
+ str(chunk) async for chunk in cls.create_async_generator(model, messages, stream=False, **kwargs)
if not isinstance(chunk, (Exception, FinishReason))
])
diff --git a/requirements.txt b/requirements.txt
index 1f75adf7..1a014bac 100644
--- a/requirements.txt
+++ b/requirements.txt
@@ -8,7 +8,6 @@ PyExecJS
duckduckgo-search>=5.0
nest_asyncio
werkzeug
-loguru
pillow
platformdirs
fastapi
diff --git a/setup.py b/setup.py
index e81ee4b0..48bbede9 100644
--- a/setup.py
+++ b/setup.py
@@ -39,7 +39,7 @@ EXTRA_REQUIRE = {
"pillow", # image
"cairosvg", # svg image
"werkzeug", "flask", # gui
- "loguru", "fastapi", # api
+ "fastapi", # api
"uvicorn", "nest_asyncio", # api
"pycryptodome" # openai
],