Liss, Alex (NYC-HUG) commited on
Commit
329dfec
·
1 Parent(s): a553f0d

improving tool use and graph query logic

Browse files
Files changed (3) hide show
  1. agent.py +15 -9
  2. prompts.py +26 -1
  3. tools/cypher.py +50 -10
agent.py CHANGED
@@ -50,7 +50,7 @@ agent_llm = ChatOpenAI(
50
  openai_api_key=OPENAI_API_KEY,
51
  model=OPENAI_MODEL,
52
  temperature=0.1,
53
- streaming=False # Disable streaming for agent
54
  )
55
 
56
  movie_chat = chat_prompt | llm | StrOutputParser()
@@ -66,19 +66,25 @@ def football_chat_wrapper(input_text):
66
  # Define the tools
67
  tools = [
68
  Tool.from_function(
69
- name="General Football Chat",
70
- description="For general football chat not covered by other tools",
71
- func=football_chat_wrapper,
72
- ),
 
 
73
  Tool.from_function(
74
  name="Game Summary Search",
75
- description="ONLY use this when specifically searching for details about a particular game or match result",
 
 
76
  func=get_game_summary,
77
  ),
78
  Tool.from_function(
79
- name="49ers Graph Search",
80
- description="Use this for ANY questions about 49ers players, games, schedules team info, fans, or relationships - this should be your DEFAULT tool for 49ers-related queries",
81
- func=cypher_qa_wrapper
 
 
82
  )
83
  ]
84
 
 
50
  openai_api_key=OPENAI_API_KEY,
51
  model=OPENAI_MODEL,
52
  temperature=0.1,
53
+ streaming=True # Disable streaming for agent
54
  )
55
 
56
  movie_chat = chat_prompt | llm | StrOutputParser()
 
66
  # Define the tools
67
  tools = [
68
  Tool.from_function(
69
+ name="49ers Graph Search",
70
+ description="""Use for ANY specific 49ers-related queries about players, games, schedules, fans, or team info.
71
+ Examples: "Who are the 49ers playing next week?", "Which players are defensive linemen?", "How many fan chapters are in California?"
72
+ This is your PRIMARY tool for 49ers-specific information and should be your DEFAULT choice for most queries.""",
73
+ func=cypher_qa_wrapper
74
+ ),
75
  Tool.from_function(
76
  name="Game Summary Search",
77
+ description="""ONLY use for detailed game summaries or specific match results.
78
+ Examples: "What happened in the 49ers vs Seahawks game?", "Give me details about the last playoff game"
79
+ Do NOT use for general schedule or player questions.""",
80
  func=get_game_summary,
81
  ),
82
  Tool.from_function(
83
+ name="General Football Chat",
84
+ description="""ONLY use for general football discussion NOT specific to 49ers data.
85
+ Examples: "How does the NFL draft work?", "What are the basic rules of football?"
86
+ Do NOT use for any 49ers-specific questions.""",
87
+ func=football_chat_wrapper,
88
  )
89
  ]
90
 
prompts.py CHANGED
@@ -6,6 +6,13 @@ Do not answer any questions that do not relate to the 49ers, players, or fans.
6
 
7
  Do not answer any questions using your pre-trained knowledge, only use the information provided in the context.
8
 
 
 
 
 
 
 
 
9
  TOOLS:
10
  ------
11
 
@@ -29,6 +36,24 @@ Thought: Do I need to use a tool? No
29
  Final Answer: [your response here]
30
  ```
31
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
32
  Begin!
33
 
34
  Previous conversation history:
@@ -156,4 +181,4 @@ MATCH (f:Fan)
156
  WHERE NOT (f)-[:MEMBER_OF]->(:Community)
157
  RETURN f.first_name AS firstName, f.last_name AS lastName, f.email AS email
158
  ```
