vbagent 0.2.0__tar.gz → 0.2.1__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (86) hide show
  1. {vbagent-0.2.0 → vbagent-0.2.1}/PKG-INFO +1 -1
  2. {vbagent-0.2.0 → vbagent-0.2.1}/pyproject.toml +1 -1
  3. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/base.py +4 -1
  4. vbagent-0.2.1/vbagent/agents/classifier.py +68 -0
  5. vbagent-0.2.1/vbagent/agents/compile_fixer.py +57 -0
  6. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/scanner.py +38 -14
  7. vbagent-0.2.1/vbagent/cli/config.py +425 -0
  8. vbagent-0.2.1/vbagent/cli/init.py +248 -0
  9. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/main.py +15 -5
  10. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/process.py +34 -0
  11. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/scan.py +27 -1
  12. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/tikz.py +29 -1
  13. vbagent-0.2.1/vbagent/cli/util.py +327 -0
  14. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/variant.py +27 -0
  15. vbagent-0.2.1/vbagent/compile.py +444 -0
  16. vbagent-0.2.1/vbagent/config.py +665 -0
  17. vbagent-0.2.1/vbagent/prompts/classifier.py +65 -0
  18. vbagent-0.2.1/vbagent/prompts/scanner/__init__.py +136 -0
  19. vbagent-0.2.1/vbagent/prompts/subjects/__init__.py +328 -0
  20. vbagent-0.2.0/vbagent/agents/classifier.py +0 -39
  21. vbagent-0.2.0/vbagent/cli/config.py +0 -191
  22. vbagent-0.2.0/vbagent/config.py +0 -291
  23. vbagent-0.2.0/vbagent/prompts/classifier.py +0 -31
  24. vbagent-0.2.0/vbagent/prompts/scanner/__init__.py +0 -71
  25. {vbagent-0.2.0 → vbagent-0.2.1}/README.md +0 -0
  26. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/__init__.py +0 -0
  27. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/__init__.py +0 -0
  28. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/alternate.py +0 -0
  29. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/clarity_checker.py +0 -0
  30. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/converter.py +0 -0
  31. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/grammar_checker.py +0 -0
  32. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/idea.py +0 -0
  33. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/multi_variant.py +0 -0
  34. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/reviewer.py +0 -0
  35. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/selector.py +0 -0
  36. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/solution_checker.py +0 -0
  37. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/tikz.py +0 -0
  38. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/tikz_checker.py +0 -0
  39. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/agents/variant.py +0 -0
  40. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/__init__.py +0 -0
  41. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/alternate.py +0 -0
  42. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/batch.py +0 -0
  43. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/check.py +0 -0
  44. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/classify.py +0 -0
  45. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/common.py +0 -0
  46. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/convert.py +0 -0
  47. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/idea.py +0 -0
  48. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/cli/ref.py +0 -0
  49. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/__init__.py +0 -0
  50. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/batch.py +0 -0
  51. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/classification.py +0 -0
  52. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/diff.py +0 -0
  53. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/idea.py +0 -0
  54. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/pipeline.py +0 -0
  55. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/review.py +0 -0
  56. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/scan.py +0 -0
  57. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/models/version_store.py +0 -0
  58. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/__init__.py +0 -0
  59. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/alternate.py +0 -0
  60. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/clarity_checker.py +0 -0
  61. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/converter.py +0 -0
  62. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/grammar_checker.py +0 -0
  63. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/idea.py +0 -0
  64. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/reviewer.py +0 -0
  65. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/assertion_reason.py +0 -0
  66. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/common.py +0 -0
  67. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/match.py +0 -0
  68. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/mcq_mc.py +0 -0
  69. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/mcq_sc.py +0 -0
  70. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/passage.py +0 -0
  71. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/scanner/subjective.py +0 -0
  72. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/solution_checker.py +0 -0
  73. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/tikz.py +0 -0
  74. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/tikz_checker.py +0 -0
  75. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/__init__.py +0 -0
  76. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/conceptual.py +0 -0
  77. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/conceptual_calculus.py +0 -0
  78. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/context.py +0 -0
  79. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/multi_context.py +0 -0
  80. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/prompts/variants/numerical.py +0 -0
  81. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/references/__init__.py +0 -0
  82. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/references/context.py +0 -0
  83. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/references/store.py +0 -0
  84. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/references/tikz_store.py +0 -0
  85. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/templates/__init__.py +0 -0
  86. {vbagent-0.2.0 → vbagent-0.2.1}/vbagent/templates/agentic_context.py +0 -0
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: vbagent
3
- Version: 0.2.0
3
+ Version: 0.2.1
4
4
  Summary: Physics question processing library and CLI - classification, LaTeX extraction, variant generation
