returncontext,"\n".join(abstraction_info_for_prompt),project_name# Return project name
defexec(self,prep_res):
context,abstraction_listing,project_name=prep_res# Unpack project name
print("Analyzing relationships using LLM...")
prompt=f"""
Based on the following abstractions and relevant code snippets from the project `{project_name}`:
List of Abstraction Indices and Names:
{abstraction_listing}
Context (Abstractions, Descriptions, Code):
{context}
Please provide:
1. A high-level `summary` of the project's main purpose and functionality in a few beginner-friendly sentences. Use markdown formatting with **bold** and *italic* text to highlight important concepts.
2. A list (`relationships`) describing the key interactions between these abstractions. For each relationship, specify:
- `from_abstraction`: Index of the source abstraction (e.g., `0 # AbstractionName1`)
- `to_abstraction`: Index of the target abstraction (e.g., `1 # AbstractionName2`)
- `label`: A brief label for the interaction **in just a few words** (e.g., "Manages", "Inherits", "Uses").
Ideally the relationship should be backed by one abstraction calling or passing parameters to another.
Simplify the relationship and exclude those non-important ones.
IMPORTANT: Make sure EVERY abstraction is involved in at least ONE relationship (either as source or target). Each abstraction index must appear at least once across all relationships.
Format the output as YAML:
```yaml
summary: |
A brief, simple explanation of the project.
Can span multiple lines with **bold** and *italic* for emphasis.
Given the following project abstractions and their relationships for the project ```` {project_name} ````:
Abstractions (Index # Name):
{abstraction_listing}
Context about relationships and project summary:
{context}
If you are going to make a tutorial for ```` {project_name} ````, what is the best order to explain these abstractions, from first to last?
Ideally, first explain those that are the most important or foundational, perhaps user-facing concepts or entry points. Then move to more detailed, lower-level implementation details or supporting concepts.
Output the ordered list of abstraction indices, including the name in a comment for clarity. Use the format `idx # AbstractionName`.
raiseValueError(f"Invalid index {idx} in ordered list. Max index is {num_abstractions-1}.")
ifidxinseen_indices:
raiseValueError(f"Duplicate index {idx} found in ordered list.")
ordered_indices.append(idx)
seen_indices.add(idx)
except(ValueError,TypeError):
raiseValueError(f"Could not parse index from ordered list entry: {entry}")
# Check if all abstractions are included
iflen(ordered_indices)!=num_abstractions:
raiseValueError(f"Ordered list length ({len(ordered_indices)}) does not match number of abstractions ({num_abstractions}). Missing indices: {set(range(num_abstractions))-seen_indices}")
print(f"Determined chapter order (indices): {ordered_indices}")
returnordered_indices# Return the list of indices
defpost(self,shared,prep_res,exec_res):
# exec_res is already the list of ordered indices
shared["chapter_order"]=exec_res# List of indices
classWriteChapters(BatchNode):
defprep(self,shared):
chapter_order=shared["chapter_order"]# List of indices
abstractions=shared["abstractions"]# List of dicts, now using 'files' with indices
files_data=shared["files"]
# Get already written chapters to provide context
# We store them temporarily during the batch run, not in shared memory yet
# The 'previous_chapters_summary' will be built progressively in the exec context
self.chapters_written_so_far=[]# Use instance variable for temporary storage across exec calls
# Create a complete list of all chapters
all_chapters=[]
chapter_filenames={}# Store chapter filename mapping for linking
Write a very beginner-friendly tutorial chapter (in Markdown format) for the project `{project_name}` about the concept: "{abstraction_name}". This is Chapter {chapter_num}.
Concept Details:
- Description:
{item["abstraction_details"]["description"]}
Complete Tutorial Structure:
{item["full_chapter_listing"]}
Context from previous chapters (summary):
{previous_chapters_summaryifprevious_chapters_summaryelse"This is the first chapter."}
Relevant Code Snippets:
{file_context_striffile_context_strelse"No specific code snippets provided for this abstraction."}
Instructions for the chapter:
- Start with a clear heading (e.g., `# Chapter {chapter_num}: {abstraction_name}`).
- If this is not the first chapter, begin with a brief transition from the previous chapter, referencing it with a proper Markdown link.
- Begin with a high-level motivation explaining what problem this abstraction solves. Start with a central use case as a concrete example. The whole chapter should guide the reader to understand how to solve this use case. Make it very minimal and friendly to beginners.
- If the abstraction is complex, break it down into key concepts. Explain each concept one-by-one in a very beginner-friendly way.
- Explain how to use this abstraction to solve the use case. Give example inputs and outputs for code snippets (if the output isn't values, describe at a high level what will happen).
- Each code block should be BELOW 20 lines! If longer code blocks are needed, break them down into smaller pieces and walk through them one-by-one. Aggresively simplify the code to make it minimal. Use comments to skip non-important implementation details. Each code block should have a beginner friendly explanation right after it.
- Describe the internal implementation to help understand what's under the hood. First provide a non-code or code-light walkthrough on what happens step-by-step when the abstraction is called. It's recommended to use a simple sequenceDiagram with a dummy example - keep it minimal with at most 5 participants to ensure clarity. If participant name has space, use:
`participant QP as Query Processing`
- Then dive deeper into code for the internal implementation with references to files. Provide example code blocks, but make them similarly simple and beginner-friendly.
- IMPORTANT: When you need to refer to other core abstractions covered in other chapters, ALWAYS use proper Markdown links like this: [Chapter Title](filename.md). Use the Complete Tutorial Structure above to find the correct filename. Example: "we will talk about [Query Processing](03_query_processing.md) in Chapter 3".
- Use mermaid diagrams to illustrate complex concepts (```mermaid``` format).
- Heavily use analogies and examples throughout to help beginners understand.
- End the chapter with a brief conclusion that summarizes what was learned and provides a transition to the next chapter. If there is a next chapter, use a proper Markdown link: [Next Chapter Title](next_chapter_filename).
- Ensure the tone is welcoming and easy for a newcomer to understand.
- Output *only* the Markdown content for this chapter.
Now, directly provide a super beginner-friendly Markdown output (DON'T need ```markdown``` tags):
print(f"Warning: Mismatch between chapter order, abstractions, or content at index {i} (abstraction index {abstraction_index}). Skipping file generation for this entry.")
# Add attribution to index content
index_content+="\n\n---\n\nGenerated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)"
return{
"output_path":output_path,
"index_content":index_content,
"chapter_files":chapter_files# List of {"filename": str, "content": str}
}
defexec(self,prep_res):
output_path=prep_res["output_path"]
index_content=prep_res["index_content"]
chapter_files=prep_res["chapter_files"]
print(f"Combining tutorial into directory: {output_path}")