Traceback (most recent call last):
  File "C:\Users\hp\Downloads\gpt4free_proxy.py", line 68, in chat_completions
    response = g4f.ChatCompletion.create(
               ^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\g4f\__init__.py", line 68, in create
    return result if stream else ''.join([str(chunk) for chunk in result])
                                         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\g4f\providers\base_provider.py", line 223, in create_completion
    yield loop.run_until_complete(await_callback(gen.__anext__))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\asyncio\base_events.py", line 687, in run_until_complete
    return future.result()
           ^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\g4f\providers\base_provider.py", line 52, in await_callback
    return await callback()
           ^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\g4f\Provider\Liaobots.py", line 287, in create_async_generator
    await raise_for_status(response)
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\g4f\requests\raise_for_status.py", line 21, in raise_for_status_async
    raise RateLimitError(f"Response {response.status}: Rate limit reached")
g4f.errors.RateLimitError: Response 402: Rate limit reached

During handling of the above exception, another exception occurred:

Traceback (most recent call last):
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 2190, in wsgi_app
    response = self.full_dispatch_request()
               ^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1486, in full_dispatch_request
    rv = self.handle_user_exception(e)
         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask_cors\extension.py", line 194, in wrapped_function
    return cors_after_request(app.make_response(f(*args, **kwargs)))
                                                ^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1484, in full_dispatch_request
    rv = self.dispatch_request()
         ^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\AppData\Local\Programs\Python\Python312\Lib\site-packages\flask\app.py", line 1469, in dispatch_request
    return self.ensure_sync(self.view_functions[rule.endpoint])(**view_args)
           ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "C:\Users\hp\Downloads\gpt4free_proxy.py", line 87, in chat_completions
    except g4f.exceptions.ProviderError as pe:
           ^^^^^^^^^^^^^^
AttributeError: module 'g4f' has no attribute 'exceptions'

```
import g4f
import asyncio
import argparse
from flask import Flask, request, jsonify, Response, stream_with_context
from flask_cors import CORS
from pyngrok import ngrok
import random
import json
import time

app = Flask(__name__)
CORS(app)

# Available providers
PROVIDERS = [
    g4f.Provider.Liaobots,
]

# Default configuration
DEFAULT_CONFIG = {
    'provider': random.choice(PROVIDERS),
    'model': 'gpt-4-turbo-2024-04-09',
    'max_tokens': 1400,
    'temperature': 0.9,
    'top_p': 1.0,
    'context_size': 100000,
    'system_prompt': (
        "You are a lively, imaginative conversational AI. You respond in an immersive roleplay style, "
        "using *actions* to depict behaviors and emotions, and you speak with a creative flair, often using storytelling elements. "
        "Ensure responses are helpful and accurate, maintaining the roleplay theme while delivering information."
    )
}

# Global configuration (can be updated dynamically)
config = {}

def get_config_with_defaults(request_config):
    """Merge request-specific config with default values."""
    final_config = DEFAULT_CONFIG.copy()
    final_config.update(request_config)
    return final_config

@app.route('/v1/chat/completions', methods=['POST'])
def chat_completions():
    """Handles chat completion requests with structured, clean, and refined responses."""
    data = request.json
    messages = data.get('messages', [])
    request_config = data.get('config', {})

    if not messages:
        return jsonify({'error': 'No messages provided'}), 400

    final_config = get_config_with_defaults(request_config)
    system_prompt = data.get('system', final_config['system_prompt'])
    stream = data.get('stream', False)

    # Prepend system message to maintain the roleplay theme
    messages.insert(0, {'role': 'system', 'content': system_prompt})

    try:
        if stream:
            return Response(stream_with_context(stream_response(messages, final_config)), content_type='text/event-stream')
        else:
            # First refinement - checking the incoming request for consistency
            refined_messages = refine_messages(messages)

            # Generating response
            response = g4f.ChatCompletion.create(
                model=final_config['model'],
                provider=final_config['provider'],
                messages=refined_messages,
                max_tokens=final_config['max_tokens'],
                temperature=final_config['temperature'],
                top_p=final_config['top_p'],
            )

            # Double refinement - polishing the response content
            refined_response = refine_response(response)
            
            # Truncate the response if it exceeds length
            truncated_response = refined_response[:1000] + '...' if len(refined_response) > 1000 else refined_response

            return jsonify({
                'choices': [{'message': {'content': truncated_response}}],
                'usage': {'total_tokens': len(truncated_response.split())}
            })
    except g4f.exceptions.ProviderError as pe:
        return jsonify({'error': f'Provider error: {str(pe)}'}), 500
    except Exception as e:
        return jsonify({'error': str(e)}), 500

def refine_messages(messages):
    """Performs validation and refinement of incoming messages for coherence."""
    refined = []
    for message in messages:
        # Simple validation and trimming for potential malformed input
        if 'content' in message and len(message['content']) > 0:
            refined.append({
                'role': message['role'],
                'content': message['content'].strip()
            })
    return refined

def refine_response(response):
    """Refines the generated response by filtering and restructuring it."""
    # In this case, let's assume response refinement could involve filtering certain phrases
    return response.replace("generic", "creative").replace("boring", "engaging")

def stream_response(messages, config):
    """Yields chunks of response in streaming mode, with roleplay flavor added."""
    try:
        for chunk in g4f.ChatCompletion.create(
            model=config['model'],
            provider=config['provider'],
            messages=messages,
            max_tokens=config['max_tokens'],
            temperature=config['temperature'],
            top_p=config['top_p'],
            stream=True,
        ):
            # Refine chunk and maintain immersive flow with structured responses
            truncated_chunk = chunk[:500] + '...' if len(chunk) > 500 else chunk
            refined_chunk = refine_response(truncated_chunk)
            yield f"data: {json.dumps({'choices': [{'delta': {'content': refined_chunk}}]})}\n\n"
            time.sleep(0.1)  # Simulate streaming delay with a lively pause
    except Exception as e:
        yield f"data: {json.dumps({'error': str(e)})}\n\n"
    finally:
        yield "data: [DONE]\n\n"

@app.route('/config', methods=['GET', 'POST'])
def handle_config():
    """Handles configuration updates and retrievals."""
    global config
    if request.method == 'POST':
        new_config = request.json
        config.update(new_config)
        return jsonify({'message': 'Configuration updated', 'config': config})
    else:
        return jsonify(config)

@app.route('/providers', methods=['GET'])
def list_providers():
    """Lists available providers."""
    return jsonify({'providers': [provider.__name__ for provider in PROVIDERS]})

def start_ngrok(port):
    """Starts ngrok tunnel."""
    public_url = ngrok.connect(port).public_url
    print(f" * ngrok tunnel '{public_url}' -> 'http://localhost:{port}'")
    return public_url

async def check_provider_status():
    """Periodically checks the status of providers."""
    while True:
        for provider in PROVIDERS:
            try:
                response = await g4f.ChatCompletion.create_async(
                    model=config.get('model', DEFAULT_CONFIG['model']),
                    provider=provider,
                    messages=[{"role": "user", "content": "Hello"}],
                    max_tokens=10,
                )
                print(f"Provider {provider.__name__} is working")
            except Exception as e:
                print(f"Provider {provider.__name__} is not working: {str(e)}")
        await asyncio.sleep(3600)  # Check every hour

def main():
    """Main entry point to start the server and ngrok tunnel."""
    parser = argparse.ArgumentParser(description="GPT4Free Advanced Local Reverse Proxy")
    parser.add_argument('--port', type=int, default=5000, help='Port to run the server on')
    args = parser.parse_args()

    # Start ngrok
    public_url = start_ngrok(args.port)

    print(f"Server is running on http://localhost:{args.port}")
    print(f"Public URL: {public_url}")
    print("Available endpoints:")
    print(f"  - Chat completions: {public_url}/v1/chat/completions")
    print(f"  - Configuration: {public_url}/config")
    print(f"  - Providers list: {public_url}/providers")
    print("\nCurrent configuration:")
    for key, value in DEFAULT_CONFIG.items():
        print(f"  {key}: {value}")

    # Start the provider status checking task
    asyncio.get_event_loop().create_task(check_provider_status())

    app.run(port=args.port, threaded=True)

if __name__ == '__main__':
    main()