This document outlines a strategic plan for enhancing the VeritaScribe application. The project is currently in an excellent state, with a robust architecture that closely follows the initial project plan. Recent updates have added significant new capabilities, including multi-provider LLM support (OpenAI, OpenRouter, Anthropic) and robust JSON parsing to handle malformed API responses.
The following enhancements are designed to build on this strong foundation to:
- Add High-Impact Features: Introduce new capabilities that will significantly improve the value and user experience.
- Improve Robustness & Quality: Address potential shortcomings and strengthen the codebase to ensure reliability and maintainability.
- Align with Advanced Goals: Implement the advanced features envisioned in the original project plan.
Phase 1 High-Impact Features have been successfully implemented:
- Annotated PDF Output ✅ - Generate PDFs with highlighted errors and detailed annotations
- Cost and Token Usage Monitoring ✅ - Track LLM usage and estimate costs across all providers
- DSPy Prompt Optimization ✅ - Multi-language few-shot learning for improved analysis accuracy
All features are now fully integrated into the VeritaScribe pipeline and available through the CLI.
- Goal: Generate a copy of the analyzed PDF with errors highlighted and explained directly on the page, providing highly contextual and actionable feedback.
- Current Status: ✅ IMPLEMENTED. Annotated PDFs can be generated using the
--annotateflag. Errors are highlighted with severity-based colors (red, orange, yellow) and include detailed sticky note annotations with explanations and suggestions. - Relevance: High-impact, user-facing feature that greatly improves the usability of the tool.
-
New Function in
report_generator.py:- Create a new method:
generate_annotated_pdf(self, report: ThesisAnalysisReport, original_pdf_path: str, output_path: str).
- Create a new method:
-
Implementation Logic:
- Open the
original_pdf_pathusingfitz.open(). - Iterate through each
AnalysisResultinreport.analysis_results. - For each
BaseErrorwithin anAnalysisResult:- Use
error.location.page_numberto get the correctfitz.Pageobject. - Use
error.location.bounding_boxto define afitz.Rect. - Highlight Error: Add a highlight annotation using
page.add_highlight_annot(rect). The color can be conditional onerror.severity(e.g., red for high, yellow for medium). - Add Comment: Add a "Sticky Note" or "Text" annotation next to the highlight using
page.add_text_annot()orpage.add_stamp_annot(). The annotation's text content should include theerror_type,explanation, andsuggested_correction.
- Use
- Save the modified document to the
output_pathusingdoc.save().
- Open the
-
CLI Integration (
main.py):- Add a new option to the
analyzecommand:--annotate-pdf: bool = typer.Option(False, "--annotate", help="Generate an annotated PDF with highlighted errors."). - If this flag is set, call the new
generate_annotated_pdffunction.
- Add a new option to the
- Goal: Leverage
dspy.telepromptto automatically generate few-shot examples and optimize prompts, improving the accuracy and reliability of the LLM analysis. - Current Status: ✅ IMPLEMENTED with multi-language support. The system now includes language-aware training data, automatic language detection, and compilation script for optimizing prompts using few-shot learning. Supports English and German analysis with extensible architecture for additional languages.
- Relevance: Core DSPy feature that significantly improves analysis quality through optimized prompts.
-
Create a "Gold Standard" Dataset:
- Create a new file:
src/veritascribe/training_data.py. - Define a small list (5-10 examples) of
dspy.Exampleobjects for each analysis module (LinguisticAnalyzer,ContentValidator). - Each example should contain a representative
text_chunkand the ideal, validated JSON output for thegrammar_errorsorcontent_errorsfield.
- Create a new file:
-
Implement a Compilation Script:
- Create a new script, e.g.,
scripts/compile_modules.py. - This script will:
- Load the training data.
- Initialize the DSPy modules.
- Define a simple validation metric, e.g.,
lambda gold, pred, trace: dspy.evaluate.metrics.answer_exact_match(gold, pred). - Use
dspy.teleprompt.BootstrapFewShot(metric=...)to create a teleprompter. - Compile each analysis module using
teleprompter.compile(module, trainset=...). - Save the compiled modules to disk, e.g.,
compiled_linguistic_analyzer.json.
- Create a new script, e.g.,
-
Update Module Loading:
- In
llm_modules.py, modify theAnalysisOrchestratorto load the compiled modules usingmodule.load()if they exist. This avoids re-compiling on every run.
- In
- Goal: Track and report the token usage and estimated cost associated with each analysis run.
- Current Status: ✅ IMPLEMENTED. Token usage and cost estimation is now tracked for all analysis runs and displayed in reports and CLI output. Pricing information is included for all supported providers (OpenAI, OpenRouter, Anthropic, Custom).
- Relevance: Highly relevant feature for managing costs across multiple LLM providers.
-
Update
ThesisAnalysisReportData Model:- In
data_models.py, add the following fields toThesisAnalysisReport:token_usage: Optional[Dict[str, int]] = Noneestimated_cost: Optional[float] = None
- In
-
Add Pricing Information to
config.py:- Extend the
PROVIDER_MODELSdictionary to include pricing information (e.g.,cost_per_prompt_token,cost_per_completion_token) for each model.
- Extend the
-
Implement Calculation Logic in
pipeline.py:- After an analysis run is complete, inspect the
dspy.settings.lm.historyobject. - Create a new private method in
ThesisAnalysisPipeline, e.g.,_calculate_llm_usage(self) -> Tuple[Dict, float]. - This method will iterate through
dspy.settings.lm.history, sum theprompt_tokensandcompletion_tokens, and calculate the total cost using the pricing information from theconfig. - Clear the history (
dspy.settings.lm.history.clear()) after calculation.
- After an analysis run is complete, inspect the
-
Integrate into Pipeline and Reports:
- Call
_calculate_llm_usageat the end of theanalyze_thesismethod and populate the new fields in theThesisAnalysisReport. - Update
report_generator.pyand the CLI summary inmain.pyto display the token usage and estimated cost.
- Call
- Goal: Make LLM API calls more resilient to transient network errors or rate limiting.
- Current Status:
max_retriesandretry_delayare defined inconfig.pybut are not used. - Relevance: Still highly relevant. The new
safe_json_parsefunction handles malformed responses, but this does not address API-level failures.
-
Add Dependency:
- Run
uv add backoff.
- Run
-
Implement Retry Logic in
llm_modules.py:- Modify the
forwardmethod in each analysis module (LinguisticAnalyzer,ContentValidator,CitationChecker). - Apply a
@backoff.on_exception(...)decorator to theself.analyzer(...)call. - Configure the decorator to use
self.settings.max_retriesandself.settings.retry_delay. - Catch specific, retry-able exceptions from the underlying LLM libraries (e.g.,
openai.RateLimitError,openai.APIConnectionError,anthropic.APIConnectionError).
- Modify the
- Goal: Create a formal test suite to ensure code quality, prevent regressions, and enable confident refactoring.
- Current Status: No formal test suite exists. The
veritascribe testcommand is a simple smoke test. - Relevance: Still highly relevant and critical for long-term maintainability.
-
Add Dependency and Configure:
- Run
uv add pytest. - Create a
tests/directory in the project root. - In
pyproject.toml, add[tool.pytest.ini_options]and settestpaths = ["tests"].
- Run
-
Write Unit Tests:
tests/test_pdf_processor.py: Test helper functions like_clean_extracted_textand_is_header_footer_or_page_number.tests/test_data_models.py: Test Pydantic model validation and calculated properties.tests/test_report_generator.py: Test the_generate_recommendationlogic.tests/test_pipeline.py: Write an integration test that runs thequick_analyzepipeline on a test PDF.
-
Update
CLAUDE.md:- Change the testing command from
veritascribe testtouv run pytest.
- Change the testing command from
- Goal: Make the bibliography extraction process more robust.
- Current Status: The current implementation uses a simple regex search for section headers.
- Relevance: Still relevant. A more robust implementation would improve the accuracy of citation analysis.
- Enhance
extract_bibliography_sectioninpdf_processor.py:- Modify the function to use
page.get_text("dict")to get font and positional information. - Identify Start: Find the "References" or "Bibliography" header.
- Collect Content: Iterate through text blocks on that page and subsequent pages.
- Identify End: The bibliography section likely ends when a new major header (e.g., "Appendix") with a larger font size is found.
- Modify the function to use