Spaces:
Runtime error
Runtime error
feat: implement full project generation module with automated documentation and prompt parsing
Browse files- src/recommendation_engine/__pycache__/chatbot_engine.cpython-313.pyc +0 -0
- src/recommendation_engine/__pycache__/config.cpython-313.pyc +0 -0
- src/recommendation_engine/__pycache__/full_project_generator.cpython-313.pyc +0 -0
- src/recommendation_engine/__pycache__/llm_client.cpython-313.pyc +0 -0
- src/recommendation_engine/__pycache__/prompt_builder.cpython-313.pyc +0 -0
- src/recommendation_engine/chatbot_engine.py +41 -1
- src/recommendation_engine/config.py +1 -0
- src/recommendation_engine/full_project_generator.py +39 -1
- src/recommendation_engine/llm_client.py +2 -0
- src/recommendation_engine/prompt_builder.py +3 -2
src/recommendation_engine/__pycache__/chatbot_engine.cpython-313.pyc
CHANGED
|
Binary files a/src/recommendation_engine/__pycache__/chatbot_engine.cpython-313.pyc and b/src/recommendation_engine/__pycache__/chatbot_engine.cpython-313.pyc differ
|
|
|
src/recommendation_engine/__pycache__/config.cpython-313.pyc
CHANGED
|
Binary files a/src/recommendation_engine/__pycache__/config.cpython-313.pyc and b/src/recommendation_engine/__pycache__/config.cpython-313.pyc differ
|
|
|
src/recommendation_engine/__pycache__/full_project_generator.cpython-313.pyc
CHANGED
|
Binary files a/src/recommendation_engine/__pycache__/full_project_generator.cpython-313.pyc and b/src/recommendation_engine/__pycache__/full_project_generator.cpython-313.pyc differ
|
|
|
src/recommendation_engine/__pycache__/llm_client.cpython-313.pyc
CHANGED
|
Binary files a/src/recommendation_engine/__pycache__/llm_client.cpython-313.pyc and b/src/recommendation_engine/__pycache__/llm_client.cpython-313.pyc differ
|
|
|
src/recommendation_engine/__pycache__/prompt_builder.cpython-313.pyc
CHANGED
|
Binary files a/src/recommendation_engine/__pycache__/prompt_builder.cpython-313.pyc and b/src/recommendation_engine/__pycache__/prompt_builder.cpython-313.pyc differ
|
|
|
src/recommendation_engine/chatbot_engine.py
CHANGED
|
@@ -631,6 +631,11 @@ def chatbot(user_id: str, user_input: str):
|
|
| 631 |
state["last_action"] = "feature"
|
| 632 |
|
| 633 |
response = format_response("feature", "", state)
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 634 |
return finalize_response(user_input, response, history, state, user_id)
|
| 635 |
|
| 636 |
elif action == "trigger_full_project_generation":
|
|
@@ -691,17 +696,52 @@ def chatbot(user_id: str, user_input: str):
|
|
| 691 |
{chr(10).join("- " + x for x in state.get("objectives", []))}
|
| 692 |
|
| 693 |
━━━━━━━━━━━━━━━━━━━━━━
|
| 694 |
-
👉
|
| 695 |
"""
|
| 696 |
return finalize_response(user_input, response, history, state, user_id)
|
| 697 |
|
| 698 |
elif action == "confirmation_yes":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 699 |
state["waiting_for_project_idea_confirm"] = False
|
| 700 |
state["waiting_for_title_confirmation"] = False
|
| 701 |
save_user_memory(user_id, {"history": history, "state": state})
|
| 702 |
return finalize_response(user_input, "Great! Confirmed. Let's move on.", history, state, user_id)
|
| 703 |
|
| 704 |
elif action == "confirmation_no":
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 705 |
state["waiting_for_project_idea_confirm"] = False
|
| 706 |
state["waiting_for_title_confirmation"] = False
|
| 707 |
save_user_memory(user_id, {"history": history, "state": state})
|
|
|
|
| 631 |
state["last_action"] = "feature"
|
| 632 |
|
| 633 |
response = format_response("feature", "", state)
|
| 634 |
+
|
| 635 |
+
if state.get("custom_abstract") or state.get("custom_description"):
|
| 636 |
+
state["waiting_for_abstract_update"] = True
|
| 637 |
+
response += "\n\n✨ **Would you like me to seamlessly weave these new features into your custom abstract and description? (Yes/No)**"
|
| 638 |
+
|
| 639 |
return finalize_response(user_input, response, history, state, user_id)
|
| 640 |
|
| 641 |
elif action == "trigger_full_project_generation":
|
|
|
|
| 696 |
{chr(10).join("- " + x for x in state.get("objectives", []))}
|
| 697 |
|
| 698 |
━━━━━━━━━━━━━━━━━━━━━━
|
| 699 |
+
👉 What's next? You can say "improve features", or tell me to "replace abstract with..." your own custom text!
|
| 700 |
"""
|
| 701 |
return finalize_response(user_input, response, history, state, user_id)
|
| 702 |
|
| 703 |
elif action == "confirmation_yes":
|
| 704 |
+
if state.get("waiting_for_abstract_update"):
|
| 705 |
+
from src.recommendation_engine.full_project_generator import rewrite_custom_sections
|
| 706 |
+
state["waiting_for_abstract_update"] = False
|
| 707 |
+
|
| 708 |
+
rewritten = rewrite_custom_sections(
|
| 709 |
+
features=state.get("features", []),
|
| 710 |
+
abstract=state.get("abstract", "") if state.get("custom_abstract") else "",
|
| 711 |
+
description=state.get("description", "") if state.get("custom_description") else ""
|
| 712 |
+
)
|
| 713 |
+
|
| 714 |
+
if state.get("custom_abstract") and rewritten.get("abstract"):
|
| 715 |
+
state["abstract"] = rewritten["abstract"]
|
| 716 |
+
if state.get("custom_description") and rewritten.get("description"):
|
| 717 |
+
state["description"] = rewritten["description"]
|
| 718 |
+
|
| 719 |
+
save_user_memory(user_id, {"history": history, "state": state})
|
| 720 |
+
return finalize_response(
|
| 721 |
+
user_input,
|
| 722 |
+
"✅ **Done!** I've upgraded your custom abstract and description with the new features while keeping your original style intact.\n\nType **'2'** to generate and view your newly upgraded full project!",
|
| 723 |
+
history,
|
| 724 |
+
state,
|
| 725 |
+
user_id
|
| 726 |
+
)
|
| 727 |
+
|
| 728 |
state["waiting_for_project_idea_confirm"] = False
|
| 729 |
state["waiting_for_title_confirmation"] = False
|
| 730 |
save_user_memory(user_id, {"history": history, "state": state})
|
| 731 |
return finalize_response(user_input, "Great! Confirmed. Let's move on.", history, state, user_id)
|
| 732 |
|
| 733 |
elif action == "confirmation_no":
|
| 734 |
+
if state.get("waiting_for_abstract_update"):
|
| 735 |
+
state["waiting_for_abstract_update"] = False
|
| 736 |
+
save_user_memory(user_id, {"history": history, "state": state})
|
| 737 |
+
return finalize_response(
|
| 738 |
+
user_input,
|
| 739 |
+
"👍 **Got it!** I will leave your custom abstract and description exactly as you wrote them.\n\nType **'2'** whenever you're ready to view the full project.",
|
| 740 |
+
history,
|
| 741 |
+
state,
|
| 742 |
+
user_id
|
| 743 |
+
)
|
| 744 |
+
|
| 745 |
state["waiting_for_project_idea_confirm"] = False
|
| 746 |
state["waiting_for_title_confirmation"] = False
|
| 747 |
save_user_memory(user_id, {"history": history, "state": state})
|
src/recommendation_engine/config.py
CHANGED
|
@@ -35,6 +35,7 @@ IDEA_MAX_TOKENS = int(os.getenv("IDEA_MAX_TOKENS", 800))
|
|
| 35 |
FEATURE_MAX_TOKENS = int(os.getenv("FEATURE_MAX_TOKENS", 600))
|
| 36 |
CHAT_MAX_TOKENS = int(os.getenv("CHAT_MAX_TOKENS", 700))
|
| 37 |
INTENT_MAX_TOKENS = int(os.getenv("INTENT_MAX_TOKENS", 300))
|
|
|
|
| 38 |
|
| 39 |
TOP_P = float(os.getenv("TOP_P", 0.95))
|
| 40 |
TOP_K = int(os.getenv("TOP_K", 40))
|
|
|
|
| 35 |
FEATURE_MAX_TOKENS = int(os.getenv("FEATURE_MAX_TOKENS", 600))
|
| 36 |
CHAT_MAX_TOKENS = int(os.getenv("CHAT_MAX_TOKENS", 700))
|
| 37 |
INTENT_MAX_TOKENS = int(os.getenv("INTENT_MAX_TOKENS", 300))
|
| 38 |
+
FULL_PROJECT_MAX_TOKENS = int(os.getenv("FULL_PROJECT_MAX_TOKENS", 2000))
|
| 39 |
|
| 40 |
TOP_P = float(os.getenv("TOP_P", 0.95))
|
| 41 |
TOP_K = int(os.getenv("TOP_K", 40))
|
src/recommendation_engine/full_project_generator.py
CHANGED
|
@@ -88,7 +88,7 @@ def generate_full_project(
|
|
| 88 |
|
| 89 |
raw = generate_text(
|
| 90 |
prompt,
|
| 91 |
-
task="
|
| 92 |
)
|
| 93 |
|
| 94 |
result = {
|
|
@@ -215,3 +215,41 @@ def generate_full_project(
|
|
| 215 |
)
|
| 216 |
|
| 217 |
return result
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 88 |
|
| 89 |
raw = generate_text(
|
| 90 |
prompt,
|
| 91 |
+
task="full_project"
|
| 92 |
)
|
| 93 |
|
| 94 |
result = {
|
|
|
|
| 215 |
)
|
| 216 |
|
| 217 |
return result
|
| 218 |
+
|
| 219 |
+
def rewrite_custom_sections(features, abstract="", description=""):
|
| 220 |
+
features_text = "\n".join(f"- {f}" for f in features)
|
| 221 |
+
|
| 222 |
+
prompt = f"""
|
| 223 |
+
The user provided custom text for their project's abstract and/or description.
|
| 224 |
+
Your task is to update their custom text to incorporate the following NEW FEATURES.
|
| 225 |
+
|
| 226 |
+
CRITICAL RULES:
|
| 227 |
+
1. You MUST preserve the exact tone, style, and core phrasing of the user's original text!
|
| 228 |
+
2. If their text is casual or extremely short (e.g., "chat bot is the best"), KEEP it casual and short.
|
| 229 |
+
3. Just weave the new features in naturally or append them.
|
| 230 |
+
4. DO NOT turn a short, simple sentence into a massive, robotic academic block!
|
| 231 |
+
|
| 232 |
+
NEW FEATURES:
|
| 233 |
+
{features_text}
|
| 234 |
+
|
| 235 |
+
CUSTOM ABSTRACT:
|
| 236 |
+
{abstract if abstract else "N/A"}
|
| 237 |
+
|
| 238 |
+
CUSTOM DESCRIPTION:
|
| 239 |
+
{description if description else "N/A"}
|
| 240 |
+
|
| 241 |
+
OUTPUT FORMAT:
|
| 242 |
+
|
| 243 |
+
ABSTRACT:
|
| 244 |
+
(your rewritten abstract here, or leave empty if N/A)
|
| 245 |
+
|
| 246 |
+
DESCRIPTION:
|
| 247 |
+
(your rewritten description here, or leave empty if N/A)
|
| 248 |
+
""".strip()
|
| 249 |
+
|
| 250 |
+
raw = generate_text(prompt, task="chat")
|
| 251 |
+
|
| 252 |
+
return {
|
| 253 |
+
"abstract": extract_section(raw, "ABSTRACT") if abstract else "",
|
| 254 |
+
"description": extract_section(raw, "DESCRIPTION") if description else ""
|
| 255 |
+
}
|
src/recommendation_engine/llm_client.py
CHANGED
|
@@ -15,6 +15,7 @@ from src.recommendation_engine.config import (
|
|
| 15 |
FEATURE_MAX_TOKENS,
|
| 16 |
CHAT_MAX_TOKENS,
|
| 17 |
INTENT_MAX_TOKENS,
|
|
|
|
| 18 |
TOP_P,
|
| 19 |
TOP_K,
|
| 20 |
MAX_RETRIES,
|
|
@@ -104,6 +105,7 @@ def get_max_tokens(task: str) -> int:
|
|
| 104 |
"idea": IDEA_MAX_TOKENS,
|
| 105 |
"feature": FEATURE_MAX_TOKENS,
|
| 106 |
"intent": INTENT_MAX_TOKENS,
|
|
|
|
| 107 |
}.get(task, CHAT_MAX_TOKENS)
|
| 108 |
|
| 109 |
def safe_prompt(prompt: str, max_chars: int = 12000) -> str:
|
|
|
|
| 15 |
FEATURE_MAX_TOKENS,
|
| 16 |
CHAT_MAX_TOKENS,
|
| 17 |
INTENT_MAX_TOKENS,
|
| 18 |
+
FULL_PROJECT_MAX_TOKENS,
|
| 19 |
TOP_P,
|
| 20 |
TOP_K,
|
| 21 |
MAX_RETRIES,
|
|
|
|
| 105 |
"idea": IDEA_MAX_TOKENS,
|
| 106 |
"feature": FEATURE_MAX_TOKENS,
|
| 107 |
"intent": INTENT_MAX_TOKENS,
|
| 108 |
+
"full_project": FULL_PROJECT_MAX_TOKENS,
|
| 109 |
}.get(task, CHAT_MAX_TOKENS)
|
| 110 |
|
| 111 |
def safe_prompt(prompt: str, max_chars: int = 12000) -> str:
|
src/recommendation_engine/prompt_builder.py
CHANGED
|
@@ -289,6 +289,7 @@ STRICT RULES:
|
|
| 289 |
3. NEVER leave any field empty
|
| 290 |
4. If information is missing, intelligently generate it
|
| 291 |
5. Use professional academic style
|
|
|
|
| 292 |
6. Technologies and lists MUST use bullet points
|
| 293 |
7. Use EXACT section names
|
| 294 |
8. No explanations outside sections
|
|
@@ -306,10 +307,10 @@ CATEGORY:
|
|
| 306 |
(short category)
|
| 307 |
|
| 308 |
ABSTRACT:
|
| 309 |
-
(full academic abstract)
|
| 310 |
|
| 311 |
DESCRIPTION:
|
| 312 |
-
(full detailed description)
|
| 313 |
|
| 314 |
TECHNOLOGIES:
|
| 315 |
- item
|
|
|
|
| 289 |
3. NEVER leave any field empty
|
| 290 |
4. If information is missing, intelligently generate it
|
| 291 |
5. Use professional academic style
|
| 292 |
+
6. IF CURRENT ABSTRACT or CURRENT DESCRIPTION is provided, you MUST use their core concepts but seamlessly REWRITE and EXPAND them to explicitly include all the new FEATURES. DO NOT just copy them, and DO NOT ignore them. They represent the user's custom baseline intent.
|
| 293 |
6. Technologies and lists MUST use bullet points
|
| 294 |
7. Use EXACT section names
|
| 295 |
8. No explanations outside sections
|
|
|
|
| 307 |
(short category)
|
| 308 |
|
| 309 |
ABSTRACT:
|
| 310 |
+
(full academic abstract. CRITICAL RULE: If a CURRENT ABSTRACT was provided above, you MUST base this entirely around that custom text and seamlessly integrate the FEATURES into it. Do not ignore the custom text!)
|
| 311 |
|
| 312 |
DESCRIPTION:
|
| 313 |
+
(full detailed description. CRITICAL RULE: If a CURRENT DESCRIPTION was provided above, you MUST base this entirely around that custom text and seamlessly integrate the FEATURES into it. Do not ignore the custom text!)
|
| 314 |
|
| 315 |
TECHNOLOGIES:
|
| 316 |
- item
|