mirror of
https://github.com/xtekky/gpt4free.git
synced 2025-12-06 02:30:41 -08:00
refactor: reorganize providers and update model configurations
- Rename DeepInfraChat to DeepInfra across all files - Move DeepInfra from needs_auth to main Provider directory - Rename LMArenaBeta to LMArena throughout codebase - Move search-related providers to new search subdirectory (GoogleSearch, SearXNG, YouTube) - Move deprecated providers to not_working directory (Free2GPT, LegacyLMArena, PenguinAI, ImageLabs, har) - Add new Mintlify provider with custom AI assistant implementation - Update Anthropic provider with Claude 4 models and Opus 4.1 parameter handling - Update Grok provider with Grok 4 models and improved streaming support - Update GithubCopilot with expanded model list including o3-mini, o4-mini, gpt-5 previews - Update LambdaChat default model from deepseek-r1 to deepseek-llama3.3-70b - Update TeachAnything default model from gemini-1.5-pro to gemma - Remove DeepInfra from needs_auth directory - Update all model_map references from DeepInfraChat to DeepInfra - Update all model_map references from LMArenaBeta to LMArena - Add beta_headers support to Anthropic for special features - Improve Mintlify provider with system prompt handling and streaming - Update model configurations in models.py to reflect provider changes
This commit is contained in:
parent
2cf62a8e63
commit
9bac34fc88
26 changed files with 641 additions and 517 deletions
|
|
@ -36,9 +36,39 @@ class Grok(AsyncAuthedProvider, ProviderModelMixin):
|
|||
needs_auth = True
|
||||
working = True
|
||||
|
||||
default_model = "grok-3"
|
||||
models = [default_model, "grok-3-thinking", "grok-2"]
|
||||
model_aliases = {"grok-3-r1": "grok-3-thinking"}
|
||||
# Updated to Grok 4 as default
|
||||
default_model = "grok-4"
|
||||
|
||||
# Updated model list with latest Grok 4 and 3 models
|
||||
models = [
|
||||
# Grok 4 models
|
||||
"grok-4",
|
||||
"grok-4-heavy",
|
||||
"grok-4-reasoning",
|
||||
|
||||
# Grok 3 models
|
||||
"grok-3",
|
||||
"grok-3-reasoning",
|
||||
"grok-3-mini",
|
||||
"grok-3-mini-reasoning",
|
||||
|
||||
# Legacy Grok 2 (still supported)
|
||||
"grok-2",
|
||||
"grok-2-image",
|
||||
|
||||
# Latest aliases
|
||||
"grok-latest",
|
||||
]
|
||||
|
||||
model_aliases = {
|
||||
# Grok 3 aliases
|
||||
"grok-3-thinking": "grok-3-reasoning",
|
||||
"grok-3-r1": "grok-3-reasoning",
|
||||
"grok-3-mini-thinking": "grok-3-mini-reasoning",
|
||||
|
||||
# Latest alias
|
||||
"grok": "grok-latest",
|
||||
}
|
||||
|
||||
@classmethod
|
||||
async def on_auth_async(cls, proxy: str = None, **kwargs) -> AsyncIterator:
|
||||
|
|
@ -79,14 +109,35 @@ class Grok(AsyncAuthedProvider, ProviderModelMixin):
|
|||
|
||||
@classmethod
|
||||
async def _prepare_payload(cls, model: str, message: str) -> Dict[str, Any]:
|
||||
# Map model names to API model names
|
||||
api_model = "grok-latest"
|
||||
|
||||
if model in ["grok-4", "grok-4-heavy", "grok-4-reasoning"]:
|
||||
api_model = model
|
||||
elif model == "grok-3":
|
||||
api_model = "grok-3"
|
||||
elif model in ["grok-3-mini", "grok-3-mini-reasoning"]:
|
||||
api_model = "grok-3-mini"
|
||||
elif model == "grok-2":
|
||||
api_model = "grok-2"
|
||||
|
||||
# Check if it's a reasoning model
|
||||
is_reasoning = model.endswith("-reasoning") or model.endswith("-thinking") or model.endswith("-r1")
|
||||
|
||||
# Enable Big Brain mode for heavy models
|
||||
enable_big_brain = "heavy" in model or "big-brain" in model
|
||||
|
||||
# Enable DeepSearch for Grok 3+ models
|
||||
enable_deep_search = not model.startswith("grok-2")
|
||||
|
||||
return {
|
||||
"temporary": True,
|
||||
"modelName": "grok-latest" if model == "grok-2" else "grok-3",
|
||||
"modelName": api_model,
|
||||
"message": message,
|
||||
"fileAttachments": [],
|
||||
"imageAttachments": [],
|
||||
"disableSearch": False,
|
||||
"enableImageGeneration": True,
|
||||
"enableImageGeneration": model == "grok-2-image" or model == "grok-4",
|
||||
"returnImageBytes": False,
|
||||
"returnRawGrokInXaiRequest": False,
|
||||
"enableImageStreaming": True,
|
||||
|
|
@ -97,8 +148,11 @@ class Grok(AsyncAuthedProvider, ProviderModelMixin):
|
|||
"isPreset": False,
|
||||
"sendFinalMetadata": True,
|
||||
"customInstructions": "",
|
||||
"deepsearchPreset": "",
|
||||
"isReasoning": model.endswith("-thinking") or model.endswith("-r1"),
|
||||
"deepsearchPreset": "enabled" if enable_deep_search else "",
|
||||
"isReasoning": is_reasoning,
|
||||
"enableBigBrain": enable_big_brain,
|
||||
"enableLiveSearch": False, # Real-time search for Grok 4
|
||||
"contextWindow": 256000 if model.startswith("grok-4") else 131072, # 256k for Grok 4, 128k for others
|
||||
}
|
||||
|
||||
@classmethod
|
||||
|
|
@ -112,38 +166,78 @@ class Grok(AsyncAuthedProvider, ProviderModelMixin):
|
|||
) -> AsyncResult:
|
||||
conversation_id = None if conversation is None else conversation.conversation_id
|
||||
prompt = format_prompt(messages) if conversation_id is None else get_last_user_message(messages)
|
||||
|
||||
async with StreamSession(
|
||||
**auth_result.get_dict()
|
||||
) as session:
|
||||
payload = await cls._prepare_payload(model, prompt)
|
||||
|
||||
# Add voice mode support flag (for future use)
|
||||
if kwargs.get("enable_voice", False):
|
||||
payload["enableVoiceMode"] = True
|
||||
|
||||
if conversation_id is None:
|
||||
url = f"{cls.conversation_url}/new"
|
||||
else:
|
||||
url = f"{cls.conversation_url}/{conversation_id}/responses"
|
||||
|
||||
async with session.post(url, json=payload, headers={"x-xai-request-id": str(uuid.uuid4())}) as response:
|
||||
if response.status == 403:
|
||||
raise MissingAuthError("Invalid secrets")
|
||||
auth_result.cookies = merge_cookies(auth_result.cookies, response)
|
||||
await raise_for_status(response)
|
||||
|
||||
thinking_duration = None
|
||||
deep_search_active = False
|
||||
|
||||
async for line in response.iter_lines():
|
||||
if line:
|
||||
try:
|
||||
json_data = json.loads(line)
|
||||
result = json_data.get("result", {})
|
||||
|
||||
if conversation_id is None:
|
||||
conversation_id = result.get("conversation", {}).get("conversationId")
|
||||
|
||||
response_data = result.get("response", {})
|
||||
|
||||
# Handle DeepSearch status
|
||||
deep_search = response_data.get("deepSearchStatus")
|
||||
if deep_search:
|
||||
if not deep_search_active:
|
||||
deep_search_active = True
|
||||
yield Reasoning(status="🔍 Deep searching...")
|
||||
if deep_search.get("completed"):
|
||||
deep_search_active = False
|
||||
yield Reasoning(status="Deep search completed")
|
||||
|
||||
# Handle image generation (Aurora for Grok 3+)
|
||||
image = response_data.get("streamingImageGenerationResponse", None)
|
||||
if image is not None:
|
||||
yield ImagePreview(f'{cls.assets_url}/{image["imageUrl"]}', "", {"cookies": auth_result.cookies, "headers": auth_result.headers})
|
||||
image_url = image.get("imageUrl")
|
||||
if image_url:
|
||||
yield ImagePreview(
|
||||
f'{cls.assets_url}/{image_url}',
|
||||
"",
|
||||
{"cookies": auth_result.cookies, "headers": auth_result.headers}
|
||||
)
|
||||
|
||||
# Handle text tokens
|
||||
token = response_data.get("token", result.get("token"))
|
||||
is_thinking = response_data.get("isThinking", result.get("isThinking"))
|
||||
|
||||
if token:
|
||||
if is_thinking:
|
||||
if thinking_duration is None:
|
||||
thinking_duration = time.time()
|
||||
yield Reasoning(status="🤔 Is thinking...")
|
||||
# Different status for different models
|
||||
if "grok-4" in model:
|
||||
status = "🧠 Grok 4 is processing..."
|
||||
elif "big-brain" in payload and payload["enableBigBrain"]:
|
||||
status = "🧠 Big Brain mode active..."
|
||||
else:
|
||||
status = "🤔 Is thinking..."
|
||||
yield Reasoning(status=status)
|
||||
yield Reasoning(token)
|
||||
else:
|
||||
if thinking_duration is not None:
|
||||
|
|
@ -152,13 +246,31 @@ class Grok(AsyncAuthedProvider, ProviderModelMixin):
|
|||
thinking_duration = None
|
||||
yield Reasoning(status=status)
|
||||
yield token
|
||||
|
||||
# Handle generated images
|
||||
generated_images = response_data.get("modelResponse", {}).get("generatedImageUrls", None)
|
||||
if generated_images:
|
||||
yield ImageResponse([f'{cls.assets_url}/{image}' for image in generated_images], "", {"cookies": auth_result.cookies, "headers": auth_result.headers})
|
||||
yield ImageResponse(
|
||||
[f'{cls.assets_url}/{image}' for image in generated_images],
|
||||
"",
|
||||
{"cookies": auth_result.cookies, "headers": auth_result.headers}
|
||||
)
|
||||
|
||||
# Handle title generation
|
||||
title = result.get("title", {}).get("newTitle", "")
|
||||
if title:
|
||||
yield TitleGeneration(title)
|
||||
|
||||
# Handle tool usage information (Grok 4)
|
||||
tool_usage = response_data.get("toolUsage")
|
||||
if tool_usage:
|
||||
tools_used = tool_usage.get("toolsUsed", [])
|
||||
if tools_used:
|
||||
yield Reasoning(status=f"Used tools: {', '.join(tools_used)}")
|
||||
|
||||
except json.JSONDecodeError:
|
||||
continue
|
||||
# if conversation_id is not None:
|
||||
# yield Conversation(conversation_id)
|
||||
|
||||
# Return conversation ID for continuation
|
||||
if conversation_id is not None and kwargs.get("return_conversation", False):
|
||||
yield Conversation(conversation_id)
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue