Spaces:
Running
Running
Update app.py
Browse files
app.py
CHANGED
|
@@ -93,8 +93,6 @@ tavily_rotator = APIKeyRotator("TAVILY")
|
|
| 93 |
|
| 94 |
os.environ["MISTRAL_API_KEY"] = mistral_rotator.get_key()
|
| 95 |
os.environ["TAVILY_API_KEY"] = tavily_rotator.get_key()
|
| 96 |
-
print(f"🔑 Tavily API Key present: {bool(os.getenv('TAVILY_API_KEY'))}")
|
| 97 |
-
print(f"🔑 Tavily API Key starts with: {os.getenv('TAVILY_API_KEY', 'NOT SET')[:10]}...")
|
| 98 |
|
| 99 |
# --- 3. RESILIENT LLM ---
|
| 100 |
|
|
@@ -459,9 +457,26 @@ def count_words(text: str) -> str:
|
|
| 459 |
def get_example_posts_for_writer() -> str:
|
| 460 |
"""Get example posts to guide the writer agent in creating high-quality content."""
|
| 461 |
examples = [
|
| 462 |
-
{
|
| 463 |
-
|
| 464 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 465 |
]
|
| 466 |
return json.dumps(examples, indent=2)
|
| 467 |
|
|
@@ -469,7 +484,36 @@ def get_example_posts_for_writer() -> str:
|
|
| 469 |
def get_example_posts_for_critic() -> str:
|
| 470 |
"""Get example posts with quality scores to guide the critic agent's evaluation."""
|
| 471 |
examples = [
|
| 472 |
-
{
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 473 |
]
|
| 474 |
return json.dumps(examples, indent=2)
|
| 475 |
|
|
@@ -654,12 +698,33 @@ def run_writer(state: EnhancedAgentState, progress_callback=None) -> EnhancedAge
|
|
| 654 |
if retry_count > 0:
|
| 655 |
retry_context = f"\nPrevious attempt rejected. Feedback: {state.get('critic_feedback')}"
|
| 656 |
|
| 657 |
-
system_msg = SystemMessage(content="""You are the Writer Agent.
|
| 658 |
-
|
| 659 |
-
|
| 660 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 661 |
|
| 662 |
-
user_msg = HumanMessage(content=f"Write post for:\n{story_text}\n{retry_context}")
|
| 663 |
|
| 664 |
writer_llm = llm_medium.bind_tools([get_example_posts_for_writer, fetch_article_content, count_words])
|
| 665 |
|
|
@@ -712,11 +777,43 @@ def run_critic(state: EnhancedAgentState, progress_callback=None) -> EnhancedAge
|
|
| 712 |
|
| 713 |
draft = state.get("draft_summary", "")
|
| 714 |
|
| 715 |
-
system_msg = SystemMessage(content="""You are the Critic Agent.
|
| 716 |
-
|
| 717 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 718 |
|
| 719 |
-
user_msg = HumanMessage(content=f"Evaluate:\n{draft}")
|
| 720 |
|
| 721 |
critic_llm = llm_large.bind_tools([get_example_posts_for_critic])
|
| 722 |
response = critic_llm.invoke([system_msg, user_msg])
|
|
@@ -864,17 +961,22 @@ def handle_checkpoint1_approve(state, progress=gr.Progress()):
|
|
| 864 |
|
| 865 |
return (
|
| 866 |
state,
|
| 867 |
-
f"## 🎯 Selected Story\n\n{story_text}",
|
| 868 |
gr.update(visible=True), # Approve button
|
| 869 |
gr.update(visible=True), # Different story
|
| 870 |
gr.update(visible=False),
|
| 871 |
gr.update(visible=False),
|
| 872 |
"",
|
| 873 |
-
gr.update(visible=
|
| 874 |
)
|
| 875 |
|
| 876 |
-
def handle_checkpoint1_reject(state, progress=gr.Progress()):
|
| 877 |
-
"""Handle rejection at checkpoint 1 - restart discovery"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 878 |
def update_progress(msg):
|
| 879 |
progress(0.3, desc=msg)
|
| 880 |
|
|
@@ -896,13 +998,13 @@ def handle_checkpoint1_reject(state, progress=gr.Progress()):
|
|
| 896 |
|
| 897 |
return (
|
| 898 |
state,
|
| 899 |
-
f"## 🔍 Discovery Results (New Search)\n\n{candidates_text}",
|
| 900 |
gr.update(visible=True),
|
| 901 |
gr.update(visible=True),
|
| 902 |
gr.update(visible=False),
|
| 903 |
gr.update(visible=False),
|
| 904 |
"",
|
| 905 |
-
gr.update(visible=
|
| 906 |
)
|
| 907 |
|
| 908 |
def handle_checkpoint2_approve(state, progress=gr.Progress()):
|
|
@@ -933,7 +1035,7 @@ def handle_checkpoint2_approve(state, progress=gr.Progress()):
|
|
| 933 |
|
| 934 |
return (
|
| 935 |
state,
|
| 936 |
-
f"## ✍️ Draft Post\n\n{draft}\n\n---\n\n**Quality Score:** {score}/10\n\n**Feedback:**\n{feedback}",
|
| 937 |
gr.update(visible=True), # Finalize
|
| 938 |
gr.update(visible=True), # Edit/Rewrite
|
| 939 |
gr.update(visible=False),
|
|
@@ -942,8 +1044,13 @@ def handle_checkpoint2_approve(state, progress=gr.Progress()):
|
|
| 942 |
gr.update(visible=True) # Show edit instructions
|
| 943 |
)
|
| 944 |
|
| 945 |
-
def handle_checkpoint2_different(state, progress=gr.Progress()):
|
| 946 |
-
"""Request different story - re-run curator"""
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 947 |
def update_progress(msg):
|
| 948 |
progress(0.5, desc=msg)
|
| 949 |
|
|
@@ -965,13 +1072,13 @@ def handle_checkpoint2_different(state, progress=gr.Progress()):
|
|
| 965 |
|
| 966 |
return (
|
| 967 |
state,
|
| 968 |
-
f"## 🎯 Selected Story (Alternative)\n\n{story_text}",
|
| 969 |
gr.update(visible=True),
|
| 970 |
gr.update(visible=True),
|
| 971 |
gr.update(visible=False),
|
| 972 |
gr.update(visible=False),
|
| 973 |
"",
|
| 974 |
-
gr.update(visible=
|
| 975 |
)
|
| 976 |
|
| 977 |
def handle_checkpoint3_finalize(state, progress=gr.Progress()):
|
|
@@ -1209,9 +1316,9 @@ with gr.Blocks(css=css, title="Tuesday Trivia Agent", theme=gr.themes.Soft()) as
|
|
| 1209 |
return handle_checkpoint1_approve(s)
|
| 1210 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1211 |
|
| 1212 |
-
def route_checkpoint1_reject(s):
|
| 1213 |
if s and s.get("stage") == WorkflowStage.CHECKPOINT_1.value:
|
| 1214 |
-
return handle_checkpoint1_reject(s)
|
| 1215 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1216 |
|
| 1217 |
# Checkpoint 2 handlers
|
|
@@ -1220,9 +1327,9 @@ with gr.Blocks(css=css, title="Tuesday Trivia Agent", theme=gr.themes.Soft()) as
|
|
| 1220 |
return handle_checkpoint2_approve(s)
|
| 1221 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1222 |
|
| 1223 |
-
def route_checkpoint2_different(s):
|
| 1224 |
if s and s.get("stage") == WorkflowStage.CHECKPOINT_2.value:
|
| 1225 |
-
return handle_checkpoint2_different(s)
|
| 1226 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1227 |
|
| 1228 |
# Checkpoint 3 handlers
|
|
@@ -1237,7 +1344,7 @@ with gr.Blocks(css=css, title="Tuesday Trivia Agent", theme=gr.themes.Soft()) as
|
|
| 1237 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), instructions, gr.update()
|
| 1238 |
|
| 1239 |
# Wire up the routing based on current stage
|
| 1240 |
-
def smart_approve(s):
|
| 1241 |
if not s:
|
| 1242 |
return s, "No active workflow", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1243 |
|
|
@@ -1251,29 +1358,29 @@ with gr.Blocks(css=css, title="Tuesday Trivia Agent", theme=gr.themes.Soft()) as
|
|
| 1251 |
|
| 1252 |
return s, "Invalid stage for approval", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1253 |
|
| 1254 |
-
def smart_reject(s):
|
| 1255 |
if not s:
|
| 1256 |
return s, "No active workflow", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1257 |
|
| 1258 |
stage = s.get("stage")
|
| 1259 |
if stage == WorkflowStage.CHECKPOINT_1.value:
|
| 1260 |
-
return route_checkpoint1_reject(s)
|
| 1261 |
elif stage == WorkflowStage.CHECKPOINT_2.value:
|
| 1262 |
-
return route_checkpoint2_different(s)
|
| 1263 |
elif stage == WorkflowStage.CHECKPOINT_3.value:
|
| 1264 |
-
return route_checkpoint3_edit(s,
|
| 1265 |
|
| 1266 |
return s, "Invalid stage for rejection", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1267 |
|
| 1268 |
approve_btn.click(
|
| 1269 |
fn=smart_approve,
|
| 1270 |
-
inputs=[state],
|
| 1271 |
outputs=[state, output_display, approve_btn, reject_btn, start_btn, restart_btn, edit_instructions, edit_instructions]
|
| 1272 |
)
|
| 1273 |
|
| 1274 |
reject_btn.click(
|
| 1275 |
fn=smart_reject,
|
| 1276 |
-
inputs=[state],
|
| 1277 |
outputs=[state, output_display, approve_btn, reject_btn, start_btn, restart_btn, edit_instructions, edit_instructions]
|
| 1278 |
)
|
| 1279 |
|
|
|
|
| 93 |
|
| 94 |
os.environ["MISTRAL_API_KEY"] = mistral_rotator.get_key()
|
| 95 |
os.environ["TAVILY_API_KEY"] = tavily_rotator.get_key()
|
|
|
|
|
|
|
| 96 |
|
| 97 |
# --- 3. RESILIENT LLM ---
|
| 98 |
|
|
|
|
| 457 |
def get_example_posts_for_writer() -> str:
|
| 458 |
"""Get example posts to guide the writer agent in creating high-quality content."""
|
| 459 |
examples = [
|
| 460 |
+
{
|
| 461 |
+
"title": "Scientists Found 14 Mysterious Creatures in the Ocean's Darkest Depths",
|
| 462 |
+
"content": """Scientists Found 14 Mysterious Creatures in the Ocean's Darkest Depths
|
| 463 |
+
|
| 464 |
+
Scientists have just revealed 14 new species living miles beneath the ocean's surface—some found at depths over 6,000 meters! This discovery is part of the Ocean Species Discoveries initiative, which is changing how new marine life is identified and shared with the world. Among the surprises: a record-setting deep-sea mollusk, a carnivorous bivalve, and even a popcorn-shaped parasitic isopod. Each of these creatures shows just how much life still hides in the ocean's darkest corners.
|
| 465 |
+
What's even cooler? The team is using cutting-edge lab techniques to make classifying species faster, more open, and globally collaborative—helping scientists everywhere explore and protect our planet's last great frontier: the deep sea.
|
| 466 |
+
|
| 467 |
+
#TuesdayTrivia #RnDCell #CCA #OceanDiscovery #MarineBiology #DeepSea""",
|
| 468 |
+
"structure": "Title -> One line gap -> First paragraph -> Next line -> Second paragraph -> One line gap -> Hashtags (must include #TuesdayTrivia #RnDCell #CCA)"
|
| 469 |
+
},
|
| 470 |
+
{
|
| 471 |
+
"title": "Researchers Have Developed Next-Generation Plant Immune System to Combat Bacterial Diseases",
|
| 472 |
+
"content": """Researchers Have Developed Next-Generation Plant Immune System to Combat Bacterial Diseases
|
| 473 |
+
|
| 474 |
+
Researchers at the University of California, Davis have used artificial intelligence to boost plant immunity, helping crops like tomatoes and potatoes resist bacterial infections. Using AlphaFold, an AI system that predicts protein structures, they redesigned the immune receptor FLS2, which identifies flagellin, a bacterial movement protein. Since bacteria mutate flagellin to escape detection, the AI-guided redesign enabled plants to recognize more bacterial variants and strengthen their defenses.
|
| 475 |
+
By altering key amino acids, the team reactivated weakened receptors, restoring the plants' ability to detect pathogens. This innovation could provide broad-spectrum disease resistance in major crops, including protection against Ralstonia solanacearum, the bacterium that causes bacterial wilt. The researchers now plan to apply machine learning to forecast future receptor modifications and extend this strategy to other plants.
|
| 476 |
+
|
| 477 |
+
#TuesdayTrivia #RnDCell #CCA #ArtificialIntelligence #PlantImmunity #AgriTech""",
|
| 478 |
+
"structure": "Title -> One line gap -> First paragraph -> Next line -> Second paragraph -> One line gap -> Hashtags"
|
| 479 |
+
}
|
| 480 |
]
|
| 481 |
return json.dumps(examples, indent=2)
|
| 482 |
|
|
|
|
| 484 |
def get_example_posts_for_critic() -> str:
|
| 485 |
"""Get example posts with quality scores to guide the critic agent's evaluation."""
|
| 486 |
examples = [
|
| 487 |
+
{
|
| 488 |
+
"title": "Researchers Have Developed a Cutting-Edge Silicon Photonic Chip to Enhance AI Efficiency",
|
| 489 |
+
"content": """Researchers Have Developed a Cutting-Edge Silicon Photonic Chip to Enhance AI Efficiency
|
| 490 |
+
|
| 491 |
+
Researchers at the University of Florida have developed a silicon photonic chip that uses light to handle convolution operations, the intensive pattern-recognition steps central to AI. The chip encodes data as laser light, directs it through microscopic Fresnel lenses etched onto silicon, and converts the results back into digital form. In tests, it classified handwritten digits with about 98% accuracy, comparable to electronic processors but with far lower energy use.
|
| 492 |
+
The design also supports wavelength multiplexing, allowing multiple colored lasers to process different data streams at once. This is the first demonstration of on-chip optical computation applied to neural networks. With optical elements already emerging in commercial AI hardware, researchers believe chip-based optics could soon become common, offering faster and more sustainable paths for scaling AI systems.
|
| 493 |
+
|
| 494 |
+
#TuesdayTrivia #RnDCell #CCA #ArtificialIntelligence #SiliconPhotonics #GreenTech""",
|
| 495 |
+
"quality_score": 9.0
|
| 496 |
+
},
|
| 497 |
+
{
|
| 498 |
+
"title": "Researchers Have Developed Injectable Skin That Brings Hope for Burn Victims and Scar-Free Healing",
|
| 499 |
+
"content": """Researchers Have Developed Injectable Skin That Brings Hope for Burn Victims and Scar-Free Healing
|
| 500 |
+
|
| 501 |
+
Imagine a reality in which burns and deep injuries can be healed with such ease that scarring is no longer a problem. This is now possible thanks to researchers at the University of Linköping in Sweden. They've created a special gel full of living skin cells—"skin in a syringe." This gel is either injected into wounds or 3D printed for skin transplants. Unlike traditional methods that only replace the outer layer of skin and almost inevitably result in scarring, this innovation helps the body heal deep dermis layers that provide strength, elasticity, and blood vessels to the skin.
|
| 502 |
+
Here's how it works: fibroblast cells, which are the main builders of connective tissue, are grown and embedded in small gelatin beads. These are then combined through "Click Chemistry" with a hyaluronic acid-based gel. The final product is a material that easily squirts out of a syringe but then settles into place perfectly. In mouse experiments, cells survived and helped grow new blood vessels, which are essential for healthy skin. The team also fabricated thin elastic hydrogel fibers that act as microvessels—a fundamental development for future organ repair and transplantation.
|
| 503 |
+
|
| 504 |
+
#TuesdayTrivia #RnDCell #CCA #TissueEngineering #RegenerativeMedicine #BiomedicalInnovation""",
|
| 505 |
+
"quality_score": 9.5
|
| 506 |
+
},
|
| 507 |
+
{
|
| 508 |
+
"title": "Researchers Have Developed AI-Driven Immune Cells to Precisely Target Cancer",
|
| 509 |
+
"content": """Researchers Have Developed AI-Driven Immune Cells to Precisely Target Cancer
|
| 510 |
+
|
| 511 |
+
Researchers have developed an advanced AI-driven approach that reprograms human immune cells to precisely target and destroy cancer—all within a few weeks. Traditionally, creating such personalized cell therapies is a time-consuming process involving months of laboratory testing. By using powerful machine-learning tools, the team was able to rapidly design T cells capable of recognizing cancer cells with high accuracy while sparing healthy tissues.
|
| 512 |
+
The AI system analyzed millions of receptor combinations and pinpointed the most effective designs, greatly accelerating the development timeline. Instead of relying on standard one-size-fits-all methods, doctors could soon adapt these AI-engineered immune cells to match the specific type of cancer found in each patient, offering new levels of precision and hope.
|
| 513 |
+
|
| 514 |
+
#TuesdayTrivia #RnDCell #CCA #CancerResearch #ImmuneTherapy #FutureOfMedicine""",
|
| 515 |
+
"quality_score": 9.0
|
| 516 |
+
}
|
| 517 |
]
|
| 518 |
return json.dumps(examples, indent=2)
|
| 519 |
|
|
|
|
| 698 |
if retry_count > 0:
|
| 699 |
retry_context = f"\nPrevious attempt rejected. Feedback: {state.get('critic_feedback')}"
|
| 700 |
|
| 701 |
+
system_msg = SystemMessage(content="""You are the Writer Agent for Tuesday Trivia posts.
|
| 702 |
+
|
| 703 |
+
CRITICAL FORMAT REQUIREMENTS:
|
| 704 |
+
1. Title (capitalize important words)
|
| 705 |
+
2. ONE blank line
|
| 706 |
+
3. First paragraph (Hook - grab attention, set context)
|
| 707 |
+
4. Next line (no blank line between paragraphs)
|
| 708 |
+
5. Second paragraph (Technical details and impact)
|
| 709 |
+
6. ONE blank line
|
| 710 |
+
7. Hashtags: MUST include #TuesdayTrivia #RnDCell #CCA plus 2-4 topic-specific hashtags
|
| 711 |
+
|
| 712 |
+
STYLE GUIDELINES:
|
| 713 |
+
- Conversational, active voice
|
| 714 |
+
- NO questions in the text
|
| 715 |
+
- 140-180 words total
|
| 716 |
+
- Make technical concepts accessible
|
| 717 |
+
- Emphasize real-world impact
|
| 718 |
+
|
| 719 |
+
HASHTAG FORMAT:
|
| 720 |
+
- Always include: #TuesdayTrivia #RnDCell #CCA
|
| 721 |
+
- Add relevant topic hashtags like #ArtificialIntelligence #Biotechnology #SpaceExploration
|
| 722 |
+
- Use camelCase (e.g., #MarineBiology not #Marine_biology)
|
| 723 |
+
- 5-7 hashtags total
|
| 724 |
+
|
| 725 |
+
Use the get_example_posts_for_writer tool to see perfect examples of the format.""")
|
| 726 |
|
| 727 |
+
user_msg = HumanMessage(content=f"Write a Tuesday Trivia post for:\n{story_text}\n{retry_context}")
|
| 728 |
|
| 729 |
writer_llm = llm_medium.bind_tools([get_example_posts_for_writer, fetch_article_content, count_words])
|
| 730 |
|
|
|
|
| 777 |
|
| 778 |
draft = state.get("draft_summary", "")
|
| 779 |
|
| 780 |
+
system_msg = SystemMessage(content="""You are the Critic Agent for Tuesday Trivia posts.
|
| 781 |
+
|
| 782 |
+
EVALUATION CRITERIA:
|
| 783 |
+
|
| 784 |
+
1. FORMAT (3 points):
|
| 785 |
+
- Title capitalized properly
|
| 786 |
+
- One blank line after title
|
| 787 |
+
- Two paragraphs (no blank line between them)
|
| 788 |
+
- One blank line before hashtags
|
| 789 |
+
- Hashtags include #TuesdayTrivia #RnDCell #CCA
|
| 790 |
+
|
| 791 |
+
2. CONTENT (3 points):
|
| 792 |
+
- First paragraph: Engaging hook + context
|
| 793 |
+
- Second paragraph: Technical details + real-world impact
|
| 794 |
+
- Accurate scientific information
|
| 795 |
+
- 140-180 words
|
| 796 |
+
|
| 797 |
+
3. STYLE (2 points):
|
| 798 |
+
- Conversational, active voice
|
| 799 |
+
- No questions in the text
|
| 800 |
+
- Technical concepts explained clearly
|
| 801 |
+
- Engaging and accessible
|
| 802 |
+
|
| 803 |
+
4. HASHTAGS (2 points):
|
| 804 |
+
- MUST include: #TuesdayTrivia #RnDCell #CCA
|
| 805 |
+
- 2-4 additional relevant hashtags
|
| 806 |
+
- camelCase format
|
| 807 |
+
- 5-7 hashtags total
|
| 808 |
+
|
| 809 |
+
OUTPUT FORMAT:
|
| 810 |
+
Provide detailed feedback, then:
|
| 811 |
+
TOTAL SCORE: X/10
|
| 812 |
+
Decision: APPROVED (if ≥8) or REJECTED (if <8)
|
| 813 |
+
|
| 814 |
+
Use get_example_posts_for_critic tool to see high-quality examples.""")
|
| 815 |
|
| 816 |
+
user_msg = HumanMessage(content=f"Evaluate this Tuesday Trivia post:\n\n{draft}")
|
| 817 |
|
| 818 |
critic_llm = llm_large.bind_tools([get_example_posts_for_critic])
|
| 819 |
response = critic_llm.invoke([system_msg, user_msg])
|
|
|
|
| 961 |
|
| 962 |
return (
|
| 963 |
state,
|
| 964 |
+
f"## 🎯 Selected Story\n\n{story_text}\n\n**Optional:** Provide instructions in the textbox below if you want to pick a different story.",
|
| 965 |
gr.update(visible=True), # Approve button
|
| 966 |
gr.update(visible=True), # Different story
|
| 967 |
gr.update(visible=False),
|
| 968 |
gr.update(visible=False),
|
| 969 |
"",
|
| 970 |
+
gr.update(visible=True) # Show instructions textbox
|
| 971 |
)
|
| 972 |
|
| 973 |
+
def handle_checkpoint1_reject(state, instructions, progress=gr.Progress()):
|
| 974 |
+
"""Handle rejection at checkpoint 1 - restart discovery with optional instructions"""
|
| 975 |
+
# Add instructions to state if provided
|
| 976 |
+
if instructions and instructions.strip():
|
| 977 |
+
if "search_topic" in state:
|
| 978 |
+
state["search_topic"] = f"{state['search_topic']} - Additional guidance: {instructions}"
|
| 979 |
+
|
| 980 |
def update_progress(msg):
|
| 981 |
progress(0.3, desc=msg)
|
| 982 |
|
|
|
|
| 998 |
|
| 999 |
return (
|
| 1000 |
state,
|
| 1001 |
+
f"## 🔍 Discovery Results (New Search)\n\n{candidates_text}\n\n**Optional:** Provide instructions in the textbox below if you want to reject again.",
|
| 1002 |
gr.update(visible=True),
|
| 1003 |
gr.update(visible=True),
|
| 1004 |
gr.update(visible=False),
|
| 1005 |
gr.update(visible=False),
|
| 1006 |
"",
|
| 1007 |
+
gr.update(visible=True) # Show instructions textbox
|
| 1008 |
)
|
| 1009 |
|
| 1010 |
def handle_checkpoint2_approve(state, progress=gr.Progress()):
|
|
|
|
| 1035 |
|
| 1036 |
return (
|
| 1037 |
state,
|
| 1038 |
+
f"## ✍️ Draft Post\n\n{draft}\n\n---\n\n**Quality Score:** {score}/10\n\n**Feedback:**\n{feedback}\n\n**Optional:** Provide specific edit instructions in the textbox below if needed.",
|
| 1039 |
gr.update(visible=True), # Finalize
|
| 1040 |
gr.update(visible=True), # Edit/Rewrite
|
| 1041 |
gr.update(visible=False),
|
|
|
|
| 1044 |
gr.update(visible=True) # Show edit instructions
|
| 1045 |
)
|
| 1046 |
|
| 1047 |
+
def handle_checkpoint2_different(state, instructions, progress=gr.Progress()):
|
| 1048 |
+
"""Request different story - re-run curator with optional instructions"""
|
| 1049 |
+
# Add instructions to curator's context if provided
|
| 1050 |
+
if instructions and instructions.strip():
|
| 1051 |
+
if "selected_story" in state:
|
| 1052 |
+
state["critic_feedback"] = f"User preference: {instructions}"
|
| 1053 |
+
|
| 1054 |
def update_progress(msg):
|
| 1055 |
progress(0.5, desc=msg)
|
| 1056 |
|
|
|
|
| 1072 |
|
| 1073 |
return (
|
| 1074 |
state,
|
| 1075 |
+
f"## 🎯 Selected Story (Alternative)\n\n{story_text}\n\n**Optional:** Provide instructions in the textbox below if you want a different story.",
|
| 1076 |
gr.update(visible=True),
|
| 1077 |
gr.update(visible=True),
|
| 1078 |
gr.update(visible=False),
|
| 1079 |
gr.update(visible=False),
|
| 1080 |
"",
|
| 1081 |
+
gr.update(visible=True) # Show instructions textbox
|
| 1082 |
)
|
| 1083 |
|
| 1084 |
def handle_checkpoint3_finalize(state, progress=gr.Progress()):
|
|
|
|
| 1316 |
return handle_checkpoint1_approve(s)
|
| 1317 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1318 |
|
| 1319 |
+
def route_checkpoint1_reject(s, instructions):
|
| 1320 |
if s and s.get("stage") == WorkflowStage.CHECKPOINT_1.value:
|
| 1321 |
+
return handle_checkpoint1_reject(s, instructions)
|
| 1322 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1323 |
|
| 1324 |
# Checkpoint 2 handlers
|
|
|
|
| 1327 |
return handle_checkpoint2_approve(s)
|
| 1328 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1329 |
|
| 1330 |
+
def route_checkpoint2_different(s, instructions):
|
| 1331 |
if s and s.get("stage") == WorkflowStage.CHECKPOINT_2.value:
|
| 1332 |
+
return handle_checkpoint2_different(s, instructions)
|
| 1333 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1334 |
|
| 1335 |
# Checkpoint 3 handlers
|
|
|
|
| 1344 |
return s, "Invalid state", gr.update(), gr.update(), gr.update(), gr.update(), instructions, gr.update()
|
| 1345 |
|
| 1346 |
# Wire up the routing based on current stage
|
| 1347 |
+
def smart_approve(s, instructions):
|
| 1348 |
if not s:
|
| 1349 |
return s, "No active workflow", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1350 |
|
|
|
|
| 1358 |
|
| 1359 |
return s, "Invalid stage for approval", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1360 |
|
| 1361 |
+
def smart_reject(s, instructions):
|
| 1362 |
if not s:
|
| 1363 |
return s, "No active workflow", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1364 |
|
| 1365 |
stage = s.get("stage")
|
| 1366 |
if stage == WorkflowStage.CHECKPOINT_1.value:
|
| 1367 |
+
return route_checkpoint1_reject(s, instructions)
|
| 1368 |
elif stage == WorkflowStage.CHECKPOINT_2.value:
|
| 1369 |
+
return route_checkpoint2_different(s, instructions)
|
| 1370 |
elif stage == WorkflowStage.CHECKPOINT_3.value:
|
| 1371 |
+
return route_checkpoint3_edit(s, instructions)
|
| 1372 |
|
| 1373 |
return s, "Invalid stage for rejection", gr.update(), gr.update(), gr.update(), gr.update(), "", gr.update()
|
| 1374 |
|
| 1375 |
approve_btn.click(
|
| 1376 |
fn=smart_approve,
|
| 1377 |
+
inputs=[state, edit_instructions],
|
| 1378 |
outputs=[state, output_display, approve_btn, reject_btn, start_btn, restart_btn, edit_instructions, edit_instructions]
|
| 1379 |
)
|
| 1380 |
|
| 1381 |
reject_btn.click(
|
| 1382 |
fn=smart_reject,
|
| 1383 |
+
inputs=[state, edit_instructions],
|
| 1384 |
outputs=[state, output_display, approve_btn, reject_btn, start_btn, restart_btn, edit_instructions, edit_instructions]
|
| 1385 |
)
|
| 1386 |
|