wifix199 commited on
Commit
4b1dcee
Β·
verified Β·
1 Parent(s): 37839fd

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +44 -27
app.py CHANGED
@@ -1,8 +1,30 @@
1
  #!/usr/bin/env python3
2
  """
3
  ai_csv_editor_hf.py ── AI-powered CSV editor using a Hugging Face model on CPU.
 
 
 
4
  """
5
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
6
  import json
7
  import tempfile
8
  import textwrap
@@ -13,33 +35,28 @@ import pandas as pd
13
  import gradio as gr
14
  from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
15
 
16
- # ──────────────────────────────────────────────────────────
17
- # 1. LOAD A SMALL INSTRUCTION-FOLLOWING MODEL (CPU only)
18
- # ──────────────────────────────────────────────────────────
19
- MODEL_NAME = "google/flan-t5-base"
20
- MAX_NEW_TOK = 256
21
  TEMPERATURE = 0.0
22
 
23
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
24
  model = AutoModelForSeq2SeqLM.from_pretrained(
25
- MODEL_NAME,
26
- device_map="cpu", # force CPU placement
27
- torch_dtype="auto"
28
- )
29
-
30
- # **Important change**: no `device=` argument here!
31
  generator = pipeline(
32
  "text2text-generation",
33
  model=model,
34
  tokenizer=tokenizer,
35
- max_new_tokens=MAX_NEW_TOK,
36
  temperature=TEMPERATURE,
37
  do_sample=False,
38
  )
39
 
