OpceanAI commited on
Commit
058ca41
·
verified ·
1 Parent(s): 9982b30

Upload app.py with huggingface_hub

Browse files
Files changed (1) hide show
  1. app.py +17 -14
app.py CHANGED
@@ -97,7 +97,7 @@ def _prune_downloads(max_age_seconds: int = 3600) -> None:
97
  pass
98
 
99
 
100
- def _download_path(markdown: str | None) -> str | None:
101
  if not markdown or not markdown.strip():
102
  return None
103
  try:
@@ -177,7 +177,7 @@ def _run_harness(text: str | None, num_candidates: int | None, structured_fallba
177
 
178
 
179
  @spaces.GPU(duration=_estimate_duration)
180
- def convert(text: str | None = None, num_candidates: int | None = None, structured_fallback: bool | None = None, max_output_tokens: int | None = None) -> tuple[str, str, str, str]:
181
  """Convert a plain-text document into faithful GitHub-Flavored Markdown.
182
 
183
  PASITA samples the document several times, every candidate is post-processed and
@@ -191,11 +191,12 @@ def convert(text: str | None = None, num_candidates: int | None = None, structur
191
  structured_fallback: Use the deterministic converter for HTML and delimited data.
192
  max_output_tokens: Optional cap on generated tokens. When omitted, the length is chosen automatically.
193
  Returns:
194
- A tuple of the rendered Markdown, the raw Markdown, a status line and run details.
 
195
  """
196
  text = (text or "").strip()
197
  if not text:
198
- return EMPTY_MD, "", _status("READY / PASTE A DOCUMENT TO CONVERT"), DETAILS_EMPTY
199
  if len(text) > MAX_INPUT_CHARS:
200
  message = f"Input too long ({len(text):,} chars). The limit is {MAX_INPUT_CHARS:,} characters."
201
  return (
@@ -203,6 +204,7 @@ def convert(text: str | None = None, num_candidates: int | None = None, structur
203
  "",
204
  _status("ERROR / INPUT TOO LONG", "error"),
205
  _details_md(None, 0.0, error=message),
 
206
  )
207
 
208
  try:
@@ -219,6 +221,7 @@ def convert(text: str | None = None, num_candidates: int | None = None, structur
219
  "",
220
  _status(f"ERROR / {err_type}", "error"),
221
  _details_md(None, 0.0, error=f"{plain} Technical detail: {err_type}: {exc}"),
 
222
  )
223
 
224
  metrics = result["metrics"]
@@ -234,7 +237,7 @@ def convert(text: str | None = None, num_candidates: int | None = None, structur
234
  detail = f"{source_label} / {numbers} / {overlap} / {taken:.1f}S"
235
  if result.get("strategy", {}).get("truncated_input"):
236
  detail += " / INPUT TRUNCATED TO 2048 TOKENS"
237
- return result["markdown"], result["markdown"], _status("DONE", "ready", detail), _details_md(result, taken)
238
 
239
 
240
  @spaces.GPU(duration=_estimate_duration)
@@ -458,8 +461,8 @@ def _extract_user_text(messages: list[ChatMessage]) -> str | None:
458
  return None
459
 
460
 
461
- def reset() -> tuple[str, str, str, str, str]:
462
- return EMPTY_MD, "", _status("READY"), DETAILS_EMPTY, _counter("")
463
 
464
 
465
  @server.post("/v1/chat/completions", response_model=None)
@@ -528,12 +531,12 @@ def chat_completions(body: ChatCompletionRequest, request: fastapi.Request) -> d
528
  }
529
 
530
 
531
- BUSY_JS = """(text, num_candidates, structured_fallback, md, source, status, details) => {
532
  const n = Number(num_candidates) || 1;
533
  const label = n > 1 ? 'PASITA ' + n + ' SAMPLES / RERANK' : 'PASITA SAMPLE / RERANK';
534
  return ['_Converting…_', '',
535
  '<div class="p-status busy"><span class="p-dot"></span><span class="p-text">CONVERTING</span><span class="p-detail">' + label + '</span></div>',
536
- '_Checking drafts…_'];
537
  }"""
538
 
539
  COUNTER_JS = """(text) => {
@@ -893,13 +896,13 @@ with gr.Blocks(title="PASITA: plain text to Markdown") as demo:
893
  details = gr.Markdown(DETAILS_EMPTY, elem_id="p-details")
894
  with gr.Row(elem_classes=["p-out-head"]):
895
  out_label = gr.HTML('<span class="p-label">MARKDOWN</span>')
896
- dl = gr.DownloadButton("DOWNLOAD .MD", value=_download_path, inputs=[source], size="sm", elem_id="p-dl")
897
 
898
  gr.Examples(
899
  examples=EXAMPLES,
900
  example_labels=["ES REPORT", "EN MEETING", "HTML", "CSV"],
901
  inputs=[text_in],
902
- outputs=[md_out, source, status, details],
903
  fn=convert,
904
  cache_examples=True,
905
  cache_mode="lazy",
@@ -912,7 +915,7 @@ with gr.Blocks(title="PASITA: plain text to Markdown") as demo:
912
  run.click(
913
  convert,
914
  inputs=[text_in, candidates, structured],
915
- outputs=[md_out, source, status, details],
916
  api_name="convert",
917
  js=BUSY_JS,
918
  show_progress="minimal",
@@ -920,13 +923,13 @@ with gr.Blocks(title="PASITA: plain text to Markdown") as demo:
920
  text_in.submit(
921
  convert,
922
  inputs=[text_in, candidates, structured],
923
- outputs=[md_out, source, status, details],
924
  api_visibility="undocumented",
925
  js=BUSY_JS,
926
  show_progress="minimal",
927
  )
928
  text_in.change(None, inputs=[text_in], outputs=[label_in], js=COUNTER_JS, api_visibility="undocumented")
929
- clear.click(reset, inputs=None, outputs=[md_out, source, status, details, label_in], api_visibility="undocumented")
930
 
931
  demo.queue()
932
  demo.launch(_app=server, theme=theme, css=CSS, mcp_server=True)
 
97
  pass
98
 
99
 
100
+ def _write_download(markdown: str | None) -> str | None:
101
  if not markdown or not markdown.strip():
102
  return None
103
  try:
 
177
 
178
 
179
  @spaces.GPU(duration=_estimate_duration)
180
+ def convert(text: str | None = None, num_candidates: int | None = None, structured_fallback: bool | None = None, max_output_tokens: int | None = None) -> tuple[str, str, str, str, str | None]:
181
  """Convert a plain-text document into faithful GitHub-Flavored Markdown.
182
 
183
  PASITA samples the document several times, every candidate is post-processed and
 
191
  structured_fallback: Use the deterministic converter for HTML and delimited data.
192
  max_output_tokens: Optional cap on generated tokens. When omitted, the length is chosen automatically.
193
  Returns:
194
+ A tuple of the rendered Markdown, the raw Markdown, a status line, run details
195
+ and a download path for the Markdown file (or None).
196
  """
197
  text = (text or "").strip()
198
  if not text:
199
+ return EMPTY_MD, "", _status("READY / PASTE A DOCUMENT TO CONVERT"), DETAILS_EMPTY, None
200
  if len(text) > MAX_INPUT_CHARS:
201
  message = f"Input too long ({len(text):,} chars). The limit is {MAX_INPUT_CHARS:,} characters."
202
  return (
 
204
  "",
205
  _status("ERROR / INPUT TOO LONG", "error"),
206
  _details_md(None, 0.0, error=message),
207
+ None,
208
  )
209
 
210
  try:
 
221
  "",
222
  _status(f"ERROR / {err_type}", "error"),
223
  _details_md(None, 0.0, error=f"{plain} Technical detail: {err_type}: {exc}"),
224
+ None,
225
  )
226
 
227
  metrics = result["metrics"]
 
237
  detail = f"{source_label} / {numbers} / {overlap} / {taken:.1f}S"
238
  if result.get("strategy", {}).get("truncated_input"):
239
  detail += " / INPUT TRUNCATED TO 2048 TOKENS"
240
+ return result["markdown"], result["markdown"], _status("DONE", "ready", detail), _details_md(result, taken), _write_download(result["markdown"])
241
 
242
 
243
  @spaces.GPU(duration=_estimate_duration)
 
461
  return None
462
 
463
 
464
+ def reset() -> tuple[str, str, str, str, str | None, str]:
465
+ return EMPTY_MD, "", _status("READY"), DETAILS_EMPTY, None, _counter("")
466
 
467
 
468
  @server.post("/v1/chat/completions", response_model=None)
 
531
  }
532
 
533
 
534
+ BUSY_JS = """(text, num_candidates, structured_fallback, md, source, status, details, dl) => {
535
  const n = Number(num_candidates) || 1;
536
  const label = n > 1 ? 'PASITA ' + n + ' SAMPLES / RERANK' : 'PASITA SAMPLE / RERANK';
537
  return ['_Converting…_', '',
538
  '<div class="p-status busy"><span class="p-dot"></span><span class="p-text">CONVERTING</span><span class="p-detail">' + label + '</span></div>',
539
+ '_Checking drafts…_', null];
540
  }"""
541
 
542
  COUNTER_JS = """(text) => {
 
896
  details = gr.Markdown(DETAILS_EMPTY, elem_id="p-details")
897
  with gr.Row(elem_classes=["p-out-head"]):
898
  out_label = gr.HTML('<span class="p-label">MARKDOWN</span>')
899
+ dl = gr.DownloadButton("DOWNLOAD .MD", size="sm", elem_id="p-dl")
900
 
901
  gr.Examples(
902
  examples=EXAMPLES,
903
  example_labels=["ES REPORT", "EN MEETING", "HTML", "CSV"],
904
  inputs=[text_in],
905
+ outputs=[md_out, source, status, details, dl],
906
  fn=convert,
907
  cache_examples=True,
908
  cache_mode="lazy",
 
915
  run.click(
916
  convert,
917
  inputs=[text_in, candidates, structured],
918
+ outputs=[md_out, source, status, details, dl],
919
  api_name="convert",
920
  js=BUSY_JS,
921
  show_progress="minimal",
 
923
  text_in.submit(
924
  convert,
925
  inputs=[text_in, candidates, structured],
926
+ outputs=[md_out, source, status, details, dl],
927
  api_visibility="undocumented",
928
  js=BUSY_JS,
929
  show_progress="minimal",
930
  )
931
  text_in.change(None, inputs=[text_in], outputs=[label_in], js=COUNTER_JS, api_visibility="undocumented")
932
+ clear.click(reset, inputs=None, outputs=[md_out, source, status, details, dl, label_in], api_visibility="undocumented")
933
 
934
  demo.queue()
935
  demo.launch(_app=server, theme=theme, css=CSS, mcp_server=True)