| |
| from concurrent.futures import ThreadPoolExecutor |
| from crewai import Crew, Process |
| from .content_crew_config import safe_run_cached |
| from agents.content_phase import ( |
| course_writer_agent, |
| course_writer_task, |
| ) |
|
|
| MAX_UNIT_WORKERS = 3 |
|
|
|
|
| def process_unit(unit: dict, course_title: str) -> dict: |
| output_unit = { |
| "unit_name": unit["unit_name"], |
| "unit_outcome": unit["outcome"], |
| "topics": [], |
| } |
|
|
| |
| agent = course_writer_agent() |
| task = course_writer_task(agent) |
| cached_crew = Crew( |
| agents=[agent], |
| tasks=[task], |
| process=Process.sequential, |
| memory=False, |
| verbose=False, |
| ) |
|
|
| for topic in unit["topics"]: |
| topic_entry = {"topic_title": topic["title"], "subtopics": []} |
|
|
| |
| for sub in topic["subtopics"]: |
| combined_scraped = "\n\n".join( |
| r.get("scraped_content", "")[:1500] |
| for r in sub.get("results", []) |
| if "scraped_content" in r |
| ) |
|
|
| inputs = { |
| "course_title": course_title, |
| "unit_title": unit["unit_name"], |
| "topic_title": topic["title"], |
| "subtopic_title": sub["title"], |
| "subtopic_description": sub["description"], |
| "combined_scraped_texts": combined_scraped, |
| } |
|
|
| print(f"๐ข Writing: {sub['title']}") |
|
|
|
|
| generated, used_sources = safe_run_cached(inputs, cached_crew=cached_crew) |
|
|
| topic_entry["subtopics"].append( |
| { |
| "title": sub["title"], |
| "description": sub["description"], |
| "generated_content": generated, |
| "sources": used_sources, |
| } |
| ) |
|
|
| output_unit["topics"].append(topic_entry) |
|
|
| return output_unit |
|
|
|
|
| def generate_course_content(course_data: dict) -> dict: |
| """ |
| ุฏู ุงููู ูุชูุงุฏููุง ู
ู ุงูู FastAPI |
| course_data ุดูููุง ุฒู ุงููู ูุงู ูู ุงููุงูู: |
| { |
| "course_name": ..., |
| "course_audience": ..., |
| "units": [...] |
| } |
| """ |
| units = course_data["units"] |
| final_results_ordered = [None] * len(units) |
|
|
| futures = [] |
| with ThreadPoolExecutor(max_workers=MAX_UNIT_WORKERS) as executor: |
| for idx, unit in enumerate(units): |
| future = executor.submit(process_unit, unit, course_data["course_name"]) |
| futures.append((idx, future)) |
|
|
| for idx, future in futures: |
| final_results_ordered[idx] = future.result() |
|
|
| output = { |
| "course_name": course_data["course_name"], |
| "course_audience": course_data["course_audience"], |
| "results": final_results_ordered, |
| } |
|
|
| return output |
|
|