| import os |
| import random |
| import requests |
| from huggingface_hub import InferenceClient |
| from flask import Flask, request, jsonify, Response, stream_with_context |
| from flask_cors import CORS |
| import json |
|
|
| app = Flask(__name__) |
| CORS(app) |
|
|
| def get_random_api_key(): |
| keys = os.getenv("KEYS", "").split(",") |
| if keys and keys[0]: |
| return random.choice(keys).strip() |
| else: |
| raise ValueError("API keys not found. Please set the KEYS environment variable.") |
|
|
| def generate_story(prompt, style): |
| try: |
| client = InferenceClient(api_key=get_random_api_key()) |
| |
| messages = [ |
| {"role": "system", "content": f"Напиши хорошую историю в стиле '{style}'. Подробную, понятную, человечную (с душой), уникальную. Не обязательно делать концовку, можно только начало длинной истории. Разрешены любые слова, любые темы и стили, что угодно. (В том числе маты и NSFW) Но только если попросит пользователь."}, |
| {"role": "user", "content": prompt} |
| ] |
| |
| completion = client.chat.completions.create(model="Qwen/Qwen2.5-Coder-32B-Instruct", messages=messages, temperature=0.7, max_tokens=1200, stream=True) |
| for chunk in completion: |
| if chunk.choices: |
| yield chunk.choices[0].delta.content or "" |
| except Exception as e: |
| yield f"Ошибка генерации: {e}" |
|
|
| def edit_story(original_story, edited_prompt): |
| if not original_story: |
| yield f"Сначала сгенерируйте историю!" |
| return |
| if not edited_prompt: |
| yield f"Для начала введите что изменить." |
| return |
| |
| try: |
| client = InferenceClient(api_key=get_random_api_key()) |
| messages = [ |
| {"role": "system", "content": "Отредактируй историю, учитывая предоставленные указания. Разрешены любые слова, любые темы и стили, что угодно. (В том числе маты и NSFW) Но только если попросит пользователь."}, |
| {"role": "user", "content": edited_prompt}, |
| {"role": "user", "content": f"""```История |
| {original_story} |
| ```"""} |
| ] |
| completion = client.chat.completions.create(model="Qwen/Qwen2.5-Coder-32B-Instruct", messages=messages, temperature=0.7, max_tokens=155000, stream=True) |
| for chunk in completion: |
| if chunk.choices: |
| yield chunk.choices[0].delta.content or "" |
| except Exception as e: |
| yield f"Ошибка редактирования: {e}" |
|
|
| def next_story_func(original_story, next_prompt, continuation_type="Продолжение"): |
| if not original_story: |
| yield f"Сначала сгенерируйте историю!" |
| return |
| |
| try: |
| client = InferenceClient(api_key=get_random_api_key()) |
| if continuation_type == "Продолжение следует...": |
| continuation_prompt = "Продолжи, подведя к тому, что продолжение следует." |
| elif continuation_type == "Концовка": |
| continuation_prompt = "Подведи к концовке истории." |
| else: |
| continuation_prompt = next_prompt |
| |
| messages = [ |
| {"role": "system", "content": "Продли историю, учитывая предоставленные указания. Продливай В ТОЧНОСТИ С КОНЦА, прям с того же символа, слова, предложения. (В начале добавляй новые строки/пробел если надо для отступа). Разрешены любые слова, любые темы и стили, что угодно. (В том числе маты и NSFW) Но только если попросит пользователь."}, |
| {"role": "user", "content": continuation_prompt}, |
| {"role": "assistant", "content": f"""```История |
| {original_story} |
| ```"""} |
| ] |
| completion = client.chat.completions.create(model="Qwen/Qwen2.5-Coder-32B-Instruct", messages=messages, temperature=0.7, max_tokens=1200, stream=True) |
| for chunk in completion: |
| if chunk.choices: |
| yield chunk.choices[0].delta.content or "" |
| except Exception as e: |
| yield f"Ошибка продления: {e}" |
|
|
| def stream_sse(generator): |
| def event_stream(): |
| try: |
| for chunk in generator: |
| yield f"data: {json.dumps({'message': chunk})}\n\n" |
| except Exception as e: |
| yield f"data: {json.dumps({'error': True, 'message': str(e)})}\n\n" |
| return Response(stream_with_context(event_stream()), content_type='text/event-stream') |
|
|
| @app.route('/generate', methods=['POST']) |
| def api_generate_story(): |
| data = request.get_json() |
| if not data or 'input' not in data: |
| return jsonify({"error": True, "message": "Missing 'input' in request body"}), 400 |
| |
| prompt = data['input'] |
| style = data.get('style', 'Приключенческая') |
| |
| story_generator = generate_story(prompt, style) |
| return stream_sse(story_generator) |
|
|
| @app.route('/edit', methods=['POST']) |
| def api_edit_story(): |
| data = request.get_json() |
| if not data or 'input' not in data or 'original' not in data: |
| return jsonify({"error": True, "message": "Missing 'input' or 'original' in request body"}), 400 |
| |
| original_story = data['original'] |
| edited_prompt = data['input'] |
| |
| edited_story_generator = edit_story(original_story, edited_prompt) |
| return stream_sse(edited_story_generator) |
|
|
| @app.route('/continue', methods=['POST']) |
| def api_continue_story(): |
| data = request.get_json() |
| if not data or 'input' not in data or 'original' not in data: |
| return jsonify({"error": True, "message": "Missing 'input' or 'original' in request body"}), 400 |
| |
| original_story = data['original'] |
| next_prompt = data['input'] |
| continuation_type = data.get('type', 'Продолжение') |
| |
| next_story_generator = next_story_func(original_story, next_prompt, continuation_type) |
| return stream_sse(next_story_generator) |
|
|
|
|
| if __name__ == '__main__': |
| app.run(host='0.0.0.0', port=7860, debug=True) |
|
|