Spaces:
Sleeping
Sleeping
File size: 8,662 Bytes
4b4d390 | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 | import os
import requests
import random
import logging
import json
try:
from PyPDF2 import PdfReader
except ImportError:
# Fallback for Docker environment
from pypdf import PdfReader
# Set up logging
logging.basicConfig(level=logging.INFO)
logger = logging.getLogger(__name__)
# Check for environment variable or use a default value for testing
def get_api_key():
api_key = os.environ.get('DEEPSEEK_API_KEY')
if not api_key:
logger.warning("No DEEPSEEK_API_KEY environment variable found. Using mock responses.")
return api_key
# Mock evaluation result for testing
def get_mock_evaluation(story_excerpt):
# Use a short excerpt of the story in the evaluation to make it look personalized
story_start = story_excerpt[:100].replace("\n", " ").strip()
if len(story_start) > 50:
story_start = story_start[:50] + "..."
# Generate random scores but keep them reasonable
unity_score = random.randint(6, 9)
characters_score = random.randint(6, 9)
decisive_moment_score = random.randint(7, 10)
language_score = random.randint(5, 9)
time_place_score = random.randint(6, 9)
plot_score = random.randint(7, 10)
ending_score = random.randint(6, 10)
message_score = random.randint(6, 9)
total_score = unity_score + characters_score + decisive_moment_score + language_score + \
time_place_score + plot_score + ending_score + message_score
# Mock evaluation text
return {
"evaluation": f"""📋 التقييم:
وحدة الحدث: {unity_score}/10
القصة تدور حول حدث رئيسي بشكل جيد، وتحافظ على تماسك الأحداث.
الشخصيات المحدودة والمعرّفة: {characters_score}/10
الشخصيات محددة بوضوح ومتميزة، مع تطوير مناسب للشخصيات الرئيسية.
التركيز على لحظة حاسمة: {decisive_moment_score}/10
القصة تبني بمهارة نحو لحظة التحول الرئيسية التي تغير مسار الأحداث.
الإيجاز واقتصاد اللغة: {language_score}/10
اللغة موجزة ومعبرة، تنقل المعاني بفعالية دون إطناب غير ضروري.
وحدة الزمان والمكان: {time_place_score}/10
هناك استخدام متناسق للإطار الزماني والمكاني، مما يعزز تماسك القصة.
حبكة جيدة البناء: {plot_score}/10
الحبكة متطورة بشكل منطقي ومتماسك، مع تسلسل واضح للأحداث.
نهاية مؤثرة: {ending_score}/10
النهاية تترك انطباعًا قويًا وتوفر إغلاقًا مناسبًا للأحداث.
رسالة أو موضوع واضح: {message_score}/10
تُظهر القصة رسالة واضحة تتطور بشكل طبيعي من خلال الأحداث.
النتيجة النهائية: {total_score}/80
{"هذا عمل أدبي متميز يتسم بقوة البناء والتماسك. القصة تحقق توازنًا جيدًا بين تطوير الشخصيات وتقدم الحبكة." if total_score > 65 else "رغم وجود عناصر قوية في القصة، هناك مجال للتحسين في بعض الجوانب. ننصح بالتركيز على تعزيز تماسك الأحداث وتطوير الشخصيات بشكل أعمق."}
ملاحظة: بداية القصة "{story_start}" تظهر إمكانات جيدة وتجذب اهتمام القارئ.""",
"fixed_story": None
}
def review_story(pdf_path):
"""
Review a story from a PDF file
"""
try:
# Load text from PDF
text = ""
try:
with open(pdf_path, "rb") as f:
reader = PdfReader(f)
text = "\n".join([p.extract_text() for p in reader.pages if p.extract_text()])
text = " ".join(text.split())
except Exception as e:
logger.error(f"PDF loading failed: {e}")
return {"evaluation": f"Error loading PDF: {e}", "fixed_story": None}
# Get evaluation
api_key = get_api_key()
if not api_key:
# Return mock evaluation
logger.info("Using mock evaluation for PDF")
return get_mock_evaluation(text)
# Use API for evaluation
return call_api_for_evaluation(text)
except Exception as e:
logger.error(f"Error in review_story: {e}")
return {"evaluation": f"Error processing story: {e}", "fixed_story": None}
def review_story_text(story_text):
"""
Review a story provided as text directly
"""
try:
# Get evaluation
api_key = get_api_key()
if not api_key:
# Return mock evaluation
logger.info("Using mock evaluation for text")
return get_mock_evaluation(story_text)
# Use API for evaluation
return call_api_for_evaluation(story_text)
except Exception as e:
logger.error(f"Error in review_story_text: {e}")
return {"evaluation": f"Error processing story text: {e}", "fixed_story": None}
def call_api_for_evaluation(story):
"""
Call the DeepSeek API for story evaluation
"""
api_key = get_api_key()
if not api_key:
return get_mock_evaluation(story)
evaluation_prompt = f"""
You are a professional literary critic specializing in the art of the short story. Your task is to evaluate the following story according to 8 essential criteria used in literary criticism. You must write the full evaluation in Modern Standard Arabic, using a clear and organized style.
🔹 For each criterion:
Give a score out of 10.
Write a brief explanation (one or two lines) that justifies the score.
🔹 At the end of the evaluation:
Add up the scores to get a final result out of 80.
If the score is above 65: Praise the story as a successful and well-crafted literary work.
If the score is 65 or lower: Provide constructive criticism that highlights the main weaknesses and suggests how to improve them.
Start the evaluation with a title that includes an emoji, such as: 📋 التقييم:
🔹 The evaluation criteria are:
1. Unity of event: Does the story revolve around a single main incident or situation?
2. Limited and defined characters: Does the story include a small number of clear and distinctive characters?
3. Focus on a decisive moment: Does the story highlight a turning point or critical decision?
4. Conciseness and economy of language: Is the language focused and free of unnecessary details?
5. Unity of time and place: Does the story take place in a specific time and setting?
6. Well-structured plot: Is there a clear logical sequence (beginning, middle, end)?
7. Impactful ending: Does the ending leave an emotional or intellectual impact?
8. Clear message or theme: Does the story convey a specific idea or feeling clearly?
Evaluate the following story based on these criteria:
{story}
"""
url = "https://api.deepseek.com/v1/chat/completions"
headers = {
"Authorization": f"Bearer {api_key}",
"Content-Type": "application/json"
}
payload_eval = {
"model": "deepseek-chat",
"messages": [
{"role": "system", "content": "You are a formal short story evaluator."},
{"role": "user", "content": evaluation_prompt.strip()}
],
"temperature": random.uniform(0.9, 1.0),
"max_tokens": 2500
}
try:
logger.info("Sending request to DeepSeek API")
response_eval = requests.post(url, headers=headers, json=payload_eval)
if response_eval.status_code != 200:
logger.error(f"API Error: {response_eval.status_code} - {response_eval.text}")
return {"evaluation": f"Error from API: {response_eval.text}", "fixed_story": None}
evaluation_result = response_eval.json()["choices"][0]["message"]["content"]
logger.info("Successfully received evaluation from API")
return {
"evaluation": evaluation_result.strip(),
"fixed_story": None
}
except Exception as e:
logger.error(f"API call failed: {e}")
return {"evaluation": f"Error calling API: {e}", "fixed_story": None} |