jinysun commited on
Commit
fd4a189
Β·
verified Β·
1 Parent(s): c092ac0

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +194 -242
app.py CHANGED
@@ -1,7 +1,5 @@
1
  import os
2
  import asyncio
3
-
4
-
5
  import openai
6
  import pandas as pd
7
  import streamlit as st
@@ -16,6 +14,8 @@ import tempfile
16
 
17
  load_dotenv()
18
 
 
 
19
  def convert_to_base64(pil_image):
20
  buffered = BytesIO()
21
  pil_image.save(buffered, format="PNG")
@@ -25,119 +25,128 @@ def convert_to_base64(pil_image):
25
  def oai_key_isvalid(api_key):
26
  """Check if a given OpenAI key is valid"""
27
  try:
 
 
 
 
28
  if os.getenv("OPENAI_API_BASE"):
29
  llm = ChatOpenAI(openai_api_key=api_key, base_url=os.getenv("OPENAI_API_BASE"))
30
- out = llm.invoke("This is a test")
31
  else:
32
  llm = ChatOpenAI(openai_api_key=api_key)
33
- out = llm.invoke("This is a test")
34
  return True
35
  except:
36
  return False
37
 
38
  def initialize_session_state():
39
  """Initialize all session state variables"""
40
- if 'prompt' not in st.session_state:
41
- st.session_state['prompt'] = None
42
- if 'agent' not in st.session_state:
43
- st.session_state['agent'] = None
44
- if 'api_key' not in st.session_state:
45
- st.session_state['api_key'] = os.getenv('OPENAI_API_KEY', 'none')
46
- if 'base_url' not in st.session_state:
47
- st.session_state['base_url'] = ''
48
- if 'model1_select' not in st.session_state:
49
- st.session_state['model1_select'] = ''
50
- if 'model2_select' not in st.session_state:
51
- st.session_state['model2_select'] = ''
52
- if 'serp_api' not in st.session_state:
53
- st.session_state['serp_api'] = 'none'
54
- if 'semantic_scholar_url' not in st.session_state:
55
- st.session_state['semantic_scholar_url'] = 'none'
56
- if 'file_type' not in st.session_state:
57
- st.session_state['file_type'] = 'None'
58
- if 'domain' not in st.session_state:
59
- st.session_state['domain'] = 'Organic solar cell'
60
-
61
- def instantiate_agent(model1, model2, file_path='...', image_path='...', tools=None):
62
- """Create or update agent instance"""
63
 
64
- try:
65
- st.session_state['agent'] = TeLLAgent(
66
- tools=tools,
67
- model1=model1,
68
- model2=model2,
69
- tools_model='gpt-4o-2024-11-20',
70
- temp=0.1,
71
- openai_api_key=st.session_state.get('api_key'),
72
- file_path=file_path,
73
- image_path=image_path
74
- )
75
- except Exception as e:
76
- st.error(f"Error instantiating agent: {str(e)}")
77
- st.session_state['agent'] = None
78
 
79
- return st.session_state.get('agent')
 
 
 
 
 
 
80
 
81
- def on_api_key_change():
82
- api_key = st.session_state.get('api_key') or os.getenv('OPENAI_API_KEY')
83
- if not oai_key_isvalid(api_key):
84
- st.write("Please input a valid OpenAI API key.")
 
 
 
 
 
 
 
 
 
 
85
 
86
- def run_prompt(prompt, file_path='...', image_path='...'):
87
- """Execute prompt with agent"""
88
- try:
89
- if st.session_state.get('domain') == 'Drug discovery':
90
- agent = instantiate_agent(
91
- model1=st.session_state.get('model1_select'),
92
- model2=st.session_state.get('model2_select'),
93
- file_path=file_path,
94
- image_path=image_path,
95
- tools='drug'
96
- )
97
- else:
98
- agent = instantiate_agent(
99
- model1=st.session_state.get('model1_select'),
100
- model2=st.session_state.get('model2_select'),
101
- file_path=file_path,
 
 
102
  image_path=image_path
103
  )
104
-
105
- if agent is None:
106
- st.error("Failed to create agent. Please check your API key and settings.")
107
- return
108
 
