Datawithsarah commited on
Commit
de718ca
·
1 Parent(s): 208307a

changed to ChatAgent

Browse files
Files changed (3) hide show
  1. agent.py +25 -18
  2. app.py +43 -48
  3. system_prompt.txt +9 -6
agent.py CHANGED
@@ -16,6 +16,7 @@ from langchain_core.tools import tool
16
  from langchain.tools.retriever import create_retriever_tool
17
  from supabase.client import Client, create_client
18
 
 
19
  load_dotenv()
20
 
21
  # === Tools ===
@@ -69,9 +70,9 @@ with open("system_prompt.txt", "r", encoding="utf-8") as f:
69
  system_prompt = f.read()
70
  sys_msg = SystemMessage(content=system_prompt)
71
 
72
- # === Embeddings and Vector Store ===
73
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
74
- supabase = create_client(os.getenv("SUPABASE_URL"), os.getenv("SUPABASE_SERVICE_KEY"))
75
  vector_store = SupabaseVectorStore(
76
  client=supabase,
77
  embedding=embeddings,
@@ -79,7 +80,7 @@ vector_store = SupabaseVectorStore(
79
  query_name="match_documents_langchain",
80
  )
81
 
82
- # === Tools ===
83
  tools = [multiply, add, subtract, divide, modulus, wiki_search, web_search, arvix_search]
84
 
85
  # === Graph Builder ===
@@ -96,38 +97,44 @@ def build_graph(provider: str = "groq"):
96
  )
97
  )
98
  else:
99
- raise ValueError("Invalid provider. Choose 'google', 'groq' or 'huggingface'.")
100
 
101
  llm_with_tools = llm.bind_tools(tools)
102
 
 
 
 
 
 
103
  def assistant(state: MessagesState):
104
  response = llm_with_tools.invoke(state["messages"])
105
- content = response.content.strip()
106
- # Extract exact match content, remove FINAL ANSWER: if present
107
- if "FINAL ANSWER:" in content:
108
- content = content.split("FINAL ANSWER:")[-1].strip()
109
- return {"messages": [AIMessage(content=content)]}
110
 
111
- def retriever(state: MessagesState):
112
- similar_question = vector_store.similarity_search(state["messages"][0].content)
113
- example_msg = HumanMessage(content=f"Reference: {similar_question[0].page_content}")
114
- return {"messages": [sys_msg] + state["messages"] + [example_msg]}
 
 
 
115
 
116
  builder = StateGraph(MessagesState)
117
  builder.add_node("retriever", retriever)
118
  builder.add_node("assistant", assistant)
119
  builder.add_node("tools", ToolNode(tools))
 
 
120
  builder.add_edge(START, "retriever")
121
  builder.add_edge("retriever", "assistant")
122
  builder.add_conditional_edges("assistant", tools_condition)
123
  builder.add_edge("tools", "assistant")
 
124
 
125
  return builder.compile()
126
 
 
127
  if __name__ == "__main__":
128
- question = "When was a picture of St. Thomas Aquinas first added to the Wikipedia page on the Principle of double effect?"
129
  graph = build_graph("groq")
130
- messages = [HumanMessage(content=question)]
131
- messages = graph.invoke({"messages": messages})
132
- for m in messages["messages"]:
133
- m.pretty_print()
 
16
  from langchain.tools.retriever import create_retriever_tool
17
  from supabase.client import Client, create_client
18
 
19
+ # === Load environment ===
20
  load_dotenv()
21
 
22
  # === Tools ===
 
70
  system_prompt = f.read()
71
  sys_msg = SystemMessage(content=system_prompt)
72
 
73
+ # === Embedding and Supabase Setup ===
74
  embeddings = HuggingFaceEmbeddings(model_name="sentence-transformers/all-mpnet-base-v2")