159
- """
 
6
 
7
  Do not answer any questions using your pre-trained knowledge, only use the information provided in the context.
8
 
9
+ IMPORTANT TOOL SELECTION GUIDELINES:
10
+ 1. For ANY 49ers-specific questions about players, games, schedules, fans, or team info, ALWAYS use the "49ers Graph Search" tool first
11
+ 2. ONLY use "Game Summary Search" for detailed game summaries or specific match results
12
+ 3. ONLY use "General Football Chat" for non-49ers football questions
13
+
14
+ When in doubt, default to using "49ers Graph Search" for any 49ers-related questions.
15
+
16
  TOOLS:
17
  ------
18
 
 
36
  Final Answer: [your response here]
37
  ```
38
 
39
+ Example 1:
40
+ User: "Who is the quarterback for the 49ers?"
41
+ Thought: This is asking about a specific 49ers player position, so I should use the 49ers Graph Search tool.
42
+ Action: 49ers Graph Search
43
+ Action Input: Who is the quarterback for the 49ers?
44
+
45
+ Example 2:
46
+ User: "Tell me about the last game against the Seahawks"
47
+ Thought: This is asking for details about a specific game, so I should use the Game Summary Search tool.
48
+ Action: Game Summary Search
49
+ Action Input: Tell me about the last game against the Seahawks
50
+
51
+ Example 3:
52
+ User: "How does the NFL draft work?"
53
+ Thought: This is asking about general NFL rules, not specific to the 49ers, so I should use the General Football Chat tool.
54
+ Action: General Football Chat
55
+ Action Input: How does the NFL draft work?
56
+
57
  Begin!
58
 
59
  Previous conversation history:
 
181
  WHERE NOT (f)-[:MEMBER_OF]->(:Community)
182
  RETURN f.first_name AS firstName, f.last_name AS lastName, f.email AS email
183
  ```
184
+ """
tools/cypher.py CHANGED
@@ -14,6 +14,8 @@ Do not use any other relationship types or properties that are not provided.
14
 
15
  Do not return entire nodes or embedding properties.
16
 
 
 
17
  Example Cypher Statements for 49ers Graph:
18
 
19
  1. Count All Nodes:
@@ -54,14 +56,16 @@ RETURN c.fan_chapter_name AS chapterName, count(f) AS fanCount
54
  ORDER BY fanCount DESC
55
  LIMIT 5
56
 
57
- 8. Find Fans Favoriting a Specific Player & Community:
58
- MATCH (f:Fan)-[:FAVORITE_PLAYER]->(p:Player {{ name: "Nick Bosa" }})
59
- MATCH (f)-[:MEMBER_OF]->(c:Community {{ fan_chapter_name: "Niner Empire Hawaii 808" }})
 
 
60
  RETURN f.first_name AS firstName, f.last_name AS lastName, c.fan_chapter_name AS community
61
 
62
- 9. Upcoming Home Games:
63
  MATCH (g:Game)
64
- WHERE g.home_team = "San Francisco 49ers"
65
  RETURN g.date AS date, g.location AS location, g.away_team AS awayTeam
66
  ORDER BY date
67
 
@@ -72,12 +76,20 @@ RETURN g.date AS date, g.home_team AS home, g.away_team AS away, g.result AS fin
72
  ORDER BY date DESC
73
  LIMIT 5
74
 
75
- 11. Games Played at a Specific Location:
76
- MATCH (g:Game {{ location: "Levi's Stadium" }})
 
77
  RETURN g.date AS date, g.home_team AS homeTeam, g.away_team AS awayTeam, g.result AS finalScore
78
 
79
- 12. Find Fans in a Specific Community:
80
- MATCH (f:Fan)-[:MEMBER_OF]->(c:Community {{ fan_chapter_name: "Bay Area 49ers Fans" }})
 
 
 
 
 
 
 
81
  RETURN f.first_name AS firstName, f.last_name AS lastName
82
  ORDER BY lastName
83
 
@@ -91,6 +103,18 @@ MATCH (f:Fan)
91
  WHERE NOT (f)-[:MEMBER_OF]->(:Community)
92
  RETURN f.first_name AS firstName, f.last_name AS lastName, f.email AS email
93
 
 
 
 
 
 
 
 
 
 
 
 
 
94
  Schema:
95
  {schema}
96
 
