OPEN SOURCE
software/src/context/builder.py
Read on this site and download the files you need.
Nichijoyaku was created using AI. A complete review by human biblical-language and biblical-studies specialists has not been established. Read alongside established translations and original-language resources.
← Back to the open-source guide
1"""Context builder for translation prompts."""23from __future__ import annotations45from src.context.glossary import GlossaryManager6from src.context.pericope import PericopeManager7from src.data.loader import DataLoader8from src.models.pericope import ChunkTranslationContext, Pericope9from src.models.verse import TranslationContext, Verse, VerseReference101112class ContextBuilder:13"""Builds translation context for verses and chunks."""1415def __init__(16self,17loader: DataLoader,18glossary: GlossaryManager,19context_window: int = 3,20pericope_manager: PericopeManager | None = None,21) -> None:22"""Initialize the context builder.2324Args:25loader: Data loader for source texts.26glossary: Glossary manager for theological terms.27context_window: Number of verses before/after to include.28pericope_manager: Optional pericope manager for chunk translation.29"""30self.loader = loader31self.glossary = glossary32self.context_window = context_window33self.pericope_manager = pericope_manager or PericopeManager()3435def build_context(self, reference: VerseReference) -> TranslationContext:36"""Build full translation context for a verse.3738Args:39reference: The verse reference to build context for.4041Returns:42TranslationContext with all available context.43"""44# Load the target verse45target_verse = self.loader.load_verse(reference)4647# Load surrounding verses48preceding = self._get_preceding_verses(reference)49following = self._get_following_verses(reference)5051# Load chapter summary52chapter_summary = self.loader.load_chapter_summary(53reference.book, reference.chapter54)5556# Load book metadata57book_metadata = self.loader.load_book_metadata(reference.book)5859# Find relevant glossary terms from the source text60glossary_terms = self._find_relevant_terms(target_verse)6162return TranslationContext(63target_verse=target_verse,64preceding_verses=preceding,65following_verses=following,66chapter_summary=chapter_summary,67book_metadata=book_metadata,68glossary_terms=glossary_terms,69)7071def _get_preceding_verses(self, reference: VerseReference) -> list[Verse]:72"""Get verses preceding the target verse."""73verses = []74book = reference.book75chapter = reference.chapter76verse_num = reference.verse7778for i in range(self.context_window, 0, -1):79target_verse = verse_num - i80if target_verse >= 1:81ref = VerseReference(book=book, chapter=chapter, verse=target_verse)82verse = self.loader.load_verse(ref)83# Only include if verse has content84if verse.has_source_text() or verse.english_kjv:85verses.append(verse)8687return verses8889def _get_following_verses(self, reference: VerseReference) -> list[Verse]:90"""Get verses following the target verse."""91verses = []92book = reference.book93chapter = reference.chapter94verse_num = reference.verse9596for i in range(1, self.context_window + 1):97target_verse = verse_num + i98ref = VerseReference(book=book, chapter=chapter, verse=target_verse)99verse = self.loader.load_verse(ref)100# Only include if verse has content101if verse.has_source_text() or verse.english_kjv:102verses.append(verse)103104return verses105106def _find_relevant_terms(self, verse: Verse) -> list:107"""Find glossary terms relevant to a verse."""108terms = []109110# Search in Greek text111if verse.greek_text:112terms.extend(self.glossary.find_terms_in_text(verse.greek_text))113114# Search in Greek transliteration115if verse.greek_translit:116for term in self.glossary.find_terms_in_text(verse.greek_translit):117if term not in terms:118terms.append(term)119120# Search in Hebrew text121if verse.hebrew_text:122for term in self.glossary.find_terms_in_text(verse.hebrew_text):123if term not in terms:124terms.append(term)125126return terms127128def build_chunk_context(129self, book: str, pericope: Pericope130) -> ChunkTranslationContext:131"""Build full translation context for a pericope/chunk.132133Args:134book: Book name.135pericope: The pericope to build context for.136137Returns:138ChunkTranslationContext with all available context.139"""140# Load all verses in the pericope141verses = []142for verse_ref in pericope.verses:143chapter, verse_num = map(int, verse_ref.split(":"))144ref = VerseReference(book=book, chapter=chapter, verse=verse_num)145verse = self.loader.load_verse(ref)146verses.append(verse)147148# Load preceding context (verses before first verse)149preceding = self._get_chunk_preceding_verses(book, pericope)150151# Load following context (verses after last verse)152following = self._get_chunk_following_verses(book, pericope)153154# Load chapter summary (use first chapter)155chapter_summary = self.loader.load_chapter_summary(156book, pericope.start_chapter157)158159# Load book metadata160book_metadata = self.loader.load_book_metadata(book)161162# Find glossary terms from all verses163glossary_terms = self._find_chunk_terms(verses)164165return ChunkTranslationContext(166pericope=pericope,167book=book,168verses=verses,169preceding_verses=preceding,170following_verses=following,171chapter_summary=chapter_summary,172book_metadata=book_metadata,173glossary_terms=glossary_terms,174)175176def build_chunk_context_by_id(177self, pericope_id: str178) -> ChunkTranslationContext | None:179"""Build chunk context by pericope ID.180181Args:182pericope_id: The pericope identifier.183184Returns:185ChunkTranslationContext or None if pericope not found.186"""187result = self.pericope_manager.get_pericope_by_id(pericope_id)188if result is None:189return None190191book, pericope = result192return self.build_chunk_context(book, pericope)193194def build_chunk_context_for_verse(195self, reference: VerseReference196) -> ChunkTranslationContext | None:197"""Build chunk context for the pericope containing a verse.198199Args:200reference: Verse reference.201202Returns:203ChunkTranslationContext or None if no pericope found.204"""205pericope = self.pericope_manager.get_pericope(206reference.book, reference.chapter, reference.verse207)208if pericope is None:209return None210211return self.build_chunk_context(reference.book, pericope)212213def _get_chunk_preceding_verses(214self, book: str, pericope: Pericope215) -> list[Verse]:216"""Get verses preceding the pericope for context."""217verses = []218chapter = pericope.start_chapter219verse_num = pericope.start_verse220221for i in range(self.context_window, 0, -1):222target_verse = verse_num - i223if target_verse >= 1:224ref = VerseReference(book=book, chapter=chapter, verse=target_verse)225verse = self.loader.load_verse(ref)226if verse.has_source_text() or verse.english_kjv:227verses.append(verse)228229return verses230231def _get_chunk_following_verses(232self, book: str, pericope: Pericope233) -> list[Verse]:234"""Get verses following the pericope for context."""235verses = []236chapter = pericope.end_chapter237verse_num = pericope.end_verse238239for i in range(1, self.context_window + 1):240target_verse = verse_num + i241ref = VerseReference(book=book, chapter=chapter, verse=target_verse)242verse = self.loader.load_verse(ref)243if verse.has_source_text() or verse.english_kjv:244verses.append(verse)245246return verses247248def _find_chunk_terms(self, verses: list[Verse]) -> list:249"""Find glossary terms relevant to all verses in a chunk."""250terms = []251seen = set()252253for verse in verses:254verse_terms = self._find_relevant_terms(verse)255for term in verse_terms:256if term.original not in seen:257terms.append(term)258seen.add(term.original)259260return terms261