Seth0330 commited on
Commit
cb5bb24
·
verified ·
1 Parent(s): fb5cdfa

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +58 -51
app.py CHANGED
@@ -43,29 +43,6 @@ else:
43
  if df is not None:
44
  st.markdown(f"**Loaded CSV:** {df.shape[0]} rows × {df.shape[1]} columns")
45
 
46
- @st.cache_data(show_spinner=False)
47
- def build_row_embeddings(df: pd.DataFrame):
48
- # 1) Convert each row to a compact JSON string
49
- texts = df.apply(lambda r: r.to_json(), axis=1).tolist()
50
-
51
- # 2) Batch‐call the embeddings endpoint
52
- embeddings = []
53
- for i in range(0, len(texts), 100):
54
- batch = texts[i : i + 100]
55
- resp = requests.post(
56
- "https://api.openai.com/v1/embeddings",
57
- headers=HEADERS,
58
- json={"model": "text-embedding-ada-002", "input": batch},
59
- timeout=60,
60
- )
61
- resp.raise_for_status()
62
- data = resp.json()["data"]
63
- embeddings.extend(d["embedding"] for d in data)
64
-
65
- return np.array(embeddings), texts
66
-
67
- embeddings, row_texts = build_row_embeddings(df)
68
-
69
  # — Prompt input
70
  prompt = st.text_area(
71
  "Enter your prompt for the agent",
@@ -73,15 +50,23 @@ prompt = st.text_area(
73
  height=150,
74
  )
75
 
76
- # — Define function for OpenAI function calling
77
  def search_csv(query: str):
78
- # Run a Pandas query safely
79
  try:
80
  result_df = df.query(query)
81
- return result_df.to_dict(orient="records")
 
82
  except Exception as e:
83
- return {"error": f"Query error: {str(e)}"}
84
 
 
 
 
 
 
 
 
 
85
  function_schema = [
86
  {
87
  "name": "search_csv",
@@ -96,9 +81,29 @@ function_schema = [
96
  },
97
  "required": ["query"],
98
  },
 
 
 
 
 
 
 
 
 
 
 
 
 
 
99
  }
100
  ]
101
 
 
 
 
 
 
 
102
  # — Run Agent
103
  if st.button("Run Agent"):
104
  if df is None:
@@ -106,24 +111,28 @@ if st.button("Run Agent"):
106
  elif not prompt.strip():
107
  st.error("Please enter a prompt.")
108
  else:
109
- # 1) First call: ask OpenAI if it wants to use a function
 
 
 
 
 
 
 
 
 
 
110
  messages = [
111
- {
112
- "role": "system",
113
- "content": (
114
- "You are an AI agent helping users analyze a CSV file. "
115
- "If you need to search or filter the CSV, call the 'search_csv' function. "
116
- "Only use the function when you need data from the CSV."
117
- ),
118
- },
119
  {"role": "user", "content": prompt}
120
  ]