109
- st.chat_message("user").write(prompt)
110
-
111
- with st.chat_message("assistant"):
112
- try:
113
- response = agent.run(prompt)
114
- if st.session_state.get('file_type') == 'CSV (.csv)':
115
- try:
116
- fx = pd.DataFrame(list(response))
117
- st.markdown(":red[Prediction finished! ]")
118
- st.download_button(
119
- "⬇️Download the predicted files as .csv",
120
- fx.to_csv(),
121
- "predict results.csv",
122
- use_container_width=True
123
- )
124
- except:
125
- st.write(response)
126
- else:
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
127
  st.write(response)
128
- except openai.AuthenticationError:
129
- st.write("Please input a valid OpenAI API key")
130
- except openai.APIError as e:
131
- st.error(f"OpenAI API error: {str(e)}")
132
- except Exception as e:
133
- st.error(f"Error running prompt: {str(e)}")
134
- except Exception as e:
135
- st.error(f"Error in run_prompt: {str(e)}")
 
 
 
 
 
136
 
137
  def main():
138
- """Main application function"""
139
  initialize_session_state()
140
- # Init with fake key
 
141
  if 'OPENAI_API_KEY' not in os.environ:
142
  os.environ['OPENAI_API_KEY'] = 'none'
143
  os.environ["SERP_API_KEY"] = 'none'
@@ -146,186 +155,129 @@ def main():
146
  if os.name == 'nt':
147
  asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
148
 
149
- # Set width of sidebar
150
  st.markdown(
151
  """
152
  <style>
153
  [data-testid="stSidebar"][aria-expanded="true"]{
154
- min-width: 500px;
155
- max-width: 500px;
156
  }
157
  </style>
158
  """,
159
  unsafe_allow_html=True,
160
  )
161
 
162
- # Initialize session state
163
-
164
-
165
- pre_prompts = [
166
- 'Generate a donor with PCE = 10% ',
167
- 'The history and development of Y6',
168
- 'Predict the LogP of PM6',
169
- 'Predict the PCE of Y6'
170
- ]
171
-
172
- # Sidebar
173
  with st.sidebar:
174
  st.header("πŸ€– :blue[TeLLAgent] ")
175
 
176
- # Input OpenAI api key
177
- st.text_input(
178
- 'Input your OpenAI API key.',
179
- placeholder='Input your OpenAI API key.',
180
- type='password',
181
- key='api_key',
182
- on_change=on_api_key_change,
183
- label_visibility="collapsed"
184
- )
185
 
186
- st.text_input(
187
- 'Input base url (optional).',
188
- placeholder='Input base url (optional)',
189
- key='base_url',
190
- type='password',
191
- label_visibility="collapsed"
192
- )
193
 
194
- # Input model to use
195
- st.text_input(
196
- 'Input global planning model to use',
197
- key='model1_select',
198
- )
199
 
200
- st.text_input(
201
- 'Input local execution model to use',
202
- key='model2_select',
203
- )
 
 
204
 
205
- st.text_input(
206
- 'Input SERP API KEY (optional).',
207
- placeholder='Input SERP API KEY (optional)',
208
- key='serp_api',
209
- type='password',
210
- label_visibility="collapsed"
211
- )
212
-
213
- st.text_input(
214
- 'Input SEMANTIC SCHOLAR API KEY (optional).',
215
- placeholder='Input SEMANTIC SCHOLAR API KEY (optional)',
216
- key='semantic_scholar_url',
217
- type='password',
218
- label_visibility="collapsed"
219
- )
220
-
221
- user_api_key = st.session_state.get('api_key')
222
- user_base_url = st.session_state.get('base_url')
223
-
224
- if user_api_key:
225
- os.environ['OPENAI_API_KEY'] = user_api_key
226
-
227
- if user_base_url and user_base_url.strip() != "" and user_base_url != "none":
228
- os.environ["OPENAI_API_BASE"] = user_base_url
229
- else:
230
- if "OPENAI_API_BASE" in os.environ:
231
- del os.environ["OPENAI_API_BASE"]
232
-
233
- os.environ["SERP_API_KEY"] = st.session_state.get('serp_api', 'none')
234
- os.environ["SEMANTIC_SCHOLAR_API_KEY"] = st.session_state.get('semantic_scholar_url', 'none')
235
-
236
- # Display prompt examples
237
- st.markdown('# What can I ask?')
238
- cols = st.columns(2)
239
- with cols[0]:
240
- st.button(
241
- r'πŸ‘‘ Generate a donor with PCE = 10% 🧨',
242
- on_click=lambda: run_prompt(pre_prompts[0]),
243
- )
244
- st.button(
245
- r'πŸ“š The history and development of Y6',
246
- on_click=lambda: run_prompt(pre_prompts[1]),
247
- )
248
- with cols[1]:
249
- st.button(
250
- r"πŸŽ„Predict the LogP of PM6",
251
- on_click=lambda: run_prompt(pre_prompts[2]),
252
- )
253
- st.button(
254
- r'πŸ’Ž Predict the PCE of Y6',
255
- on_click=lambda: run_prompt(pre_prompts[3]),
256
- )
257
-
258
- st.selectbox(
259
- 'Select the file type',
260
- ['None', 'CSV (.csv)', 'Figure (.jpg, .png, .jpeg)', 'PDF (.pdf)'],
261
- key='file_type',
262
- )
263
 
 
 