@@ -112,7 +136,23 @@ cypher_qa = GraphCypherQAChain.from_llm(
112
  def cypher_qa_wrapper(input_text):
113
  """Wrapper function to handle input format and potential errors"""
114
  try:
115
- return cypher_qa.invoke({"query": input_text})
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
116
  except Exception as e:
117
  print(f"Error in cypher_qa: {str(e)}")
118
  return {"output": "I apologize, but I encountered an error while searching the database. Could you please rephrase your question?"}
 
14
 
15
  Do not return entire nodes or embedding properties.
16
 
17
+ IMPORTANT: Always use case-insensitive comparisons in your Cypher queries by applying toLower() to both the property and the search string, or by using the =~ operator with (?i) for case-insensitive regex matching. This ensures that user queries match regardless of capitalization.
18
+
19
  Example Cypher Statements for 49ers Graph:
20
 
21
  1. Count All Nodes:
 
56
  ORDER BY fanCount DESC
57
  LIMIT 5
58
 
59
+ 8. Find Fans Favoriting a Specific Player & Community (Case-Insensitive):
60
+ MATCH (f:Fan)-[:FAVORITE_PLAYER]->(p:Player)
61
+ WHERE toLower(p.name) = toLower("Nick Bosa")
62
+ MATCH (f)-[:MEMBER_OF]->(c:Community)
63
+ WHERE toLower(c.fan_chapter_name) = toLower("Niner Empire Hawaii 808")
64
  RETURN f.first_name AS firstName, f.last_name AS lastName, c.fan_chapter_name AS community
65
 
66
+ 9. Upcoming Home Games (Case-Insensitive):
67
  MATCH (g:Game)
68
+ WHERE toLower(g.home_team) = toLower("San Francisco 49ers")
69
  RETURN g.date AS date, g.location AS location, g.away_team AS awayTeam
70
  ORDER BY date
71
 
 
76
  ORDER BY date DESC
77
  LIMIT 5
78
 
79
+ 11. Games Played at a Specific Location (Case-Insensitive):
80
+ MATCH (g:Game)
81
+ WHERE toLower(g.location) = toLower("Levi's Stadium")
82
  RETURN g.date AS date, g.home_team AS homeTeam, g.away_team AS awayTeam, g.result AS finalScore
83
 
84
+ 12. Find Fans in a Specific Community (Case-Insensitive):
85
+ MATCH (f:Fan)-[:MEMBER_OF]->(c:Community)
86
+ WHERE toLower(c.fan_chapter_name) = toLower("Bay Area 49ers Fans")
87
+ RETURN f.first_name AS firstName, f.last_name AS lastName
88
+ ORDER BY lastName
89
+
90
+ 12b. Find Fans in a Community (Using Regex, Case-Insensitive):
91
+ MATCH (f:Fan)-[:MEMBER_OF]->(c:Community)
92
+ WHERE c.fan_chapter_name =~ '(?i).*bay area.*'
93
  RETURN f.first_name AS firstName, f.last_name AS lastName
94
  ORDER BY lastName
95
 
 
103
  WHERE NOT (f)-[:MEMBER_OF]->(:Community)
104
  RETURN f.first_name AS firstName, f.last_name AS lastName, f.email AS email
105
 
106
+ 15. Case-Insensitive Player Search:
107
+ MATCH (p:Player)
108
+ WHERE toLower(p.position) = toLower("QB") // Case-insensitive position filter
109
+ RETURN p.name AS playerName, p.position AS position, p.jersey_number AS jerseyNumber
110
+ ORDER BY p.jersey_number
111
+
112
+ 16. Case-Insensitive Team Search:
113
+ MATCH (g:Game)
114
+ WHERE toLower(g.away_team) CONTAINS toLower("seahawks") // Case-insensitive team search
115
+ RETURN g.date AS date, g.home_team AS home, g.away_team AS away, g.result AS finalScore
116
+ ORDER BY date DESC
117
+
118
  Schema:
119
  {schema}
120
 
 
136
  def cypher_qa_wrapper(input_text):
137
  """Wrapper function to handle input format and potential errors"""
138
  try:
139
+ # Log the incoming query for debugging
140
+ print(f"Processing query: {input_text}")
141
+
142
+ # Process the query through the Cypher QA chain
143
+ result = cypher_qa.invoke({"query": input_text})
144
+
145
+ # If we have access to the generated Cypher query, we could modify it here
146
+ # to ensure case-insensitivity, but the GraphCypherQAChain already executes
147
+ # the query. Instead, we rely on the prompt engineering approach to ensure
148
+ # the LLM generates case-insensitive queries.
149
+
150
+ # Log the result for debugging
151
+ if "intermediate_steps" in result:
152
+ generated_cypher = result["intermediate_steps"][0]["query"]
153
+ print(f"Generated Cypher query: {generated_cypher}")
154
+
155
+ return result
156
  except Exception as e:
157
  print(f"Error in cypher_qa: {str(e)}")
158
  return {"output": "I apologize, but I encountered an error while searching the database. Could you please rephrase your question?"}