75
+ supabase: Client = create_client(os.environ.get("SUPABASE_URL"), os.environ.get("SUPABASE_SERVICE_KEY"))
76
  vector_store = SupabaseVectorStore(
77
  client=supabase,
78
  embedding=embeddings,
 
80
  query_name="match_documents_langchain",
81
  )
82
 
83
+ # === Tools List ===
84
  tools = [multiply, add, subtract, divide, modulus, wiki_search, web_search, arvix_search]
85
 
86
  # === Graph Builder ===
 
97
  )
98
  )
99
  else:
100
+ raise ValueError("Invalid provider.")
101
 
102
  llm_with_tools = llm.bind_tools(tools)
103
 
104
+ def retriever(state: MessagesState):
105
+ query = state["messages"][-1].content
106
+ similar = vector_store.similarity_search(query)
107
+ return {"messages": [sys_msg, state["messages"][-1], HumanMessage(content=f"Reference: {similar[0].page_content}")]}
108
+
109
  def assistant(state: MessagesState):
110
  response = llm_with_tools.invoke(state["messages"])
111
+ return {"messages": state["messages"] + [response]}
 
 
 
 
112
 
113
+ def formatter(state: MessagesState):
114
+ last = state["messages"][-1].content.strip()
115
+ if "FINAL ANSWER:" in last:
116
+ answer = last.split("FINAL ANSWER:")[-1].strip()
117
+ else:
118
+ answer = last.strip()
119
+ return {"messages": [AIMessage(content=answer)]}
120
 
121
  builder = StateGraph(MessagesState)
122
  builder.add_node("retriever", retriever)
123
  builder.add_node("assistant", assistant)
124
  builder.add_node("tools", ToolNode(tools))
125
+ builder.add_node("formatter", formatter)
126
+
127
  builder.add_edge(START, "retriever")
128
  builder.add_edge("retriever", "assistant")
129
  builder.add_conditional_edges("assistant", tools_condition)
130
  builder.add_edge("tools", "assistant")
131
+ builder.add_edge("assistant", "formatter")
132
 
133
  return builder.compile()
134
 
135
+ # === Test Entry Point ===
136
  if __name__ == "__main__":
 
137
  graph = build_graph("groq")
138
+ messages = graph.invoke({"messages": [HumanMessage(content="What is the capital of France?")]})
139
+ for msg in messages["messages"]:
140
+ msg.pretty_print()
 
app.py CHANGED
@@ -1,39 +1,27 @@
1
- """ Basic Agent Evaluation Runner"""
2
  import os
3
- import inspect
4
  import gradio as gr
5
- import requests
6
  import pandas as pd
7
- import time
 
8
  from langchain_core.messages import HumanMessage
9
  from agent import build_graph
10
- import re
11
 
 
12
 
13
- # (Keep Constants as is)
14
- # --- Constants ---
15
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
16
-
17
- # --- Basic Agent Definition ---
18
- # ----- THIS IS WERE YOU CAN BUILD WHAT YOU WANT ------
19
-
20
-
21
  cached_answers = []
22
 
23
- def parse_final_answer(raw: str) -> str:
24
- raw = raw.strip()
25
- if "FINAL ANSWER:" in raw:
26
- return raw.split("FINAL ANSWER:")[-1].strip()
27
- return raw.split("Final Answer:")[-1].strip() if "Final Answer:" in raw else raw
28
-
29
- class BasicAgent:
30
  def __init__(self):
 
31
  self.graph = build_graph()
32
 
33
  def __call__(self, question: str) -> str:
 
34
  messages = [HumanMessage(content=question)]
35
- output = self.graph.invoke({"messages": messages})
36
- return parse_final_answer(output['messages'][-1].content)
 
37
 
38
  def run_agent_only(profile: gr.OAuthProfile | None):
39
  global cached_answers
@@ -44,67 +32,74 @@ def run_agent_only(profile: gr.OAuthProfile | None):
44
  return "Please login first.", None
45
 
46
  try:
47
- agent = BasicAgent()
48
  except Exception as e:
49
  return f"Agent Init Error: {e}", None
50
 
51
  try:
52
- questions = requests.get("https://agents-course-unit4-scoring.hf.space/questions", timeout=15).json()
 
53
  except Exception as e:
54
  return f"Error fetching questions: {e}", None
55
 
56
- with open("system_prompt.txt", "r") as f:
57
- system_prompt = f.read().strip()
58
-
59
- for item in questions:
60
  task_id = item.get("task_id")
61
  question = item.get("question")
62
  file_name = item.get("file_name")
63
 
64
- if not task_id or not question:
65
  continue
66
 
67
  try:
68
- user_message = question + (f"\n\nFile to use: {file_name}" if file_name else "")
69
- answer = agent(system_prompt + "\n\n" + user_message)
 
 
 
70
  cached_answers.append({"task_id": task_id, "submitted_answer": answer})
71
  results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": answer})
72
  except Exception as e:
73
  results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": f"AGENT ERROR: {e}"})
74
 
75
- return "Agent finished. Click 'Submit Cached Answers' next.", pd.DataFrame(results_log)
76
 
77
  def submit_cached_answers(profile: gr.OAuthProfile | None):
 
78
  if not profile or not cached_answers:
79
- return "Nothing to submit. Run the agent first.", None
 
 
 
 
80
 
81
  payload = {
82
- "username": profile.username,
83
- "agent_code": f"https://huggingface.co/spaces/{os.getenv('SPACE_ID')}/tree/main",
84
  "answers": cached_answers
85
  }
86
 
87
  try:
88
- response = requests.post("https://agents-course-unit4-scoring.hf.space/submit", json=payload, timeout=60)
89
  result = response.json()
90
- score = result.get("score", "?")
91
- correct = result.get("correct_count", "?")
92
- total = result.get("total_attempted", "?")
93
- return f"Submission complete. Score: {score}% ({correct}/{total})", None
 
94
  except Exception as e:
95
  return f"Submission failed: {e}", None
96
 
 
97
  with gr.Blocks() as demo:
98
- gr.Markdown("""# Agent Evaluator
99
- 1. Login with Hugging Face
100
- 2. Run agent only
101
- 3. Submit answers""")
102
-
103
  gr.LoginButton()
104
- run_button = gr.Button("Run Agent")
105
- submit_button = gr.Button("Submit Cached Answers")
106
- status_box = gr.Textbox(label="Status", lines=4)
107
- table = gr.DataFrame(label="Answers Log")
 
 
108
 
109
  run_button.click(fn=run_agent_only, outputs=[status_box, table])
110
  submit_button.click(fn=submit_cached_answers, outputs=[status_box, table])
 
 
1
  import os
 
2
  import gradio as gr
 
3
  import pandas as pd
4
+ import requests
5
+ from dotenv import load_dotenv
6
  from langchain_core.messages import HumanMessage
7
  from agent import build_graph
 
8
 
9
+ load_dotenv()
10
 
 
 
11
  DEFAULT_API_URL = "https://agents-course-unit4-scoring.hf.space"
 
 
 
 
 
12
  cached_answers = []
13
 
14
+ class ChatAgent:
 
 
 
 
 
 
15
  def __init__(self):
16
+ print("ChatAgent initialized with LangGraph workflow.")
17
  self.graph = build_graph()
18
 
19
  def __call__(self, question: str) -> str:
20
+ print(f"Processing question: {question[:60]}...")
21
  messages = [HumanMessage(content=question)]
22
+ results = self.graph.invoke({"messages": messages})
23
+ answer = results['messages'][-1].content.strip()
24
+ return answer
25
 
26
  def run_agent_only(profile: gr.OAuthProfile | None):
27
  global cached_answers
 
32
  return "Please login first.", None
33
 
34
  try:
35
+ agent = ChatAgent()
36
  except Exception as e:
37
  return f"Agent Init Error: {e}", None
38
 
39
  try:
40
+ response = requests.get(f"{DEFAULT_API_URL}/questions", timeout=15)
41
+ questions_data = response.json()
42
  except Exception as e:
43
  return f"Error fetching questions: {e}", None
44
 
45
+ for item in questions_data:
 
 
 
46
  task_id = item.get("task_id")
47
  question = item.get("question")
48
  file_name = item.get("file_name")
49
 
50
+ if not task_id or question is None:
51
  continue
52
 
53
  try:
54
+ user_message = question
55
+ if file_name:
56
+ user_message += f"\n\nFile to use: {file_name}"
57
+
58
+ answer = agent(user_message)
59
  cached_answers.append({"task_id": task_id, "submitted_answer": answer})
60
  results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": answer})
61
  except Exception as e:
62
  results_log.append({"Task ID": task_id, "Question": question, "Submitted Answer": f"AGENT ERROR: {e}"})
63
 
64
+ return "Agent finished. Now click 'Submit Cached Answers'", pd.DataFrame(results_log)
65
 
66
  def submit_cached_answers(profile: gr.OAuthProfile | None):
67
+ global cached_answers
68
  if not profile or not cached_answers:
69
+ return "No cached answers to submit. Run the agent first.", None
70
+
71
+ space_id = os.getenv("SPACE_ID")
72
+ username = profile.username
73
+ agent_code = f"https://huggingface.co/spaces/{space_id}/tree/main"
74
 
75
  payload = {
76
+ "username": username,
77
+ "agent_code": agent_code,
78
  "answers": cached_answers
79
  }
80
 
81
  try:
82
+ response = requests.post(f"{DEFAULT_API_URL}/submit", json=payload, timeout=60)
83
  result = response.json()
84
+ final_status = (
85
+ f"Submission Successful!\nUser: {result.get('username')}\n"
86
+ f"Score: {result.get('score', 'N/A')}% ({result.get('correct_count', '?')}/{result.get('total_attempted', '?')})"
87
+ )
88
+ return final_status, None
89
  except Exception as e:
90
  return f"Submission failed: {e}", None
91
 
92
+ # --- Gradio UI ---
93
  with gr.Blocks() as demo:
94
+ gr.Markdown("# LangGraph ChatAgent Evaluation")
95
+ gr.Markdown("Run the agent on all tasks, then submit for scoring.")
 
 
 
96
  gr.LoginButton()
97
+
98
+ run_button = gr.Button("🧠 Run Agent")
99
+ submit_button = gr.Button("📤 Submit Answers")
100
+
101
+ status_box = gr.Textbox(label="Status", lines=3)
102
+ table = gr.DataFrame(label="Results", wrap=True)
103
 
104
  run_button.click(fn=run_agent_only, outputs=[status_box, table])
105
  submit_button.click(fn=submit_cached_answers, outputs=[status_box, table])
system_prompt.txt CHANGED
@@ -1,6 +1,9 @@
1
- You are a helpful assistant. Think step-by-step to solve the question. Then output only the final answer as your last message. The final answer must be:
2
- - a number (without comma separators or symbols),
3
- - a string (no articles or abbreviations),
4
- - or a comma-separated list of such elements.
5
- Do not include any explanation or prefix like "Answer:", "FINAL ANSWER:", or similar.
6
- Return only the answer.
 
 
 
 
1
+ You are a helpful assistant. Think step-by-step to solve the question using available tools or reasoning. When you arrive at the correct answer, respond with only the answer and nothing else.
2
+
3
+ Your answer must follow these rules:
4
+ - If it's a number, do not include commas, currency symbols, or percentage signs.
5
+ - If it's a string, do not use articles (a, an, the) or abbreviations.
6
+ - If it's a list, format it as a comma-separated list of numbers or strings.
7
+ - Do not prefix your answer with "Answer:", "FINAL ANSWER:", or any other label.
8
+
9
+ Your reply should contain the answer only. No explanation. No formatting. No markdown. Just the final answer.