Mohammed Foud
commited on
Commit
·
e78883e
1
Parent(s):
2ec02f9
Add application file
Browse files- .cursorignore +2 -0
- .gitignore +1 -0
- __pycache__/config.cpython-312.pyc +0 -0
- app.py +1 -0
- routes/__pycache__/api.cpython-312.pyc +0 -0
- routes/__pycache__/views.cpython-312.pyc +0 -0
- routes/api.py +47 -9
- services/__pycache__/document_generator.cpython-312.pyc +0 -0
- services/__pycache__/model_provider.cpython-312.pyc +0 -0
- templates/index.html +173 -0
- utils/__pycache__/retry_decorator.cpython-312.pyc +0 -0
.cursorignore
CHANGED
@@ -10,3 +10,5 @@ etc
|
|
10 |
.vscode
|
11 |
.env
|
12 |
.env.local
|
|
|
|
|
|
10 |
.vscode
|
11 |
.env
|
12 |
.env.local
|
13 |
+
har_and_cookies
|
14 |
+
output
|
.gitignore
CHANGED
@@ -21,3 +21,4 @@ rad.json
|
|
21 |
#Test results file
|
22 |
TestResults.xml
|
23 |
trash
|
|
|
|
21 |
#Test results file
|
22 |
TestResults.xml
|
23 |
trash
|
24 |
+
output
|
__pycache__/config.cpython-312.pyc
ADDED
Binary file (1.44 kB). View file
|
|
app.py
CHANGED
@@ -9,6 +9,7 @@ app.config.from_object(Config)
|
|
9 |
# Register blueprints
|
10 |
app.register_blueprint(views_bp)
|
11 |
app.register_blueprint(api_bp)
|
|
|
12 |
def create_app():
|
13 |
app = Flask(__name__)
|
14 |
app.config.from_object(Config)
|
|
|
9 |
# Register blueprints
|
10 |
app.register_blueprint(views_bp)
|
11 |
app.register_blueprint(api_bp)
|
12 |
+
app.run(debug=True)
|
13 |
def create_app():
|
14 |
app = Flask(__name__)
|
15 |
app.config.from_object(Config)
|
routes/__pycache__/api.cpython-312.pyc
ADDED
Binary file (19.3 kB). View file
|
|
routes/__pycache__/views.cpython-312.pyc
ADDED
Binary file (698 Bytes). View file
|
|
routes/api.py
CHANGED
@@ -36,28 +36,55 @@ def extract_chapters(index_content: str) -> List[str]:
|
|
36 |
chapters.append(chapter_title)
|
37 |
return chapters if chapters else ["Literature Review", "Methodology", "Results and Discussion"]
|
38 |
|
39 |
-
def generate_automatic_sections(model: str, research_subject: str
|
|
|
|
|
40 |
"""Generate sections automatically based on AI-generated index"""
|
41 |
try:
|
42 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
43 |
chapters = extract_chapters(index_content)
|
44 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
45 |
sections = [
|
46 |
("Index", index_content),
|
47 |
-
("Introduction", f"Write a comprehensive introduction for a research paper about {research_subject}.
|
|
|
48 |
]
|
49 |
|
|
|
50 |
for i, chapter in enumerate(chapters, 1):
|
|
|
51 |
sections.append(
|
52 |
(f"Chapter {i}: {chapter}",
|
53 |
f"Write a detailed chapter about '{chapter}' for a research paper about {research_subject}. "
|
54 |
-
f"Provide comprehensive coverage of this aspect, including relevant theories, examples, and analysis.")
|
55 |
)
|
56 |
|
57 |
sections.append(
|
58 |
-
("Conclusion", f"Write a conclusion section for a research paper about {research_subject}.
|
59 |
)
|
60 |
|
|
|
|
|
|
|
|
|
|
|
|
|
61 |
return sections
|
62 |
except Exception as e:
|
63 |
raise Exception(f"Failed to generate automatic structure: {str(e)}")
|
@@ -101,6 +128,10 @@ def stream():
|
|
101 |
research_subject = request.args.get('subject', '').strip()
|
102 |
selected_model = request.args.get('model', 'gpt-4o')
|
103 |
structure_type = request.args.get('structure', 'automatic')
|
|
|
|
|
|
|
|
|
104 |
|
105 |
def generate():
|
106 |
try:
|
@@ -145,8 +176,14 @@ def stream():
|
|
145 |
"current_step": 1
|
146 |
}) + "\n\n"
|
147 |
|
148 |
-
|
149 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
150 |
|
151 |
steps[1]["status"] = "complete"
|
152 |
yield "data: " + json.dumps({
|
@@ -163,7 +200,7 @@ def stream():
|
|
163 |
"current_step": 2
|
164 |
}) + "\n\n"
|
165 |
|
166 |
-
chapters = extract_chapters(
|
167 |
|
168 |
# Create sub-steps for each chapter with initial timing info
|
169 |
chapter_substeps = [
|
@@ -450,4 +487,5 @@ def download(filename):
|
|
450 |
Config.UPLOAD_FOLDER,
|
451 |
safe_filename,
|
452 |
as_attachment=True
|
453 |
-
)
|
|
|
|
36 |
chapters.append(chapter_title)
|
37 |
return chapters if chapters else ["Literature Review", "Methodology", "Results and Discussion"]
|
38 |
|
39 |
+
def generate_automatic_sections(model: str, research_subject: str, chapter_count: str = 'auto',
|
40 |
+
word_count: str = 'auto', include_references: bool = False,
|
41 |
+
citation_style: str = None) -> List[Tuple[str, str]]:
|
42 |
"""Generate sections automatically based on AI-generated index"""
|
43 |
try:
|
44 |
+
# Generate index with specified parameters
|
45 |
+
index_prompt = f"Create a research paper outline about {research_subject}"
|
46 |
+
if chapter_count != 'auto':
|
47 |
+
index_prompt += f" with exactly {chapter_count} main chapters"
|
48 |
+
if word_count != 'auto':
|
49 |
+
index_prompt += f" targeting approximately {word_count} words"
|
50 |
+
|
51 |
+
index_content = model_provider.generate_index_content(model, index_prompt)
|
52 |
chapters = extract_chapters(index_content)
|
53 |
|
54 |
+
# If specific chapter count requested, adjust chapters list
|
55 |
+
if chapter_count != 'auto':
|
56 |
+
requested_count = int(chapter_count)
|
57 |
+
if len(chapters) > requested_count:
|
58 |
+
chapters = chapters[:requested_count]
|
59 |
+
elif len(chapters) < requested_count:
|
60 |
+
default_chapters = ["Literature Review", "Methodology", "Results", "Discussion"]
|
61 |
+
chapters.extend(default_chapters[len(chapters):requested_count])
|
62 |
+
|
63 |
sections = [
|
64 |
("Index", index_content),
|
65 |
+
("Introduction", f"Write a comprehensive introduction for a research paper about {research_subject}. "
|
66 |
+
f"{'Target word count: ' + word_count + ' words.' if word_count != 'auto' else ''}")
|
67 |
]
|
68 |
|
69 |
+
# Add chapter prompts
|
70 |
for i, chapter in enumerate(chapters, 1):
|
71 |
+
word_guidance = f" Target approximately {int(int(word_count) / (len(chapters) + 2)) } words." if word_count != 'auto' else ''
|
72 |
sections.append(
|
73 |
(f"Chapter {i}: {chapter}",
|
74 |
f"Write a detailed chapter about '{chapter}' for a research paper about {research_subject}. "
|
75 |
+
f"Provide comprehensive coverage of this aspect, including relevant theories, examples, and analysis.{word_guidance}")
|
76 |
)
|
77 |
|
78 |
sections.append(
|
79 |
+
("Conclusion", f"Write a conclusion section for a research paper about {research_subject}.")
|
80 |
)
|
81 |
|
82 |
+
# Add references section if requested
|
83 |
+
if include_references:
|
84 |
+
sections.append(
|
85 |
+
("References", f"Generate a references section in {citation_style} format for this research paper about {research_subject}.")
|
86 |
+
)
|
87 |
+
|
88 |
return sections
|
89 |
except Exception as e:
|
90 |
raise Exception(f"Failed to generate automatic structure: {str(e)}")
|
|
|
128 |
research_subject = request.args.get('subject', '').strip()
|
129 |
selected_model = request.args.get('model', 'gpt-4o')
|
130 |
structure_type = request.args.get('structure', 'automatic')
|
131 |
+
chapter_count = request.args.get('chapterCount', 'auto')
|
132 |
+
word_count = request.args.get('wordCount', 'auto')
|
133 |
+
include_references = request.args.get('includeReferences') == 'true'
|
134 |
+
citation_style = request.args.get('citationStyle')
|
135 |
|
136 |
def generate():
|
137 |
try:
|
|
|
176 |
"current_step": 1
|
177 |
}) + "\n\n"
|
178 |
|
179 |
+
sections = generate_automatic_sections(
|
180 |
+
selected_model,
|
181 |
+
research_subject,
|
182 |
+
chapter_count,
|
183 |
+
word_count,
|
184 |
+
include_references,
|
185 |
+
citation_style
|
186 |
+
)
|
187 |
|
188 |
steps[1]["status"] = "complete"
|
189 |
yield "data: " + json.dumps({
|
|
|
200 |
"current_step": 2
|
201 |
}) + "\n\n"
|
202 |
|
203 |
+
chapters = extract_chapters(sections[0][1])
|
204 |
|
205 |
# Create sub-steps for each chapter with initial timing info
|
206 |
chapter_substeps = [
|
|
|
487 |
Config.UPLOAD_FOLDER,
|
488 |
safe_filename,
|
489 |
as_attachment=True
|
490 |
+
)
|
491 |
+
|
services/__pycache__/document_generator.cpython-312.pyc
ADDED
Binary file (2.12 kB). View file
|
|
services/__pycache__/model_provider.cpython-312.pyc
ADDED
Binary file (16.1 kB). View file
|
|
templates/index.html
CHANGED
@@ -57,6 +57,88 @@
|
|
57 |
</div>
|
58 |
</div>
|
59 |
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
60 |
<div class="pt-4">
|
61 |
<button type="submit" id="generateBtn"
|
62 |
class="w-full flex justify-center items-center py-3 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed">
|
@@ -359,6 +441,97 @@
|
|
359 |
generateBtn.disabled = false;
|
360 |
};
|
361 |
});
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
362 |
</script>
|
363 |
</body>
|
364 |
</html>
|
|
|
57 |
</div>
|
58 |
</div>
|
59 |
|
60 |
+
<!-- New automatic structure options -->
|
61 |
+
<div id="automaticOptions" class="space-y-4">
|
62 |
+
<div>
|
63 |
+
<label for="chapterCount" class="block text-sm font-medium text-gray-700 mb-1">
|
64 |
+
<i class="fas fa-list-ol mr-2"></i>Number of Chapters
|
65 |
+
</label>
|
66 |
+
<div class="flex space-x-4 mb-2">
|
67 |
+
<label class="inline-flex items-center">
|
68 |
+
<input type="radio" name="chapterCountType" value="auto" checked
|
69 |
+
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
|
70 |
+
<span class="ml-2 text-gray-700">Automatic</span>
|
71 |
+
</label>
|
72 |
+
<label class="inline-flex items-center">
|
73 |
+
<input type="radio" name="chapterCountType" value="manual"
|
74 |
+
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
|
75 |
+
<span class="ml-2 text-gray-700">Manual</span>
|
76 |
+
</label>
|
77 |
+
</div>
|
78 |
+
<div class="flex space-x-4">
|
79 |
+
<select id="chapterCount" name="chapterCount" disabled
|
80 |
+
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500">
|
81 |
+
<option value="3">3 Chapters</option>
|
82 |
+
<option value="4">4 Chapters</option>
|
83 |
+
<option value="5">5 Chapters</option>
|
84 |
+
<option value="6">6 Chapters</option>
|
85 |
+
</select>
|
86 |
+
<input type="number" id="customChapterCount" name="customChapterCount"
|
87 |
+
class="hidden w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500"
|
88 |
+
min="1" max="10" placeholder="Enter number (1-10)">
|
89 |
+
</div>
|
90 |
+
</div>
|
91 |
+
|
92 |
+
<div>
|
93 |
+
<label for="wordCount" class="block text-sm font-medium text-gray-700 mb-1">
|
94 |
+
<i class="fas fa-font mr-2"></i>Target Word Count
|
95 |
+
</label>
|
96 |
+
<div class="flex space-x-4 mb-2">
|
97 |
+
<label class="inline-flex items-center">
|
98 |
+
<input type="radio" name="wordCountType" value="auto" checked
|
99 |
+
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
|
100 |
+
<span class="ml-2 text-gray-700">Automatic</span>
|
101 |
+
</label>
|
102 |
+
<label class="inline-flex items-center">
|
103 |
+
<input type="radio" name="wordCountType" value="manual"
|
104 |
+
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
|
105 |
+
<span class="ml-2 text-gray-700">Manual</span>
|
106 |
+
</label>
|
107 |
+
</div>
|
108 |
+
<div class="flex space-x-4">
|
109 |
+
<select id="wordCount" name="wordCount" disabled
|
110 |
+
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500">
|
111 |
+
<option value="2000">2,000 words</option>
|
112 |
+
<option value="3000">3,000 words</option>
|
113 |
+
<option value="5000">5,000 words</option>
|
114 |
+
<option value="8000">8,000 words</option>
|
115 |
+
<option value="10000">10,000 words</option>
|
116 |
+
</select>
|
117 |
+
<input type="number" id="customWordCount" name="customWordCount"
|
118 |
+
class="hidden w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500"
|
119 |
+
min="500" max="20000" step="100" placeholder="Enter words (500-20000)">
|
120 |
+
</div>
|
121 |
+
</div>
|
122 |
+
|
123 |
+
<div>
|
124 |
+
<label class="block text-sm font-medium text-gray-700 mb-2">
|
125 |
+
<i class="fas fa-quote-right mr-2"></i>References
|
126 |
+
</label>
|
127 |
+
<div class="flex items-center mb-2">
|
128 |
+
<input type="checkbox" id="includeReferences" name="includeReferences"
|
129 |
+
class="h-4 w-4 text-indigo-600 focus:ring-indigo-500">
|
130 |
+
<label for="includeReferences" class="ml-2 text-sm text-gray-700">Include References Section</label>
|
131 |
+
</div>
|
132 |
+
<select id="citationStyle" name="citationStyle" disabled
|
133 |
+
class="w-full px-4 py-2 border border-gray-300 rounded-md focus:ring-indigo-500 focus:border-indigo-500">
|
134 |
+
<option value="APA">APA</option>
|
135 |
+
<option value="MLA">MLA</option>
|
136 |
+
<option value="Chicago">Chicago</option>
|
137 |
+
<option value="Harvard">Harvard</option>
|
138 |
+
</select>
|
139 |
+
</div>
|
140 |
+
</div>
|
141 |
+
|
142 |
<div class="pt-4">
|
143 |
<button type="submit" id="generateBtn"
|
144 |
class="w-full flex justify-center items-center py-3 px-4 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 disabled:opacity-50 disabled:cursor-not-allowed">
|
|
|
441 |
generateBtn.disabled = false;
|
442 |
};
|
443 |
});
|
444 |
+
|
445 |
+
document.addEventListener('DOMContentLoaded', function() {
|
446 |
+
// Get elements
|
447 |
+
const structureRadios = document.querySelectorAll('input[name="structure"]');
|
448 |
+
const automaticOptions = document.getElementById('automaticOptions');
|
449 |
+
const includeReferences = document.getElementById('includeReferences');
|
450 |
+
const citationStyle = document.getElementById('citationStyle');
|
451 |
+
const citationStyleContainer = citationStyle.parentElement;
|
452 |
+
|
453 |
+
// Handle structure radio changes
|
454 |
+
structureRadios.forEach(radio => {
|
455 |
+
radio.addEventListener('change', function() {
|
456 |
+
automaticOptions.style.display =
|
457 |
+
this.value === 'automatic' ? 'block' : 'none';
|
458 |
+
});
|
459 |
+
});
|
460 |
+
|
461 |
+
// Initialize automatic options visibility
|
462 |
+
automaticOptions.style.display =
|
463 |
+
document.querySelector('input[name="structure"]:checked').value === 'automatic'
|
464 |
+
? 'block'
|
465 |
+
: 'none';
|
466 |
+
|
467 |
+
// Handle references checkbox
|
468 |
+
includeReferences.addEventListener('change', function() {
|
469 |
+
citationStyleContainer.style.display = this.checked ? 'block' : 'none';
|
470 |
+
citationStyle.disabled = !this.checked;
|
471 |
+
});
|
472 |
+
// Initialize citation style visibility
|
473 |
+
citationStyleContainer.style.display = includeReferences.checked ? 'block' : 'none';
|
474 |
+
|
475 |
+
// Chapter count controls
|
476 |
+
const chapterCountTypeRadios = document.querySelectorAll('input[name="chapterCountType"]');
|
477 |
+
const chapterCountSelect = document.getElementById('chapterCount');
|
478 |
+
const customChapterCount = document.getElementById('customChapterCount');
|
479 |
+
const chapterCountContainer = chapterCountSelect.parentElement;
|
480 |
+
|
481 |
+
chapterCountTypeRadios.forEach(radio => {
|
482 |
+
radio.addEventListener('change', function() {
|
483 |
+
const isManual = this.value === 'manual';
|
484 |
+
chapterCountContainer.style.display = isManual ? 'flex' : 'none';
|
485 |
+
chapterCountSelect.disabled = !isManual;
|
486 |
+
customChapterCount.classList.toggle('hidden', true);
|
487 |
+
chapterCountSelect.classList.toggle('hidden', false);
|
488 |
+
});
|
489 |
+
});
|
490 |
+
// Initialize chapter count visibility
|
491 |
+
chapterCountContainer.style.display =
|
492 |
+
document.querySelector('input[name="chapterCountType"]:checked').value === 'manual'
|
493 |
+
? 'flex'
|
494 |
+
: 'none';
|
495 |
+
|
496 |
+
chapterCountSelect.addEventListener('change', function() {
|
497 |
+
if (this.value === 'custom') {
|
498 |
+
this.classList.toggle('hidden', true);
|
499 |
+
customChapterCount.classList.toggle('hidden', false);
|
500 |
+
}
|
501 |
+
});
|
502 |
+
|
503 |
+
// Word count controls
|
504 |
+
const wordCountTypeRadios = document.querySelectorAll('input[name="wordCountType"]');
|
505 |
+
const wordCountSelect = document.getElementById('wordCount');
|
506 |
+
const customWordCount = document.getElementById('customWordCount');
|
507 |
+
const wordCountContainer = wordCountSelect.parentElement;
|
508 |
+
|
509 |
+
wordCountTypeRadios.forEach(radio => {
|
510 |
+
radio.addEventListener('change', function() {
|
511 |
+
const isManual = this.value === 'manual';
|
512 |
+
wordCountContainer.style.display = isManual ? 'flex' : 'none';
|
513 |
+
wordCountSelect.disabled = !isManual;
|
514 |
+
customWordCount.classList.toggle('hidden', true);
|
515 |
+
wordCountSelect.classList.toggle('hidden', false);
|
516 |
+
});
|
517 |
+
});
|
518 |
+
// Initialize word count visibility
|
519 |
+
wordCountContainer.style.display =
|
520 |
+
document.querySelector('input[name="wordCountType"]:checked').value === 'manual'
|
521 |
+
? 'flex'
|
522 |
+
: 'none';
|
523 |
+
|
524 |
+
wordCountSelect.addEventListener('change', function() {
|
525 |
+
if (this.value === 'custom') {
|
526 |
+
this.classList.toggle('hidden', true);
|
527 |
+
customWordCount.classList.toggle('hidden', false);
|
528 |
+
}
|
529 |
+
});
|
530 |
+
|
531 |
+
// Add custom option to selects
|
532 |
+
chapterCountSelect.innerHTML += '<option value="custom">Custom...</option>';
|
533 |
+
wordCountSelect.innerHTML += '<option value="custom">Custom...</option>';
|
534 |
+
});
|
535 |
</script>
|
536 |
</body>
|
537 |
</html>
|
utils/__pycache__/retry_decorator.cpython-312.pyc
ADDED
Binary file (1.35 kB). View file
|
|