40
- # ──────────────────────────────────────────────────────────
41
- # 2. PROMPT β†’ JSON β€œEDIT PLAN”
42
- # ──────────────────────────────────────────────────────────
43
  SYSTEM_PROMPT = textwrap.dedent("""\
44
  You are an assistant that converts natural-language spreadsheet commands
45
  into JSON edit plans. Respond with ONLY valid JSON matching this schema:
@@ -72,20 +89,24 @@ into JSON edit plans. Respond with ONLY valid JSON matching this schema:
72
 
73
  def plan_from_command(cmd: str) -> Dict[str, Any]:
74
  prompt = f"{SYSTEM_PROMPT}\n\nUser: {cmd}\nJSON:"
75
- output = generator(prompt)[0]["generated_text"]
 
 
 
 
 
76
  try:
77
  return json.loads(output)
78
  except json.JSONDecodeError as e:
79
  raise ValueError(f"Model returned invalid JSON:\n{output}") from e
80
 
81
- # ──────────────────────────────────────────────────────────
82
- # 3. DATA OPERATIONS
83
- # ───────────────────────────��──────────────────────────────
84
  def apply_action(df: pd.DataFrame,
85
  uploads: Dict[str, pd.DataFrame],
86
  act: Dict[str, Any]) -> pd.DataFrame:
87
  op = act["operation"]
88
-
89
  if op == "concat":
90
  sep = act.get("separator", "")
91
  df[act["target"]] = (
@@ -93,7 +114,6 @@ def apply_action(df: pd.DataFrame,
93
  .astype(str)
94
  .agg(sep.join, axis=1)
95
  )
96
-
97
  elif op in {"vlookup", "xlookup"}:
98
  lookup_df = uploads[act["lookup_file"]]
99
  right = lookup_df[[act["lookup_column"], act["return_column"]]] \
@@ -102,20 +122,17 @@ def apply_action(df: pd.DataFrame,
102
  act["return_column"]: act["target"]
103
  })
104
  df = df.merge(right, on=act["lookup_value"], how="left")
105
-
106
  elif op == "sumif":
107
  mask = df[act["criteria_column"]] == act["criteria"]
108
  total = df.loc[mask, act["sum_column"]].sum()
109
  df[act["target"]] = total
110
-
111
  else:
112
  raise ValueError(f"Unsupported operation: {op}")
113
-
114
  return df
115
 
116
- # ──────────────────────────────────────────────────────────
117
- # 4. GRADIO UI
118
- # ──────────────────────────────────────────────────────────
119
  def run_editor(files: List[gr.File], command: str):
120
  if not files:
121
  return None, "⚠️ Please upload at least one CSV file.", None
 
1
  #!/usr/bin/env python3
2
  """
3
  ai_csv_editor_hf.py ── AI-powered CSV editor using a Hugging Face model on CPU.
4
+
5
+ This version patches Gradio’s JSON‐schema introspector to skip over
6
+ boolean schemas and avoid the "const in schema" TypeError.
7
  """
8
 
9
+ # ─────────────────────────────────────────────────────────────────────────────
10
+ # 0. MONKEY-PATCH for gradio_client.utils.get_type to handle bool schemas
11
+ # ─────────────────────────────────────────────────────────────────────────────
12
+ try:
13
+ import gradio_client.utils as _client_utils
14
+ _old_get_type = _client_utils.get_type
15
+ def _patched_get_type(schema):
16
+ # If schema is unexpectedly a bool, just return a generic "Any"
17
+ if isinstance(schema, bool):
18
+ return "Any"
19
+ return _old_get_type(schema)
20
+ _client_utils.get_type = _patched_get_type
21
+ except ImportError:
22
+ # If gradio_client isn't present yet, we'll let it import later
23
+ pass
24
+
25
+ # ─────────────────────────────────────────────────────────────────────────────
26
+ # 1. LOAD A SMALL INSTRUCTION-FOLLOWING MODEL (CPU only)
27
+ # ─────────────────────────────────────────────────────────────────────────────
28
  import json
29
  import tempfile
30
  import textwrap
 
35
  import gradio as gr
36
  from transformers import pipeline, AutoTokenizer, AutoModelForSeq2SeqLM
37
 
38
+ MODEL_NAME = "google/flan-t5-base"
39
+ MAX_NEW_TOKS = 256
 
 
 
40
  TEMPERATURE = 0.0
41
 
42
  tokenizer = AutoTokenizer.from_pretrained(MODEL_NAME)
43
  model = AutoModelForSeq2SeqLM.from_pretrained(
44
+ MODEL_NAME,
45
+ device_map="cpu", # force CPU placement
46
+ torch_dtype="auto"
47
+ )
 
 
48
  generator = pipeline(
49
  "text2text-generation",
50
  model=model,
51
  tokenizer=tokenizer,
52
+ max_new_tokens=MAX_NEW_TOKS,
53
  temperature=TEMPERATURE,
54
  do_sample=False,
55
  )
56
 
57
+ # ─────────────────────────────────────────────────────────────────────────────
58
+ # 2. PROMPT β†’ JSON β€œEDIT PLAN”
59
+ # ─────────────────────────────────────────────────────────────────────────────
60
  SYSTEM_PROMPT = textwrap.dedent("""\
61
  You are an assistant that converts natural-language spreadsheet commands
62
  into JSON edit plans. Respond with ONLY valid JSON matching this schema:
 
89
 
90
  def plan_from_command(cmd: str) -> Dict[str, Any]:
91
  prompt = f"{SYSTEM_PROMPT}\n\nUser: {cmd}\nJSON:"
92
+ output = generator(
93
+ prompt,
94
+ max_new_tokens=MAX_NEW_TOKS,
95
+ temperature=TEMPERATURE,
96
+ do_sample=False,
97
+ )[0]["generated_text"]
98
  try:
99
  return json.loads(output)
100
  except json.JSONDecodeError as e:
101
  raise ValueError(f"Model returned invalid JSON:\n{output}") from e
102
 
103
+ # ─────────────────────────────────────────────────────────────────────────────
104
+ # 3. DATA OPERATIONS
105
+ # ─────────────────────────────────────────────────────────────────────────────
106
  def apply_action(df: pd.DataFrame,
107
  uploads: Dict[str, pd.DataFrame],
108
  act: Dict[str, Any]) -> pd.DataFrame:
109
  op = act["operation"]
 
110
  if op == "concat":
111
  sep = act.get("separator", "")
112
  df[act["target"]] = (
 
114
  .astype(str)
115
  .agg(sep.join, axis=1)
116
  )
 
117
  elif op in {"vlookup", "xlookup"}:
118
  lookup_df = uploads[act["lookup_file"]]
119
  right = lookup_df[[act["lookup_column"], act["return_column"]]] \
 
122
  act["return_column"]: act["target"]
123
  })
124
  df = df.merge(right, on=act["lookup_value"], how="left")
 
125
  elif op == "sumif":
126
  mask = df[act["criteria_column"]] == act["criteria"]
127
  total = df.loc[mask, act["sum_column"]].sum()
128
  df[act["target"]] = total
 
129
  else:
130
  raise ValueError(f"Unsupported operation: {op}")
 
131
  return df
132
 
133
+ # ─────────────────────────────────────────────────────────────────────────────
134
+ # 4. GRADIO UI
135
+ # ─────────────────────────────────────────────────────────────────────────────
136
  def run_editor(files: List[gr.File], command: str):
137
  if not files:
138
  return None, "⚠️ Please upload at least one CSV file.", None