264
  uploaded_file = None
265
- if st.session_state.get('file_type') == 'Figure (.jpg, .png, .jpeg)':
 
 
 
266
  uploaded_file = st.file_uploader("Choose a Figure", type=["jpg", "jpeg", "png"])
267
- if st.session_state.get('file_type') == 'PDF (.pdf)':
 
 
 
 
 
 
 
 
268
  uploaded_file = st.file_uploader("Choose a PDF file")
269
- if st.session_state.get('file_type') == 'CSV (.csv)':
 
 
 
 
 
 
270
  uploaded_file = st.file_uploader("Choose a csv file", type='csv')
271
-
272
- st.selectbox(
273
- r'πŸ“š Choose the domain',
274
- ['Organic solar cell', 'Drug discovery'],
275
- key='domain',
276
- )
277
 
278
- # Display available tools - only initialize agent if not already done
279
- if st.session_state.get('agent') is None:
280
- if st.session_state.get('domain') == 'Drug discovery':
281
- instantiate_agent(
282
- model1='gpt-4o-2024-11-20',
283
- model2='gpt-4o-2024-11-20',
284
- tools='drug'
285
- )
286
- else:
287
- instantiate_agent(
288
- model1='gpt-4o-2024-11-20',
289
- model2='gpt-4o-2024-11-20'
290
- )
291
 
292
- # Safely display tools
 
 
 
293
  agent = st.session_state.get('agent')
294
  if agent is not None and hasattr(agent, 'agent_executor2'):
295
  try:
296
  tools = agent.agent_executor2.tools
297
- tool_list = pd.Series(
298
- {f"βœ… {t.name}": t.description for t in tools}
299
- ).reset_index()
300
  tool_list.columns = ['Tool', 'Description']
301
- st.markdown(f"# {len(tool_list)} available tools")
302
- st.dataframe(
303
- tool_list,
304
- use_container_width=True,
305
- hide_index=True,
306
- height=200
307
- )
308
- except Exception as e:
309
- st.warning(f"Could not load tools: {str(e)}")
310
  else:
311
- st.info("Agent not initialized. Please check your API key.")
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
312
 
313
- # Execute agent on user input
314
- if prompt := st.chat_input("Say something and/or attach files"):
315
- uploaded_file = None
316
- if st.session_state.get('file_type') == 'Figure (.jpg, .png, .jpeg)':
317
- # Re-get uploaded file for main area
318
- pass
319
- elif st.session_state.get('file_type') == 'PDF (.pdf)':
320
- pass
321
- elif st.session_state.get('file_type') == 'CSV (.csv)':
322
- pass
323
-
324
- # Check if file was uploaded in sidebar
325
- # Note: uploaded_file needs to be handled differently in Streamlit
326
- # For now, just run the prompt
327
  run_prompt(prompt)
328
 
329
- # Run the main function
330
  if __name__ == "__main__":
331
  main()
 
1
  import os
2
  import asyncio
 
 
3
  import openai
4
  import pandas as pd
5
  import streamlit as st
 
14
 
15
  load_dotenv()
16
 