121
 
 
122
  chat_resp = requests.post(
123
  "https://api.openai.com/v1/chat/completions",
124
  headers=HEADERS,
125
  json={
126
- "model": "gpt-3.5-turbo-1106", # or "gpt-4-1106-preview" if available
127
  "messages": messages,
128
  "functions": function_schema,
129
  "function_call": "auto",
@@ -136,27 +145,25 @@ if st.button("Run Agent"):
136
  response_json = chat_resp.json()
137
  msg = response_json["choices"][0]["message"]
138
 
139
- # 2) Check if function call is requested
140
  if msg.get("function_call"):
141
  func_name = msg["function_call"]["name"]
142
  args_json = msg["function_call"]["arguments"]
143
  args = json.loads(args_json)
144
- # Only one function: search_csv
145
- search_result = search_csv(args["query"])
 
 
 
146
 
147
- # 3) Pass function result back to OpenAI for final answer
148
  followup_messages = [
149
- {
150
- "role": "system",
151
- "content": (
152
- "You are an AI agent helping users analyze a CSV file."
153
- ),
154
- },
155
  {"role": "user", "content": prompt},
156
  {
157
  "role": "function",
158
  "name": func_name,
159
- "content": json.dumps(search_result),
160
  }
161
  ]
162
 
@@ -164,7 +171,7 @@ if st.button("Run Agent"):
164
  "https://api.openai.com/v1/chat/completions",
165
  headers=HEADERS,
166
  json={
167
- "model": "gpt-3.5-turbo-1106", # or "gpt-4-1106-preview"
168
  "messages": followup_messages,
169
  "temperature": 0,
170
  "max_tokens": 1500,
@@ -176,8 +183,8 @@ if st.button("Run Agent"):
176
 
177
  st.subheader("✅ Agent Answer")
178
  st.markdown(answer)
179
- st.subheader("📊 Filtered CSV Data")
180
- st.json(search_result)
181
  else:
182
  # No function call: model answered directly
183
  st.subheader("✅ Agent Answer")
 
43
  if df is not None:
44
  st.markdown(f"**Loaded CSV:** {df.shape[0]} rows × {df.shape[1]} columns")
45
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
46
  # — Prompt input
47
  prompt = st.text_area(
48
  "Enter your prompt for the agent",
 
50
  height=150,
51
  )
52
 
53
+ # — Functions for function calling
54
  def search_csv(query: str):
 
55
  try:
56
  result_df = df.query(query)
57
+ # Limit output to 50 rows for large results
58
+ return result_df.head(50).to_dict(orient="records")
59
  except Exception as e:
60
+ return {"error": f"Invalid query. Example: 'price > 100'. Details: {str(e)}"}
61
 
62
+ def count_unique(column: str):
63
+ try:
64
+ n = df[column].nunique()
65
+ return {"column": column, "unique_count": int(n)}
66
+ except Exception as e:
67
+ return {"error": f"Column '{column}' not found or not countable. Details: {str(e)}"}
68
+
69
+ # — Function schemas for OpenAI
70
  function_schema = [
71
  {
72
  "name": "search_csv",
 
81
  },
82
  "required": ["query"],
83
  },
84
+ },
85
+ {
86
+ "name": "count_unique",
87
+ "description": "Count the number of unique values in a column.",
88
+ "parameters": {
89
+ "type": "object",
90
+ "properties": {
91
+ "column": {
92
+ "type": "string",
93
+ "description": "The column name to count unique values."
94
+ },
95
+ },
96
+ "required": ["column"],
97
+ },
98
  }
99
  ]
100
 
101
+ # — Map function names to Python functions
102
+ function_map = {
103
+ "search_csv": search_csv,
104
+ "count_unique": count_unique,
105
+ }
106
+
107
  # — Run Agent
108
  if st.button("Run Agent"):
109
  if df is None:
 
111
  elif not prompt.strip():
112
  st.error("Please enter a prompt.")
113
  else:
114
+ # Build dynamic system message with column info
115
+ columns = ", ".join(df.columns)
116
+ system_message = {
117
+ "role": "system",
118
+ "content": (
119
+ f"You are an AI agent helping users analyze a CSV file with these columns: {columns}. "
120
+ "If you need to search or filter the CSV, call the 'search_csv' function. "
121
+ "If the user wants to know how many unique values are in a column, call the 'count_unique' function. "
122
+ "If you use 'search_csv', use Pandas query syntax."
123
+ ),
124
+ }
125
  messages = [
126
+ system_message,
 
 
 
 
 
 
 
127
  {"role": "user", "content": prompt}
128
  ]
129
 
130
+ # First OpenAI call: See if a function call is needed
131
  chat_resp = requests.post(
132
  "https://api.openai.com/v1/chat/completions",
133
  headers=HEADERS,
134
  json={
135
+ "model": "gpt-3.5-turbo-1106", # or "gpt-4-1106-preview" if you have it
136
  "messages": messages,
137
  "functions": function_schema,
138
  "function_call": "auto",
 
145
  response_json = chat_resp.json()
146
  msg = response_json["choices"][0]["message"]
147
 
148
+ # If OpenAI requests a function call
149
  if msg.get("function_call"):
150
  func_name = msg["function_call"]["name"]
151
  args_json = msg["function_call"]["arguments"]
152
  args = json.loads(args_json)
153
+ # Call the appropriate function
154
+ if func_name in function_map:
155
+ function_result = function_map[func_name](**args)
156
+ else:
157
+ function_result = {"error": f"Unknown function: {func_name}"}
158
 
159
+ # Send function result back for final answer
160
  followup_messages = [
161
+ system_message,
 
 
 
 
 
162
  {"role": "user", "content": prompt},
163
  {
164
  "role": "function",
165
  "name": func_name,
166
+ "content": json.dumps(function_result),
167
  }
168
  ]
169
 
 
171
  "https://api.openai.com/v1/chat/completions",
172
  headers=HEADERS,
173
  json={
174
+ "model": "gpt-3.5-turbo-1106",
175
  "messages": followup_messages,
176
  "temperature": 0,
177
  "max_tokens": 1500,
 
183
 
184
  st.subheader("✅ Agent Answer")
185
  st.markdown(answer)
186
+ st.subheader("🔎 Function Output")
187
+ st.json(function_result)
188
  else:
189
  # No function call: model answered directly
190
  st.subheader("✅ Agent Answer")