gpt4free/g4f/providers/tool_support.py
hlohaus 2befef988b feat: refactor provider create functions to class attributes and update calls
- Added `create_function` and `async_create_function` class attributes with default implementations in `base_provider.py` for `AbstractProvider`, `AsyncProvider`, and `AsyncGeneratorProvider`
- Updated `get_create_function` and `get_async_create_function` methods to return these class attributes
- Replaced calls to `provider.get_create_function()` and `provider.get_async_create_function()` with direct attribute access `provider.create_function` and `provider.async_create_function` across `g4f/__init__.py`, `g4f/client/__init__.py`, `g4f/providers/retry_provider.py`, and `g4f/tools/run_tools.py`
- Removed redundant `get_create_function` and `get_async_create_function` methods from `providers/base_provider.py` and `providers/types.py`
- Ensured all provider response calls now use the class attributes for creating completions asynchronously and synchronously as needed
2025-06-12 12:45:55 +02:00

83 lines
No EOL
2.6 KiB
Python

from __future__ import annotations
import json
from ..typing import AsyncResult, Messages, MediaListType
from ..client.service import get_model_and_provider
from ..client.helper import filter_json
from .base_provider import AsyncGeneratorProvider
from .response import ToolCalls, FinishReason, Usage
class ToolSupportProvider(AsyncGeneratorProvider):
working = True
@classmethod
async def create_async_generator(
cls,
model: str,
messages: Messages,
stream: bool = True,
media: MediaListType = None,
tools: list[str] = None,
response_format: dict = None,
**kwargs
) -> AsyncResult:
provider = None
if ":" in model:
provider, model = model.split(":", 1)
model, provider = get_model_and_provider(
model, provider,
stream, logging=False,
has_images=media is not None
)
if tools is not None:
if len(tools) > 1:
raise ValueError("Only one tool is supported.")
if response_format is None:
response_format = {"type": "json"}
tools = tools.pop()
lines = ["Respone in JSON format."]
properties = tools["function"]["parameters"]["properties"]
properties = {key: value["type"] for key, value in properties.items()}
lines.append(f"Response format: {json.dumps(properties, indent=2)}")
messages = [{"role": "user", "content": "\n".join(lines)}] + messages
finish = None
chunks = []
has_usage = False
async for chunk in provider.async_create_function(
model,
messages,
stream=stream,
media=media,
response_format=response_format,
**kwargs
):
if isinstance(chunk, str):
chunks.append(chunk)
elif isinstance(chunk, Usage):
yield chunk
has_usage = True
elif isinstance(chunk, FinishReason):
finish = chunk
break
else:
yield chunk
if not has_usage:
yield Usage(completion_tokens=len(chunks), total_tokens=len(chunks))
chunks = "".join(chunks)
if tools is not None:
yield ToolCalls([{
"id": "",
"type": "function",
"function": {
"name": tools["function"]["name"],
"arguments": filter_json(chunks)
}
}])
yield chunks
if finish is not None:
yield finish