5
5
  Author: vaibhavblayer
6
6
  Author-email: vaibhavblayer@gmail.com
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "vbagent"
3
- version = "0.2.0"
3
+ version = "0.2.1"
4
4
  description = "Physics question processing library and CLI - classification, LaTeX extraction, variant generation"
5
5
  authors = [
6
6
  {name = "vaibhavblayer", email = "vaibhavblayer@gmail.com"}
@@ -8,7 +8,7 @@ from typing import TYPE_CHECKING, Any, Optional
8
8
  if TYPE_CHECKING:
9
9
  from agents import Agent, ModelSettings
10
10
 
11
- from vbagent.config import get_model, get_model_settings
11
+ from vbagent.config import get_model, get_model_settings, apply_provider_config
12
12
 
13
13
 
14
14
  def _get_agent_class():
@@ -115,6 +115,9 @@ def create_agent(
115
115
  """
116
116
  Agent = _get_agent_class()
117
117
 
118
+ # Apply provider config (base_url, api_key) before creating agent
119
+ apply_provider_config()
120
+
118
121
  # Get model and settings from config if not explicitly provided
119
122
  if model is None:
120
123
  model = get_model(agent_type or "default")
@@ -0,0 +1,68 @@
1
+ """Classifier agent for question image classification.
2
+
3
+ Uses openai-agents SDK to analyze question images and extract
4
+ structured metadata including question type, difficulty, topic, etc.
5
+ """
6
+
7
+ from typing import TYPE_CHECKING, Optional
8
+
9
+ if TYPE_CHECKING:
10
+ from agents import Agent
11
+
12
+ from vbagent.agents.base import (
13
+ create_agent,
14
+ create_image_message,
15
+ run_agent_sync,
16
+ )
17
+ from vbagent.config import get_config
18
+ from vbagent.models.classification import ClassificationResult
19
+ from vbagent.prompts.classifier import get_classifier_prompt, get_user_template
20
+
21
+
22
+ def create_classifier_agent(subject: Optional[str] = None) -> "Agent":
23
+ """Create a classifier agent for a subject.
24
+
25
+ Args:
26
+ subject: Subject override (uses config if not provided)
27
+
28
+ Returns:
29
+ Configured Agent instance for classification
30
+ """
31
+ if subject is None:
32
+ subject = get_config().subject
33
+
34
+ prompt = get_classifier_prompt(subject)
35
+
36
+ return create_agent(
37
+ name=f"Classifier-{subject}",
38
+ instructions=prompt,
39
+ output_type=ClassificationResult,
40
+ agent_type="classifier",
41
+ )
42
+
43
+
44
+ # Legacy: Create default classifier agent for backward compatibility
45
+ classifier_agent = create_classifier_agent("physics")
46
+
47
+
48
+ def classify(image_path: str, subject: Optional[str] = None) -> ClassificationResult:
49
+ """Analyze a question image and return structured metadata.
50
+
51
+ Args:
52
+ image_path: Path to the image file to classify
53
+ subject: Subject override (uses config if not provided)
54
+
55
+ Returns:
56
+ ClassificationResult with extracted metadata
57
+
58
+ Raises:
59
+ FileNotFoundError: If the image file doesn't exist
60
+ """
61
+ if subject is None:
62
+ subject = get_config().subject
63
+
64
+ agent = create_classifier_agent(subject)
65
+ user_template = get_user_template(subject)
66
+ message = create_image_message(image_path, user_template)
67
+ result = run_agent_sync(agent, message)
68
+ return result
@@ -0,0 +1,57 @@
1
+ """Agent for fixing LaTeX compilation errors.
2
+
3
+ Takes a LaTeX snippet and pdflatex error output, returns corrected LaTeX.
4
+ """
5
+
6
+ from vbagent.agents.base import create_agent, run_agent_sync
7
+
8
+
9
+ SYSTEM_PROMPT = r"""You are a LaTeX error fixer. You receive LaTeX code that failed to compile and the pdflatex error output.
10
+
11
+ Your job:
12
+ 1. Read the error messages carefully
13
+ 2. Fix ONLY the errors — do not change the content or structure
14
+ 3. Common fixes: missing braces, undefined commands, wrong environment names, missing $ delimiters
15
+ 4. Output ONLY the corrected LaTeX code — no explanations, no markdown, no code blocks
16
+
17
+ CRITICAL: Output the EXACT same content with ONLY the compilation errors fixed. Do not add \documentclass, preamble, or any wrapping."""
18
+
19
+ USER_TEMPLATE = """Fix the compilation errors in this LaTeX code.
20
+
21
+ **Errors from pdflatex:**
22
+ ```
23
+ {errors}
24
+ ```
25
+
26
+ **LaTeX code to fix:**
27
+ ```latex
28
+ {latex}
29
+ ```
30
+
31
+ Output ONLY the corrected LaTeX code:"""
32
+
33
+
34
+ def fix_latex(error_summary: str, latex: str) -> str:
35
+ """Send LaTeX + errors to agent and get fixed version.
36
+
37
+ Args:
38
+ error_summary: Parsed pdflatex error output
39
+ latex: The LaTeX code that failed to compile
40
+
41
+ Returns:
42
+ Corrected LaTeX code
43
+ """
44
+ agent = create_agent(
45
+ name="LaTeX-Fixer",
46
+ instructions=SYSTEM_PROMPT,
47
+ agent_type="converter", # Use converter model (lighter/cheaper)
48
+ )
49
+
50
+ prompt = USER_TEMPLATE.format(errors=error_summary, latex=latex)
51
+ result = run_agent_sync(agent, prompt)
52
+
53
+ # Clean markdown artifacts
54
+ import re
55
+ result = re.sub(r'^```(?:latex|tex)?\s*\n?', '', result, flags=re.IGNORECASE)
56
+ result = re.sub(r'\n?```\s*$', '', result)
57
+ return result.strip()
@@ -1,11 +1,11 @@
1
- """Scanner agent for extracting LaTeX from physics question images.
1
+ """Scanner agent for extracting LaTeX from question images.
2
2
 
3
- Uses openai-agents SDK to analyze physics question images and extract
4
- LaTeX code using type-specific prompts.
3
+ Uses openai-agents SDK to analyze question images and extract
4
+ LaTeX code using type-specific and subject-specific prompts.
5
5
  """
6
6
 
7
7
  import re
8
- from typing import TYPE_CHECKING
8
+ from typing import TYPE_CHECKING, Optional
9
9
 
10
10
  if TYPE_CHECKING:
11
11
  from agents import Agent
@@ -15,9 +15,10 @@ from vbagent.agents.base import (
15
15
  create_image_message,
16
16
  run_agent_sync,
17
17
  )
18
+ from vbagent.config import get_config
18
19
  from vbagent.models.classification import ClassificationResult
19
20
  from vbagent.models.scan import ScanResult
20
- from vbagent.prompts.scanner import get_scanner_prompt, USER_TEMPLATE
21
+ from vbagent.prompts.scanner import get_scanner_prompt, get_user_template
21
22
  from vbagent.references.context import get_context_prompt_section
22
23
 
23
24
 
@@ -51,17 +52,26 @@ def clean_latex_output(latex: str) -> str:
51
52
  return latex.strip()
52
53
 
53
54
 
54
- def create_scanner_agent(question_type: str, use_context: bool = True) -> "Agent":
55
+ def create_scanner_agent(
56
+ question_type: str,
57
+ use_context: bool = True,
58
+ subject: Optional[str] = None,
59
+ ) -> "Agent":
55
60
  """Create a scanner agent with type-specific prompt.
56
61
 
57
62
  Args:
58
63
  question_type: The type of question (mcq_sc, mcq_mc, etc.)
59
64
  use_context: Whether to include reference context in prompt
65
+ subject: Subject override (uses config if not provided)
60
66
 
61
67
  Returns:
62
68
  Configured Agent instance for scanning that question type
63
69
  """
64
- prompt = get_scanner_prompt(question_type)
70
+ # Get subject from config if not provided
71
+ if subject is None:
72
+ subject = get_config().subject
73
+
74
+ prompt = get_scanner_prompt(question_type, subject)
65
75
 
66
76
  # Add reference context if enabled
67
77
  context = get_context_prompt_section("latex", use_context)
@@ -69,7 +79,7 @@ def create_scanner_agent(question_type: str, use_context: bool = True) -> "Agent
69
79
  prompt = prompt + "\n" + context
70
80
 
71
81
  return create_agent(
72
- name=f"Scanner-{question_type}",
82
+ name=f"Scanner-{question_type}-{subject}",
73
83
  instructions=prompt,
74
84
  agent_type="scanner",
75
85
  )
@@ -79,8 +89,9 @@ def scan(
79
89
  image_path: str,
80
90
  classification: ClassificationResult,
81
91
  use_context: bool = True,
92
+ subject: Optional[str] = None,
82
93
  ) -> ScanResult:
83
- """Extract LaTeX from a physics question image.
94
+ """Extract LaTeX from a question image.
84
95
 
85
96
  Uses the classification result to select the appropriate prompt
86
97
  for the question type.
@@ -89,6 +100,7 @@ def scan(
89
100
  image_path: Path to the image file to scan
90
101
  classification: Classification result with question type info
91
102
  use_context: Whether to include reference context in prompt
103
+ subject: Subject override (uses config if not provided)
92
104
 
93
105
  Returns:
94
106
  ScanResult with extracted LaTeX and diagram info
@@ -96,8 +108,13 @@ def scan(
96
108
  Raises:
97
109
  FileNotFoundError: If the image file doesn't exist
98
110
  """
99
- agent = create_scanner_agent(classification.question_type, use_context)
100
- message = create_image_message(image_path, USER_TEMPLATE)
111
+ # Get subject from config if not provided
112
+ if subject is None:
113
+ subject = get_config().subject
114
+
115
+ agent = create_scanner_agent(classification.question_type, use_context, subject)
116
+ user_template = get_user_template(subject)
117
+ message = create_image_message(image_path, user_template)
101
118
  raw_latex = run_agent_sync(agent, message)
102
119
 
103
120
  # Clean up markdown artifacts from LLM output
@@ -114,8 +131,9 @@ def scan_with_type(
114
131
  image_path: str,
115
132
  question_type: str,
116
133
  use_context: bool = True,
134
+ subject: Optional[str] = None,
117
135
  ) -> ScanResult:
118
- """Extract LaTeX from a physics question image with explicit type.
136
+ """Extract LaTeX from a question image with explicit type.
119
137
 
120
138
  Bypasses classification and uses the provided question type directly.
121
139
 
@@ -123,6 +141,7 @@ def scan_with_type(
123
141
  image_path: Path to the image file to scan
124
142
  question_type: The type of question (mcq_sc, mcq_mc, etc.)
125
143
  use_context: Whether to include reference context in prompt
144
+ subject: Subject override (uses config if not provided)
126
145
 
127
146
  Returns:
128
147
  ScanResult with extracted LaTeX
@@ -130,8 +149,13 @@ def scan_with_type(
130
149
  Raises:
131
150
  FileNotFoundError: If the image file doesn't exist
132
151
  """
133
- agent = create_scanner_agent(question_type, use_context)
134
- message = create_image_message(image_path, USER_TEMPLATE)
152
+ # Get subject from config if not provided
153
+ if subject is None:
154
+ subject = get_config().subject
155
+
156
+ agent = create_scanner_agent(question_type, use_context, subject)
157
+ user_template = get_user_template(subject)
158
+ message = create_image_message(image_path, user_template)
135
159
  raw_latex = run_agent_sync(agent, message)
136
160
 
137
161
  # Clean up markdown artifacts from LLM output