mirror of
https://github.com/The-Pocket/PocketFlow-Tutorial-Codebase-Knowledge.git
synced 2026-08-29 08:34:31 +08:00
Add language parameter for multi-language support
This commit is contained in:
@@ -2,7 +2,7 @@ import os
|
|||||||
import yaml
|
import yaml
|
||||||
from pocketflow import Node, BatchNode
|
from pocketflow import Node, BatchNode
|
||||||
from utils.crawl_github_files import crawl_github_files
|
from utils.crawl_github_files import crawl_github_files
|
||||||
from utils.call_llm import call_llm
|
from utils.call_llm import call_llm
|
||||||
from utils.crawl_local_files import crawl_local_files
|
from utils.crawl_local_files import crawl_local_files
|
||||||
|
|
||||||
# Helper to get content for specific file indices
|
# Helper to get content for specific file indices
|
||||||
@@ -19,7 +19,7 @@ class FetchRepo(Node):
|
|||||||
repo_url = shared.get("repo_url")
|
repo_url = shared.get("repo_url")
|
||||||
local_dir = shared.get("local_dir")
|
local_dir = shared.get("local_dir")
|
||||||
project_name = shared.get("project_name")
|
project_name = shared.get("project_name")
|
||||||
|
|
||||||
if not project_name:
|
if not project_name:
|
||||||
# Basic name derivation from URL or directory
|
# Basic name derivation from URL or directory
|
||||||
if repo_url:
|
if repo_url:
|
||||||
@@ -63,7 +63,7 @@ class FetchRepo(Node):
|
|||||||
max_file_size=prep_res["max_file_size"],
|
max_file_size=prep_res["max_file_size"],
|
||||||
use_relative_paths=prep_res["use_relative_paths"]
|
use_relative_paths=prep_res["use_relative_paths"]
|
||||||
)
|
)
|
||||||
|
|
||||||
# Convert dict to list of tuples: [(path, content), ...]
|
# Convert dict to list of tuples: [(path, content), ...]
|
||||||
files_list = list(result.get("files", {}).items())
|
files_list = list(result.get("files", {}).items())
|
||||||
print(f"Fetched {len(files_list)} files.")
|
print(f"Fetched {len(files_list)} files.")
|
||||||
@@ -76,7 +76,7 @@ class IdentifyAbstractions(Node):
|
|||||||
def prep(self, shared):
|
def prep(self, shared):
|
||||||
files_data = shared["files"]
|
files_data = shared["files"]
|
||||||
project_name = shared["project_name"] # Get project name
|
project_name = shared["project_name"] # Get project name
|
||||||
|
|
||||||
# Helper to create context from files, respecting limits (basic example)
|
# Helper to create context from files, respecting limits (basic example)
|
||||||
def create_llm_context(files_data):
|
def create_llm_context(files_data):
|
||||||
context = ""
|
context = ""
|
||||||
@@ -117,7 +117,7 @@ Format the output as a YAML list of dictionaries:
|
|||||||
|
|
||||||
```yaml
|
```yaml
|
||||||
- name: Query Processing
|
- name: Query Processing
|
||||||
description: |
|
description: |
|
||||||
Explains what the abstraction does.
|
Explains what the abstraction does.
|
||||||
It's like a central dispatcher routing requests.
|
It's like a central dispatcher routing requests.
|
||||||
file_indices:
|
file_indices:
|
||||||
@@ -286,7 +286,7 @@ Now, provide the YAML output:
|
|||||||
validated_relationships.append({
|
validated_relationships.append({
|
||||||
"from": from_idx,
|
"from": from_idx,
|
||||||
"to": to_idx,
|
"to": to_idx,
|
||||||
"label": rel["label"]
|
"label": rel["label"]
|
||||||
})
|
})
|
||||||
except (ValueError, TypeError):
|
except (ValueError, TypeError):
|
||||||
raise ValueError(f"Could not parse indices from relationship: {rel}")
|
raise ValueError(f"Could not parse indices from relationship: {rel}")
|
||||||
@@ -416,7 +416,7 @@ class WriteChapters(BatchNode):
|
|||||||
all_chapters.append(f"{chapter_num}. [{chapter_name}]({filename})")
|
all_chapters.append(f"{chapter_num}. [{chapter_name}]({filename})")
|
||||||
# Store mapping of chapter index to filename for linking
|
# Store mapping of chapter index to filename for linking
|
||||||
chapter_filenames[abstraction_index] = {"num": chapter_num, "name": chapter_name, "filename": filename}
|
chapter_filenames[abstraction_index] = {"num": chapter_num, "name": chapter_name, "filename": filename}
|
||||||
|
|
||||||
# Create a formatted string with all chapters
|
# Create a formatted string with all chapters
|
||||||
full_chapter_listing = "\n".join(all_chapters)
|
full_chapter_listing = "\n".join(all_chapters)
|
||||||
|
|
||||||
@@ -428,19 +428,22 @@ class WriteChapters(BatchNode):
|
|||||||
related_file_indices = abstraction_details.get("files", [])
|
related_file_indices = abstraction_details.get("files", [])
|
||||||
# Get content using helper, passing indices
|
# Get content using helper, passing indices
|
||||||
related_files_content_map = get_content_for_indices(files_data, related_file_indices)
|
related_files_content_map = get_content_for_indices(files_data, related_file_indices)
|
||||||
|
|
||||||
# Get previous chapter info for transitions
|
# Get previous chapter info for transitions
|
||||||
prev_chapter = None
|
prev_chapter = None
|
||||||
if i > 0:
|
if i > 0:
|
||||||
prev_idx = chapter_order[i-1]
|
prev_idx = chapter_order[i-1]
|
||||||
prev_chapter = chapter_filenames[prev_idx]
|
prev_chapter = chapter_filenames[prev_idx]
|
||||||
|
|
||||||
# Get next chapter info for transitions
|
# Get next chapter info for transitions
|
||||||
next_chapter = None
|
next_chapter = None
|
||||||
if i < len(chapter_order) - 1:
|
if i < len(chapter_order) - 1:
|
||||||
next_idx = chapter_order[i+1]
|
next_idx = chapter_order[i+1]
|
||||||
next_chapter = chapter_filenames[next_idx]
|
next_chapter = chapter_filenames[next_idx]
|
||||||
|
|
||||||
|
# Get language from shared store, default to English
|
||||||
|
language = shared.get("language", "english")
|
||||||
|
|
||||||
items_to_process.append({
|
items_to_process.append({
|
||||||
"chapter_num": i + 1,
|
"chapter_num": i + 1,
|
||||||
"abstraction_index": abstraction_index,
|
"abstraction_index": abstraction_index,
|
||||||
@@ -451,6 +454,7 @@ class WriteChapters(BatchNode):
|
|||||||
"chapter_filenames": chapter_filenames, # Add chapter filenames mapping
|
"chapter_filenames": chapter_filenames, # Add chapter filenames mapping
|
||||||
"prev_chapter": prev_chapter, # Add previous chapter info
|
"prev_chapter": prev_chapter, # Add previous chapter info
|
||||||
"next_chapter": next_chapter, # Add next chapter info
|
"next_chapter": next_chapter, # Add next chapter info
|
||||||
|
"language": language, # Add language for multi-language support
|
||||||
# previous_chapters_summary will be added dynamically in exec
|
# previous_chapters_summary will be added dynamically in exec
|
||||||
})
|
})
|
||||||
else:
|
else:
|
||||||
@@ -476,8 +480,16 @@ class WriteChapters(BatchNode):
|
|||||||
# Use the temporary instance variable
|
# Use the temporary instance variable
|
||||||
previous_chapters_summary = "\n---\n".join(self.chapters_written_so_far)
|
previous_chapters_summary = "\n---\n".join(self.chapters_written_so_far)
|
||||||
|
|
||||||
|
# Get language from item, default to English
|
||||||
|
language = item.get("language", "english")
|
||||||
|
|
||||||
|
# Add language instruction if not English
|
||||||
|
language_instruction = ""
|
||||||
|
if language.lower() != "english":
|
||||||
|
language_instruction = f"Write this tutorial chapter in {language}. Ensure all explanations, examples, and comments are in {language}.\n\n"
|
||||||
|
|
||||||
prompt = f"""
|
prompt = f"""
|
||||||
|
{language_instruction}
|
||||||
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}.
|
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:
|
Concept Details:
|
||||||
@@ -502,11 +514,11 @@ Instructions for the chapter:
|
|||||||
|
|
||||||
- If the abstraction is complex, break it down into key concepts. Explain each concept one-by-one in a very beginner-friendly way.
|
- 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).
|
- 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.
|
- 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:
|
- 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`
|
`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.
|
- 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.
|
||||||
@@ -610,13 +622,13 @@ class CombineTutorial(Node):
|
|||||||
# Use chapter number (i+1) for ordering filename
|
# Use chapter number (i+1) for ordering filename
|
||||||
filename = f"{i+1:02d}_{safe_name}.md"
|
filename = f"{i+1:02d}_{safe_name}.md"
|
||||||
index_content += f"{i+1}. [{abstraction_name}]({filename})\n"
|
index_content += f"{i+1}. [{abstraction_name}]({filename})\n"
|
||||||
|
|
||||||
# Add attribution to chapter content
|
# Add attribution to chapter content
|
||||||
chapter_content = chapters_content[i]
|
chapter_content = chapters_content[i]
|
||||||
if not chapter_content.endswith("\n\n"):
|
if not chapter_content.endswith("\n\n"):
|
||||||
chapter_content += "\n\n"
|
chapter_content += "\n\n"
|
||||||
chapter_content += "---\n\nGenerated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)"
|
chapter_content += "---\n\nGenerated by [AI Codebase Knowledge Builder](https://github.com/The-Pocket/Tutorial-Codebase-Knowledge)"
|
||||||
|
|
||||||
# Store filename and corresponding content
|
# Store filename and corresponding content
|
||||||
chapter_files.append({"filename": filename, "content": chapter_content})
|
chapter_files.append({"filename": filename, "content": chapter_content})
|
||||||
else:
|
else:
|
||||||
@@ -658,4 +670,4 @@ class CombineTutorial(Node):
|
|||||||
|
|
||||||
def post(self, shared, prep_res, exec_res):
|
def post(self, shared, prep_res, exec_res):
|
||||||
shared["final_output_dir"] = exec_res # Store the output path
|
shared["final_output_dir"] = exec_res # Store the output path
|
||||||
print(f"\nTutorial generation complete! Files are in: {exec_res}")
|
print(f"\nTutorial generation complete! Files are in: {exec_res}")
|
||||||
|
|||||||
Reference in New Issue
Block a user