17
+ # --- Helper Functions ---
18
+
19
  def convert_to_base64(pil_image):
20
  buffered = BytesIO()
21
  pil_image.save(buffered, format="PNG")
 
25
  def oai_key_isvalid(api_key):
26
  """Check if a given OpenAI key is valid"""
27
  try:
28
+ # Simple check without invoking expensive calls if possible,
29
+ # or keep the invoke if you want strict validation.
30
+ if not api_key or api_key == 'none': return False
31
+
32
  if os.getenv("OPENAI_API_BASE"):
33
  llm = ChatOpenAI(openai_api_key=api_key, base_url=os.getenv("OPENAI_API_BASE"))
 
34
  else:
35
  llm = ChatOpenAI(openai_api_key=api_key)
36
+ llm.invoke("Hi")
37
  return True
38
  except:
39
  return False
40
 
41
  def initialize_session_state():
42
  """Initialize all session state variables"""
43
+ # UI States
44
+ if 'prompt' not in st.session_state: st.session_state['prompt'] = None
45
+ if 'file_type' not in st.session_state: st.session_state['file_type'] = 'None'
46
+ if 'domain' not in st.session_state: st.session_state['domain'] = 'Organic solar cell'
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
 
48
+ # Config States (Defaults)
49
+ if 'model1_select' not in st.session_state: st.session_state['model1_select'] = 'deepseek-ai/DeepSeek-R1'
50
+ if 'model2_select' not in st.session_state: st.session_state['model2_select'] = 'deepseek-ai/DeepSeek-v3.1'
51
+ if 'api_key' not in st.session_state: st.session_state['api_key'] = os.getenv('OPENAI_API_KEY', '')
 
 
 
 
 
 
 
 
 
 
52
 
53
+ # Agent & Logic States
54
+ if 'agent' not in st.session_state: st.session_state['agent'] = None
55
+ if 'last_agent_config' not in st.session_state: st.session_state['last_agent_config'] = {}
56
+
57
+ # File Paths
58
+ if 'current_file_path' not in st.session_state: st.session_state['current_file_path'] = '...'
59
+ if 'current_image_path' not in st.session_state: st.session_state['current_image_path'] = '...'
60
 
61
+ def update_agent_if_needed(current_config):
62
+ """
63
+ Compare current_config with the last used config.
64
+ If changed, instantiate the agent automatically.
65
+ """
66
+ last_config = st.session_state.get('last_agent_config', {})
67
+
68
+ # Check if config changed or agent is missing
69
+ if st.session_state['agent'] is None or current_config != last_config:
70
+
71
+ # Validations
72
+ if not current_config['api_key'] or current_config['api_key'] == 'none':
73
+ # Don't try to init if no key, just return
74
+ return
75
 
76
+ model1 = current_config['model1'] or "deepseek-ai/DeepSeek-R1"
77
+ model2 = current_config['model2'] or "deepseek-ai/DeepSeek-v3.1"
78
+ domain = current_config['domain']
79
+ file_path = current_config['file_path']
80
+ image_path = current_config['image_path']
81
+
82
+ tools_setting = 'drug' if domain == 'Drug discovery' else None
83
+
84
+ try:
85
+ # Create the agent
86
+ new_agent = TeLLAgent(
87
+ tools=tools_setting,
88
+ model1=model1,
89
+ model2=model2,
90
+ tools_model='gpt-4o-2024-11-20',
91
+ temp=0.1,
92
+ openai_api_key=current_config['api_key'],
93
+ file_path=file_path,
94
  image_path=image_path
95
  )
 
 
 
 
96
 
97
+ st.session_state['agent'] = new_agent
98
+ st.session_state['last_agent_config'] = current_config # Update history
99
+
100
+ # Optional: Toast notification to show user it updated
101
+ # st.toast(f"Agent updated! (Model: {model1})", icon="πŸ€–")
102
+
103
+ except Exception as e:
104
+ st.error(f"Auto-initialization failed: {str(e)}")
105
+ st.session_state['agent'] = None
106
+
107
+ def run_prompt(prompt):
108
+ """Execute prompt using the already initialized agent"""
109
+ agent = st.session_state.get('agent')
110
+
111
+ if agent is None:
112
+ st.error("Agent is not ready. Please check your API Key and Model settings.")
113
+ return
114
+
115
+ st.chat_message("user").write(prompt)
116
+
117
+ with st.chat_message("assistant"):
118
+ try:
119
+ response = agent.run(prompt)
120
+ if st.session_state.get('file_type') == 'CSV (.csv)':
121
+ try:
122
+ fx = pd.DataFrame(list(response))
123
+ st.markdown(":red[Prediction finished! ]")
124
+ st.download_button(
125
+ "⬇️Download the predicted files as .csv",
126
+ fx.to_csv(),
127
+ "predict results.csv",
128
+ use_container_width=True
129
+ )
130
+ except:
131
  st.write(response)
