Update app.py
Browse files
app.py
CHANGED
@@ -19,6 +19,8 @@ from langgraph.prebuilt import create_react_agent
|
|
19 |
|
20 |
|
21 |
# Show title and description.
|
|
|
|
|
22 |
st.title("Coder for NextJS Templates")
|
23 |
st.markdown(
|
24 |
"This chatbot connects to a Next.JS Github Repository to answer questions and modify code "
|
@@ -179,17 +181,14 @@ else:
|
|
179 |
else:
|
180 |
llm = ChatAnthropic(temperature=0, model_name="claude-3-haiku-20240307")
|
181 |
|
182 |
-
|
|
|
183 |
Your task is to answer user queries about the repository or execute tasks for modifying it.
|
184 |
-
|
185 |
Before performing any operation, always use the force_clone_repo tool to ensure you have the latest version of the repository.
|
186 |
-
|
187 |
Here is all of the code from the repository as well as the file paths for context of how the repo is structured: {REPO_CONTENT}
|
188 |
-
|
189 |
Given this context, follow this prompt in completing the user's task:
|
190 |
For user questions, provide direct answers based on the current state of the repository.
|
191 |
For tasks given by the user, use the available tools and your knowledge of the repo to make necessary changes to the repository.
|
192 |
-
|
193 |
When making changes, remember to force clone the repository first, make the changes, and then commit and push the changes.
|
194 |
Available tools:
|
195 |
1. shell_tool: Execute shell commands
|
@@ -198,8 +197,13 @@ else:
|
|
198 |
4. commit_and_push: Commit and push changes to the repository
|
199 |
5. read_file: Read content from a specific file in the repository
|
200 |
When using the write_file tool, always provide both the file_path and the content as separate arguments.
|
201 |
-
|
202 |
Respond to the human's messages and use tools when necessary to complete tasks. Take a deep breath and think through the task step by step:"""
|
|
|
|
|
|
|
|
|
|
|
|
|
203 |
|
204 |
from langgraph.checkpoint import MemorySaver
|
205 |
|
@@ -282,23 +286,29 @@ else:
|
|
282 |
repo_contents_json = json.dumps(repo_contents, ensure_ascii=False, indent=2)
|
283 |
st.session_state.REPO_CONTENT = repo_contents_json
|
284 |
st.success("Repository content refreshed successfully.")
|
285 |
-
|
286 |
-
# Update the system
|
287 |
-
st.session_state.
|
288 |
-
|
289 |
-
|
290 |
-
|
|
|
291 |
if st.session_state.use_sonnet and "ANTHROPIC_API_KEY" in os.environ:
|
292 |
new_llm = ChatAnthropic(temperature=0, model_name="claude-3-5-sonnet-20240620")
|
293 |
else:
|
294 |
new_llm = ChatAnthropic(temperature=0, model_name="claude-3-haiku-20240307")
|
295 |
|
296 |
-
|
297 |
new_llm,
|
298 |
tools=tools,
|
299 |
-
messages_modifier=st.session_state.
|
300 |
checkpointer=memory
|
301 |
)
|
|
|
|
|
|
|
|
|
|
|
302 |
|
303 |
if st.session_state.use_sonnet and "ANTHROPIC_API_KEY" in os.environ:
|
304 |
refresh_repo_data()
|
@@ -311,26 +321,32 @@ else:
|
|
311 |
if "system_prompt" not in st.session_state:
|
312 |
st.session_state.system_prompt = system_prompt_template.format(REPO_CONTENT=st.session_state.REPO_CONTENT)
|
313 |
|
314 |
-
|
|
|
315 |
llm,
|
316 |
tools=tools,
|
317 |
-
messages_modifier=st.session_state.
|
318 |
checkpointer=memory
|
319 |
)
|
320 |
-
|
321 |
-
|
322 |
-
|
|
|
|
|
|
|
323 |
async def run_github_editor(query: str, thread_id: str = "default"):
|
324 |
inputs = {"messages": [HumanMessage(content=query)]}
|
325 |
config = {
|
326 |
"configurable": {"thread_id": thread_id},
|
327 |
-
"recursion_limit": 50
|
328 |
}
|
329 |
-
|
330 |
st.write(f"Human: {query}\n")
|
331 |
-
|
332 |
current_thought = ""
|
333 |
-
|
|
|
|
|
334 |
async for event in graph.astream_events(inputs, config=config, version="v2"):
|
335 |
kind = event["event"]
|
336 |
if kind == "on_chat_model_start":
|
@@ -347,9 +363,9 @@ else:
|
|
347 |
current_thought = ""
|
348 |
else:
|
349 |
st.write(content, end="")
|
350 |
-
elif kind == "on_tool_start":
|
351 |
st.write(f"\nUsing tool: {event['name']}")
|
352 |
-
elif kind == "on_tool_end":
|
353 |
st.write(f"Tool result: {event['data']['output']}\n")
|
354 |
|
355 |
# Create a session state variable to store the chat messages. This ensures that the
|
@@ -368,12 +384,11 @@ else:
|
|
368 |
|
369 |
# Create a chat input field to allow the user to enter a message. This will display
|
370 |
# automatically at the bottom of the page.
|
371 |
-
if prompt := st.chat_input("Give me a Task!"):
|
372 |
-
|
373 |
# Store and display the current prompt.
|
374 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
375 |
with st.chat_message("user"):
|
376 |
st.markdown(prompt)
|
377 |
-
|
378 |
# Generate a response using the custom chatbot logic.
|
379 |
asyncio.run(run_github_editor(prompt))
|
|
|
19 |
|
20 |
|
21 |
# Show title and description.
|
22 |
+
# Add a radio button for mode selection
|
23 |
+
mode = st.radio("Select Mode", ["Q/A", "Task"])
|
24 |
st.title("Coder for NextJS Templates")
|
25 |
st.markdown(
|
26 |
"This chatbot connects to a Next.JS Github Repository to answer questions and modify code "
|
|
|
181 |
else:
|
182 |
llm = ChatAnthropic(temperature=0, model_name="claude-3-haiku-20240307")
|
183 |
|
184 |
+
# Modify the system prompts
|
185 |
+
task_system_prompt_template = """You are an AI specialized in managing and analyzing a GitHub repository for a Next.js blog website.
|
186 |
Your task is to answer user queries about the repository or execute tasks for modifying it.
|
|
|
187 |
Before performing any operation, always use the force_clone_repo tool to ensure you have the latest version of the repository.
|
|
|
188 |
Here is all of the code from the repository as well as the file paths for context of how the repo is structured: {REPO_CONTENT}
|
|
|
189 |
Given this context, follow this prompt in completing the user's task:
|
190 |
For user questions, provide direct answers based on the current state of the repository.
|
191 |
For tasks given by the user, use the available tools and your knowledge of the repo to make necessary changes to the repository.
|
|
|
192 |
When making changes, remember to force clone the repository first, make the changes, and then commit and push the changes.
|
193 |
Available tools:
|
194 |
1. shell_tool: Execute shell commands
|
|
|
197 |
4. commit_and_push: Commit and push changes to the repository
|
198 |
5. read_file: Read content from a specific file in the repository
|
199 |
When using the write_file tool, always provide both the file_path and the content as separate arguments.
|
|
|
200 |
Respond to the human's messages and use tools when necessary to complete tasks. Take a deep breath and think through the task step by step:"""
|
201 |
+
|
202 |
+
qa_system_prompt_template = """You are an AI specialized in analyzing a GitHub repository for a Next.js blog website.
|
203 |
+
Your task is to answer user queries about the repository based on the provided content.
|
204 |
+
Here is all of the code from the repository as well as the file paths for context of how the repo is structured: {REPO_CONTENT}
|
205 |
+
Given this context, provide direct answers to user questions based on the current state of the repository.
|
206 |
+
Take a deep breath and think through the question step by step before answering:"""
|
207 |
|
208 |
from langgraph.checkpoint import MemorySaver
|
209 |
|
|
|
286 |
repo_contents_json = json.dumps(repo_contents, ensure_ascii=False, indent=2)
|
287 |
st.session_state.REPO_CONTENT = repo_contents_json
|
288 |
st.success("Repository content refreshed successfully.")
|
289 |
+
|
290 |
+
# Update the system prompts with the new repo content
|
291 |
+
st.session_state.task_system_prompt = task_system_prompt_template.format(REPO_CONTENT=st.session_state.REPO_CONTENT)
|
292 |
+
st.session_state.qa_system_prompt = qa_system_prompt_template.format(REPO_CONTENT=st.session_state.REPO_CONTENT)
|
293 |
+
|
294 |
+
# Recreate the graphs with the updated system prompts
|
295 |
+
global task_graph, qa_graph
|
296 |
if st.session_state.use_sonnet and "ANTHROPIC_API_KEY" in os.environ:
|
297 |
new_llm = ChatAnthropic(temperature=0, model_name="claude-3-5-sonnet-20240620")
|
298 |
else:
|
299 |
new_llm = ChatAnthropic(temperature=0, model_name="claude-3-haiku-20240307")
|
300 |
|
301 |
+
task_graph = create_react_agent(
|
302 |
new_llm,
|
303 |
tools=tools,
|
304 |
+
messages_modifier=st.session_state.task_system_prompt,
|
305 |
checkpointer=memory
|
306 |
)
|
307 |
+
|
308 |
+
qa_graph = create_react_agent(
|
309 |
+
new_llm,
|
310 |
+
messages_modifier=st.session_state.qa_system_prompt
|
311 |
+
)
|
312 |
|
313 |
if st.session_state.use_sonnet and "ANTHROPIC_API_KEY" in os.environ:
|
314 |
refresh_repo_data()
|
|
|
321 |
if "system_prompt" not in st.session_state:
|
322 |
st.session_state.system_prompt = system_prompt_template.format(REPO_CONTENT=st.session_state.REPO_CONTENT)
|
323 |
|
324 |
+
# Create separate graphs for Task and Q/A modes
|
325 |
+
task_graph = create_react_agent(
|
326 |
llm,
|
327 |
tools=tools,
|
328 |
+
messages_modifier=st.session_state.task_system_prompt,
|
329 |
checkpointer=memory
|
330 |
)
|
331 |
+
|
332 |
+
qa_graph = create_react_agent(
|
333 |
+
llm,
|
334 |
+
messages_modifier=st.session_state.qa_system_prompt
|
335 |
+
)
|
336 |
+
|
337 |
async def run_github_editor(query: str, thread_id: str = "default"):
|
338 |
inputs = {"messages": [HumanMessage(content=query)]}
|
339 |
config = {
|
340 |
"configurable": {"thread_id": thread_id},
|
341 |
+
"recursion_limit": 50
|
342 |
}
|
343 |
+
|
344 |
st.write(f"Human: {query}\n")
|
345 |
+
|
346 |
current_thought = ""
|
347 |
+
|
348 |
+
graph = task_graph if mode == "Task" else qa_graph
|
349 |
+
|
350 |
async for event in graph.astream_events(inputs, config=config, version="v2"):
|
351 |
kind = event["event"]
|
352 |
if kind == "on_chat_model_start":
|
|
|
363 |
current_thought = ""
|
364 |
else:
|
365 |
st.write(content, end="")
|
366 |
+
elif kind == "on_tool_start" and mode == "Task":
|
367 |
st.write(f"\nUsing tool: {event['name']}")
|
368 |
+
elif kind == "on_tool_end" and mode == "Task":
|
369 |
st.write(f"Tool result: {event['data']['output']}\n")
|
370 |
|
371 |
# Create a session state variable to store the chat messages. This ensures that the
|
|
|
384 |
|
385 |
# Create a chat input field to allow the user to enter a message. This will display
|
386 |
# automatically at the bottom of the page.
|
387 |
+
if prompt := st.chat_input(f"{'Ask a question' if mode == 'Q/A' else 'Give me a Task'}!"):
|
|
|
388 |
# Store and display the current prompt.
|
389 |
st.session_state.messages.append({"role": "user", "content": prompt})
|
390 |
with st.chat_message("user"):
|
391 |
st.markdown(prompt)
|
392 |
+
|
393 |
# Generate a response using the custom chatbot logic.
|
394 |
asyncio.run(run_github_editor(prompt))
|