atakan commited on
Commit
f9502c9
·
1 Parent(s): a5c67b7

fix: Protect all LaTeX math, fractions, Greek letters, and matrix environments from markdown parser

Browse files
Files changed (3) hide show
  1. controlai_agent/prompts.py +3 -3
  2. web/app.js +14 -0
  3. web/index.html +1 -1
controlai_agent/prompts.py CHANGED
@@ -14,9 +14,9 @@ When answering theoretical principles, derivations, proofs, comparisons, or limi
14
 
15
  ### Strict Negative & Formatting Constraints:
16
  1. **ZERO EMOJIS**: NEVER use any emojis anywhere in your response (absolutely NO checkmarks, NO pins, NO graphs, NO rockets, NO lightbulbs).
17
- 2. **NO RAW LATEX DOCUMENT TAGS**: NEVER output `\begin{figure}`, `\includegraphics`, `\caption`, `\centering`, `\section*`, or `\end{figure}`. You are generating web markdown, not a PDF compilation. Use standard markdown headers (e.g. `### Section Title`).
18
- 3. **MANDATORY TOOL CALL FOR PLOTS**: When asked to plot, visualize, or simulate (Nyquist plot, Bode diagram, Root Locus, Step Response, Phase Portrait), NEVER hallucinate a fake image filename. You MUST explicitly call `execute_python_code` (using `control as ct` or `matplotlib.pyplot`) or `simulate_step_response` to generate and display the real plot!
19
- 4. **Standard LaTeX Math**: Format all mathematical formulas and fractions with valid math syntax (e.g. `$\frac{\omega_n^2}{s^2 + 2\zeta\omega_n s + \omega_n^2}$`).
20
  5. **Deterministic Grounding**: When a tool executes successfully, present the exact numerical results and generated plot.
21
  6. **No Infinite Retries**: If a tool returns an error, correct the parameters or synthesize the analytical answer directly.
22
  7. **No Forced Citations**: Do NOT cite arbitrary random file paths unless the user explicitly requests literature references.
 
14
 
15
  ### Strict Negative & Formatting Constraints:
16
  1. **ZERO EMOJIS**: NEVER use any emojis anywhere in your response (absolutely NO checkmarks, NO pins, NO graphs, NO rockets, NO lightbulbs).
17
+ 2. **ALWAYS USE DOLLAR DELIMITERS FOR MATH**: ALWAYS enclose EVERY mathematical formula, transfer function, variable, fraction, and Greek letter in dollar signs: `$ ... $` for inline math or `$$ ... $$` for centered equations. Example: `$$G(s) = \frac{1}{s(s+1)(s+2)}$$` and `$\omega \to \infty$`. NEVER write raw LaTeX keywords (`\frac`, `\omega`, `\to`) without `$` or `$$` delimiters!
18
+ 3. **NO RAW LATEX DOCUMENT TAGS**: NEVER output `\begin{figure}`, `\includegraphics`, `\caption`, `\centering`, `\section*`, or `\end{figure}`. Use standard markdown headers (e.g. `### Section Title`).
19
+ 4. **MANDATORY TOOL CALL FOR PLOTS**: When asked to plot, visualize, or simulate (Nyquist plot, Bode diagram, Root Locus, Step Response, Phase Portrait), NEVER hallucinate a fake image filename. You MUST explicitly call `execute_python_code` (using `control as ct` or `matplotlib.pyplot`) or `simulate_step_response` to generate and display the real plot!
20
  5. **Deterministic Grounding**: When a tool executes successfully, present the exact numerical results and generated plot.
21
  6. **No Infinite Retries**: If a tool returns an error, correct the parameters or synthesize the analytical answer directly.
22
  7. **No Forced Citations**: Do NOT cite arbitrary random file paths unless the user explicitly requests literature references.
web/app.js CHANGED
@@ -166,6 +166,13 @@ document.addEventListener('DOMContentLoaded', () => {
166
  text = text.replace(/\\includegraphics.*?\{([^\}]+)\}/g, '![$1](/plots/$1)');
167
  text = text.replace(/\\caption\{([\s\S]*?)\}/g, '*$1*');
168
 
 
 
 
 
 
 
 
169
  // 1. Extract Display Math: $$ ... $$
170
  text = text.replace(/\$\$([\s\S]*?)\$\$/g, (match, formula) => {
171
  const ph = `@@MATH_BLOCK_${mathPlaceholders.length}@@`;
@@ -194,6 +201,13 @@ document.addEventListener('DOMContentLoaded', () => {
194
  return ph;
195
  });
196
 
 
 
 
 
 
 
 
197
  // Parse Markdown
198
  let html = marked.parse(text);
199
 
 
166
  text = text.replace(/\\includegraphics.*?\{([^\}]+)\}/g, '![$1](/plots/$1)');
167
  text = text.replace(/\\caption\{([\s\S]*?)\}/g, '*$1*');
168
 
169
+ // 0. Extract LaTeX Environments: \begin{aligned}...\end{aligned}, \begin{bmatrix}...\end{bmatrix}, etc.
170
+ text = text.replace(/\\begin\{(aligned|bmatrix|matrix|pmatrix|vmatrix|cases|equation\*?)\}[\s\S]*?\\end\{\1\}/g, (match) => {
171
+ const ph = `@@MATH_BLOCK_${mathPlaceholders.length}@@`;
172
+ mathPlaceholders.push({ type: 'block', formula: match.trim() });
173
+ return `\n\n${ph}\n\n`;
174
+ });
175
+
176
  // 1. Extract Display Math: $$ ... $$
177
  text = text.replace(/\$\$([\s\S]*?)\$\$/g, (match, formula) => {
178
  const ph = `@@MATH_BLOCK_${mathPlaceholders.length}@@`;
 
201
  return ph;
202
  });
203
 
204
+ // 5. Auto-catch unescaped freestanding math blocks like \frac{...}{...} or \omega \to ...
205
+ text = text.replace(/(\\frac\{[^\}]+\}\{[^\}]+\}|\\angle\s+[a-zA-Z0-9_\(\)]+|\\sqrt\{[^\}]+\}|\\dot\{[^\}]+\})/g, (match) => {
206
+ const ph = `@@MATH_INLINE_${mathPlaceholders.length}@@`;
207
+ mathPlaceholders.push({ type: 'inline', formula: match.trim() });
208
+ return ph;
209
+ });
210
+
211
  // Parse Markdown
212
  let html = marked.parse(text);
213
 
web/index.html CHANGED
@@ -226,6 +226,6 @@
226
  </div>
227
  </div>
228
 
229
- <script src="/static/app.js?v=20260819_figure_sanitize"></script>
230
  </body>
231
  </html>
 
226
  </div>
227
  </div>
228
 
229
+ <script src="/static/app.js?v=20260819_math_fix"></script>
230
  </body>
231
  </html>