132
+ else:
133
+ st.write(response)
134
+ except openai.AuthenticationError:
135
+ st.write("Please input a valid OpenAI API key")
136
+ except openai.APIError as e:
137
+ st.error(f"OpenAI API error: {str(e)}")
138
+ except Exception as e:
139
+ st.error(f"Error running prompt: {str(e)}")
140
+
141
+ def on_api_key_change():
142
+ """Callback when API key changes"""
143
+ # Logic is now handled by auto-update, but we can do validation here
144
+ pass
145
 
146
  def main():
 
147
  initialize_session_state()
148
+
149
+ # Environment Defaults
150
  if 'OPENAI_API_KEY' not in os.environ:
151
  os.environ['OPENAI_API_KEY'] = 'none'
152
  os.environ["SERP_API_KEY"] = 'none'
 
155
  if os.name == 'nt':
156
  asyncio.set_event_loop_policy(asyncio.WindowsProactorEventLoopPolicy())
157
 
158
+ # Sidebar Setup
159
  st.markdown(
160
  """
161
  <style>
162
  [data-testid="stSidebar"][aria-expanded="true"]{
163
+ min-width: 500px; max-width: 500px;
 
164
  }
165
  </style>
166
  """,
167
  unsafe_allow_html=True,
168
  )
169
 
170
+ # --- Sidebar Inputs ---
 
 
 
 
 
 
 
 
 
 
171
  with st.sidebar:
172
  st.header("πŸ€– :blue[TeLLAgent] ")
173
 
174
+ # 1. Credentials
175
+ api_key_input = st.text_input('Input your OpenAI API key.', type='password', key='api_key', label_visibility="collapsed")
176
+ base_url_input = st.text_input('Input base url (optional).', key='base_url', type='password', label_visibility="collapsed")
 
 
 
 
 
 
177
 
178
+ # 2. Model Configuration
179
+ # Defaults are set in initialize_session_state, user can change them here
180
+ model1_input = st.text_input('Input global planning model to use', key='model1_select')
181
+ model2_input = st.text_input('Input local execution model to use', key='model2_select')
 
 
 
182
 
183
+ # 3. External Tools Keys
184
+ serp_input = st.text_input('Input SERP API KEY (optional).', key='serp_api', type='password', label_visibility="collapsed")
185
+ scholar_input = st.text_input('Input SEMANTIC SCHOLAR API KEY (optional).', key='semantic_scholar_url', type='password', label_visibility="collapsed")
 
 
186
 
187
+ # Update OS Environ
188
+ if api_key_input: os.environ['OPENAI_API_KEY'] = api_key_input
189
+ if base_url_input and base_url_input != "none": os.environ["OPENAI_API_BASE"] = base_url_input
190
+ elif "OPENAI_API_BASE" in os.environ: del os.environ["OPENAI_API_BASE"]
191
+ os.environ["SERP_API_KEY"] = serp_input if serp_input else 'none'
192
+ os.environ["SEMANTIC_SCHOLAR_API_KEY"] = scholar_input if scholar_input else 'none'
193
 
194
+ # 4. Domain & Files
195
+ st.selectbox(r'πŸ“š Choose the domain', ['Organic solar cell', 'Drug discovery'], key='domain')
196
+ st.selectbox('Select the file type', ['None', 'CSV (.csv)', 'Figure (.jpg, .png, .jpeg)', 'PDF (.pdf)'], key='file_type')
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
197
 
198
+ # --- File Processing (Immediate) ---
199
+ # We process files HERE so the paths are ready for the Agent Auto-Init immediately after.
200
  uploaded_file = None
