RICS / backend /core /text_modes.py
StormShadow308's picture
Add demo documentation and Docker setup for v2 report generation system
aad7814
Raw
History Blame Contribute Delete
4.13 kB
"""Proofread and enhance modes for legacy UI compatibility."""
from __future__ import annotations
from backend.core.note_bullets import format_bullets_for_prompt
from backend.core.paragraph_merge import merge_observations_into_paragraph
from backend.core.style_profile import StyleProfile
from backend.llm import openai_client
from backend.models.schema import TemplateSchema
PROOFREAD_SYSTEM = """\
You are a professional RICS survey report editor and proofreader. \
Fix grammar, clarity, and British English spellings. Do not add new facts. \
Output plain text only.\
"""
ENHANCE_SYSTEM = """\
You are an expert RICS surveyor and technical writer. \
Expand the section using supplied evidence only — do not invent facts. \
Use British English. Output plain text only.\
"""
def _profile_fields(profile: StyleProfile) -> dict[str, str]:
return {
"tone": profile.tone,
"formality_level": profile.formality_level,
"avg_sentence_complexity": profile.avg_sentence_complexity,
"vocabulary_level": profile.vocabulary_level,
"writing_style_summary": profile.writing_style_summary,
}
def proofread_text(
text: str,
bullets: list[str],
*,
style_profile: StyleProfile | None = None,
) -> str:
clean = text.split("\n\n[Editor notes:")[0].strip()
if not clean:
return text
profile = style_profile or StyleProfile()
pf = _profile_fields(profile)
bullets_text = format_bullets_for_prompt(bullets)
if not openai_client.is_available():
return clean
user = f"""AUTHOR'S WRITING STYLE PROFILE:
- Tone: {pf['tone']}
- Formality: {pf['formality_level']}
- Sentence complexity: {pf['avg_sentence_complexity']}
- Vocabulary: {pf['vocabulary_level']}
- Style summary: {pf['writing_style_summary']}
ORIGINAL FACT BULLETS:
{bullets_text}
TEXT TO PROOFREAD:
{clean}
TASK: Proofread and improve the text. Do NOT add new facts.
Return corrected text, then "---NOTES---" and 1–3 brief editor notes."""
out = openai_client.chat_text(
[{"role": "system", "content": PROOFREAD_SYSTEM}, {"role": "user", "content": user}],
temperature=0.15,
max_tokens=max(700, min(2400, len(clean.split()) * 3)),
)
if "---NOTES---" in out:
corrected, notes = out.split("---NOTES---", 1)
corrected = corrected.strip()
notes_block = f"\n\n[Editor notes: {notes.strip()}]"
else:
corrected = out.strip()
notes_block = ""
return corrected + notes_block
def enhance_text(
text: str,
bullets: list[str],
snippets: list[str],
*,
style_profile: StyleProfile | None = None,
schema: TemplateSchema | None = None,
) -> str:
base = text.split("\n\n[Editor notes:")[0].strip()
if not base:
base = text.strip()
profile = style_profile or StyleProfile()
pf = _profile_fields(profile)
bullets_text = format_bullets_for_prompt(bullets)
examples = "\n\n---\n\n".join(s.strip() for s in snippets if s.strip())[:3500]
if openai_client.is_available():
user = f"""AUTHOR'S WRITING STYLE PROFILE:
- Tone: {pf['tone']}
- Formality: {pf['formality_level']}
- Vocabulary: {pf['vocabulary_level']}
- Style summary: {pf['writing_style_summary']}
ORIGINAL FACT BULLETS:
{bullets_text}
ADDITIONAL EVIDENCE:
{examples or '(No additional evidence available.)'}
CURRENT TEXT:
{base}
TASK: Rewrite and expand the current text using evidence only. Aim for 80–200 words.
Output only the enhanced text."""
out = openai_client.chat_text(
[{"role": "system", "content": ENHANCE_SYSTEM}, {"role": "user", "content": user}],
temperature=0.2,
max_tokens=max(900, min(2400, len(base.split()) + 800)),
)
enhanced = (out or "").strip()
if enhanced:
return enhanced
sch = schema or TemplateSchema()
merged = merge_observations_into_paragraph(base, bullets, sch)
if snippets and snippets[0].strip() not in merged:
extra = snippets[0].strip()
if len(extra) > 40:
merged = f"{merged.rstrip()} {extra}"
return merged