201
+ current_file_path = '...'
202
+ current_image_path = '...'
203
+
204
+ if st.session_state['file_type'] == 'Figure (.jpg, .png, .jpeg)':
205
  uploaded_file = st.file_uploader("Choose a Figure", type=["jpg", "jpeg", "png"])
206
+ if uploaded_file:
207
+ st.image(uploaded_file, width=200)
208
+ with tempfile.NamedTemporaryFile(delete=False, suffix=".png") as temp:
209
+ img_str = base64.b64encode(uploaded_file.getvalue()).decode("utf-8")
210
+ temp.write(base64.b64decode(img_str))
211
+ current_image_path = temp.name
212
+ st.session_state['current_image_path'] = temp.name # Persist
213
+
214
+ elif st.session_state['file_type'] == 'PDF (.pdf)':
215
  uploaded_file = st.file_uploader("Choose a PDF file")
216
+ if uploaded_file:
217
+ with tempfile.NamedTemporaryFile(suffix='.pdf', delete=False) as f:
218
+ f.write(uploaded_file.read())
219
+ current_file_path = f.name
220
+ st.session_state['current_file_path'] = f.name
221
+
222
+ elif st.session_state['file_type'] == 'CSV (.csv)':
223
  uploaded_file = st.file_uploader("Choose a csv file", type='csv')
224
+ if uploaded_file:
225
+ with tempfile.NamedTemporaryFile(suffix='.csv', delete=False) as f:
226
+ f.write(uploaded_file.read())
227
+ current_file_path = f.name
228
+ st.session_state['current_file_path'] = f.name
 
229
 
230
+ # --- AUTOMATIC AGENT INITIALIZATION ---
231
+ # Collect current config into a dict
232
+ current_config = {
233
+ 'api_key': api_key_input,
234
+ 'base_url': base_url_input,
235
+ 'model1': model1_input,
236
+ 'model2': model2_input,
237
+ 'domain': st.session_state['domain'],
238
+ 'file_path': current_file_path, # Uses the temp path created just now
239
+ 'image_path': current_image_path # Uses the temp path created just now
240
+ }
 
 
241
 
242
+ # Trigger the check & init logic
243
+ update_agent_if_needed(current_config)
244
+
245
+ # Show Tools status
246
  agent = st.session_state.get('agent')
247
  if agent is not None and hasattr(agent, 'agent_executor2'):
248
  try:
249
  tools = agent.agent_executor2.tools
250
+ tool_list = pd.Series({f"βœ… {t.name}": t.description for t in tools}).reset_index()
 
 
251
  tool_list.columns = ['Tool', 'Description']
252
+ st.dataframe(tool_list, use_container_width=True, hide_index=True, height=150)
253
+ except: pass
 
 
 
 
 
 
 
254
  else:
255
+ if not api_key_input:
256
+ st.warning("πŸ”‘ Waiting for API Key...")
257
+
258
+ # Pre-defined Prompts
259
+
260
+ st.markdown('# What can I ask?')
261
+
262
+ pre_prompts = [
263
+ 'Generate a donor with PCE = 10% ',
264
+ 'The history and development of Y6',
265
+ 'Predict the LogP of PM6',
266
+ 'Predict the PCE of Y6'
267
+ ]
268
+
269
+ cols = st.columns(2)
270
+ with cols[0]:
271
+ st.button(r'πŸ‘‘ Generate a donor...', on_click=lambda: run_prompt(pre_prompts[0]))
272
+ st.button(r'πŸ“š History of Y6', on_click=lambda: run_prompt(pre_prompts[1]))
273
+ with cols[1]:
274
+ st.button(r"πŸŽ„Predict LogP of PM6", on_click=lambda: run_prompt(pre_prompts[2]))
275
+ st.button(r'πŸ’Ž Predict PCE of Y6', on_click=lambda: run_prompt(pre_prompts[3]))
276
 
277
+ # --- Main Chat Area ---
278
+ if prompt := st.chat_input("Say something..."):
279
+ # Append context about file if needed, though Agent handles files via init args mostly.
 
 
 
 
 
 
 
 
 
 
 
280
  run_prompt(prompt)
281
 
 
282
  if __name__ == "__main__":
283
  main()