Nolan Zandi Claude Sonnet 4.6 commited on
Commit
70b0712
·
1 Parent(s): c6c3720

fix: resolve ModuleNotFoundError for tools.tools

Browse files

Root causes:
- tools/__init__.py was missing; created empty file to make tools/ a
proper Python package
- chart_tools.py and stats_tools.py had top-level `from haystack.tools
import Tool` imports, causing the entire module to fail to load if
that import path is unavailable, which surfaced as
ModuleNotFoundError: No module named 'tools.tools'
- Fixed by removing all Haystack imports from chart_tools.py and
stats_tools.py — they now export plain schema dicts only
- tools.py does the `from haystack.tools import Tool` import lazily
inside tools_call(), so any ImportError surfaces clearly at call
time rather than at module load
- Pinned haystack-ai>=2.7.0 in requirements.txt to ensure Tool is
available

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>

requirements.txt CHANGED
@@ -1,4 +1,4 @@
1
- haystack-ai
2
  anthropic-haystack
3
  python-dotenv
4
  gradio
 
1
+ haystack-ai>=2.7.0
2
  anthropic-haystack
3
  python-dotenv
4
  gradio
tools/__init__.py ADDED
File without changes
tools/chart_tools.py CHANGED
@@ -1,16 +1,12 @@
1
- from haystack.tools import Tool
2
-
3
- _noop = lambda **kwargs: None
4
-
5
- chart_tools = [
6
- Tool(
7
- name="scatter_chart_generation_func",
8
- description="""This is a scatter plot generation tool useful to generate scatter plots from queried data from our data source that we are querying.
9
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
10
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
11
  from the scatter_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
12
  to it for context if desired.""",
13
- parameters={
14
  "type": "object",
15
  "properties": {
16
  "data": {
@@ -78,16 +74,15 @@ chart_tools = [
78
  },
79
  "required": ["x_column", "y_column"]
80
  },
81
- function=_noop
82
- ),
83
- Tool(
84
- name="line_chart_generation_func",
85
- description="""This is a line chart generation tool useful to generate line charts from queried data from our data source that we are querying.
86
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
87
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
88
  from the line_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
89
  to it for context if desired.""",
90
- parameters={
91
  "type": "object",
92
  "properties": {
93
  "data": {
@@ -119,16 +114,15 @@ chart_tools = [
119
  },
120
  "required": ["x_column", "y_column", "layout"]
121
  },
122
- function=_noop
123
- ),
124
- Tool(
125
- name="bar_chart_generation_func",
126
- description="""This is a bar chart generation tool useful to generate bar charts from queried data from our data source that we are querying.
127
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
128
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
129
  from the bar_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
130
  to it for context if desired.""",
131
- parameters={
132
  "type": "object",
133
  "properties": {
134
  "data": {
@@ -170,16 +164,15 @@ chart_tools = [
170
  },
171
  "required": ["x_column", "y_column", "layout"]
172
  },
173
- function=_noop
174
- ),
175
- Tool(
176
- name="pie_chart_generation_func",
177
- description="""This is a pie chart generation tool useful to generate pie charts from queried data from our data source that we are querying.
178
  The data values will come from the columns of our query.csv (the 'values' and 'names' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
179
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
180
  from the pie_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
181
  to it for context if desired.""",
182
- parameters={
183
  "type": "object",
184
  "properties": {
185
  "data": {
@@ -207,16 +200,15 @@ chart_tools = [
207
  },
208
  "required": ["values", "names", "layout"]
209
  },
210
- function=_noop
211
- ),
212
- Tool(
213
- name="histogram_generation_func",
214
- description="""This is a histogram generation tool useful to generate histograms from queried data from our data source that we are querying.
215
  The data values will come from the columns of our query.csv file but the layout section of the plotly dictionary objects will be generated by you.
216
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
217
  from the histogram_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
218
  to it for context if desired.""",
219
- parameters={
220
  "type": "object",
221
  "properties": {
222
  "data": {
@@ -261,16 +253,14 @@ chart_tools = [
261
  },
262
  "required": ["x_column"]
263
  },
264
- function=_noop
265
- ),
266
- Tool(
267
- name="table_generation_func",
268
- description="""This is a table generation tool useful to format data as a table from queried data from our data source that we are querying.
269
  Takes no parameters as it uses data queried in our query.csv file to build the table.
270
  Call this function after running our query and generating query.csv.
271
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
272
  from the table_generation_func function in any way and always display the iframe fully to the user in the chat window.""",
273
- parameters={"type": "object", "properties": {}},
274
- function=_noop
275
- ),
276
  ]
 
1
+ chart_tool_schemas = [
2
+ {
3
+ "name": "scatter_chart_generation_func",
4
+ "description": """This is a scatter plot generation tool useful to generate scatter plots from queried data from our data source that we are querying.
 
 
 
 
5
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
6
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
7
  from the scatter_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
8
  to it for context if desired.""",
9
+ "parameters": {
10
  "type": "object",
11
  "properties": {
12
  "data": {
 
74
  },
75
  "required": ["x_column", "y_column"]
76
  },
77
+ },
78
+ {
79
+ "name": "line_chart_generation_func",
80
+ "description": """This is a line chart generation tool useful to generate line charts from queried data from our data source that we are querying.
 
81
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
82
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
83
  from the line_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
84
  to it for context if desired.""",
85
+ "parameters": {
86
  "type": "object",
87
  "properties": {
88
  "data": {
 
114
  },
115
  "required": ["x_column", "y_column", "layout"]
116
  },
117
+ },
118
+ {
119
+ "name": "bar_chart_generation_func",
120
+ "description": """This is a bar chart generation tool useful to generate bar charts from queried data from our data source that we are querying.
 
121
  The data values will come from the columns of our query.csv (the 'x' and 'y' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
122
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
123
  from the bar_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
124
  to it for context if desired.""",
125
+ "parameters": {
126
  "type": "object",
127
  "properties": {
128
  "data": {
 
164
  },
165
  "required": ["x_column", "y_column", "layout"]
166
  },
167
+ },
168
+ {
169
+ "name": "pie_chart_generation_func",
170
+ "description": """This is a pie chart generation tool useful to generate pie charts from queried data from our data source that we are querying.
 
171
  The data values will come from the columns of our query.csv (the 'values' and 'names' values of each graph) file but the layout section of the plotly dictionary objects will be generated by you.
172
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
173
  from the pie_chart_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
174
  to it for context if desired.""",
175
+ "parameters": {
176
  "type": "object",
177
  "properties": {
178
  "data": {
 
200
  },
201
  "required": ["values", "names", "layout"]
202
  },
203
+ },
204
+ {
205
+ "name": "histogram_generation_func",
206
+ "description": """This is a histogram generation tool useful to generate histograms from queried data from our data source that we are querying.
 
207
  The data values will come from the columns of our query.csv file but the layout section of the plotly dictionary objects will be generated by you.
208
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
209
  from the histogram_generation_func function in any way and always display the iframe fully to the user in the chat window. You can add your own text supplementary
210
  to it for context if desired.""",
211
+ "parameters": {
212
  "type": "object",
213
  "properties": {
214
  "data": {
 
253
  },
254
  "required": ["x_column"]
255
  },
256
+ },
257
+ {
258
+ "name": "table_generation_func",
259
+ "description": """This is a table generation tool useful to format data as a table from queried data from our data source that we are querying.
 
260
  Takes no parameters as it uses data queried in our query.csv file to build the table.
261
  Call this function after running our query and generating query.csv.
262
  Returns an iframe string which will be displayed inline in our chat window. Do not edit the iframe string returned
263
  from the table_generation_func function in any way and always display the iframe fully to the user in the chat window.""",
264
+ "parameters": {"type": "object", "properties": {}},
265
+ },
 
266
  ]
tools/stats_tools.py CHANGED
@@ -1,15 +1,11 @@
1
- from haystack.tools import Tool
2
-
3
- _noop = lambda **kwargs: None
4
-
5
- stats_tools = [
6
- Tool(
7
- name="regression_func",
8
- description="""This a tool to calculate regressions on our data source that we are querying.
9
  We can run queries with our 'sql_query_func' function and they will be available to use in this function via the query.csv file that is generated.
10
  Returns a dictionary of values that includes a regression_summary and a regression chart (which is an iframe displaying the
11
  linear regression in chart form and should be shown to the user).""",
12
- parameters={
13
  "type": "object",
14
  "properties": {
15
  "independent_variables": {
@@ -33,6 +29,5 @@ stats_tools = [
33
  },
34
  "required": ["independent_variables", "dependent_variable"]
35
  },
36
- function=_noop
37
- )
38
  ]
 
1
+ stats_tool_schemas = [
2
+ {
3
+ "name": "regression_func",
4
+ "description": """This a tool to calculate regressions on our data source that we are querying.
 
 
 
 
5
  We can run queries with our 'sql_query_func' function and they will be available to use in this function via the query.csv file that is generated.
6
  Returns a dictionary of values that includes a regression_summary and a regression chart (which is an iframe displaying the
7
  linear regression in chart form and should be shown to the user).""",
8
+ "parameters": {
9
  "type": "object",
10
  "properties": {
11
  "independent_variables": {
 
29
  },
30
  "required": ["independent_variables", "dependent_variable"]
31
  },
32
+ }
 
33
  ]
tools/tools.py CHANGED
@@ -1,20 +1,28 @@
1
- from haystack.tools import Tool
2
- from .stats_tools import stats_tools
3
- from .chart_tools import chart_tools
4
-
5
- _noop = lambda **kwargs: None
6
 
7
  def tools_call(session_hash, data_source, titles):
 
 
 
 
 
 
 
 
 
 
 
8
 
9
  titles_string = (titles[:625] + '..') if len(titles) > 625 else titles
10
 
11
- query_tools = {
12
- 'file_upload': Tool(
13
- name="query_func",
14
- description=f"""This is a tool useful to query a SQLite table called 'data_source' with the following Columns: {titles_string}.
15
  There may also be more columns in the table if the number of columns is too large to process.
16
  This function also saves the results of the query to csv file called query.csv.""",
17
- parameters={
18
  "type": "object",
19
  "properties": {
20
  "queries": {
@@ -24,14 +32,13 @@ def tools_call(session_hash, data_source, titles):
24
  },
25
  "required": ["queries"]
26
  },
27
- function=_noop
28
- ),
29
- 'sql': Tool(
30
- name="query_func",
31
- description=f"""This is a tool useful to query a PostgreSQL database with the following tables, {titles_string}.
32
  There may also be more tables in the database if the number of tables is too large to process.
33
  This function also saves the results of the query to csv file called query.csv.""",
34
- parameters={
35
  "type": "object",
36
  "properties": {
37
  "queries": {
@@ -41,14 +48,13 @@ def tools_call(session_hash, data_source, titles):
41
  },
42
  "required": ["queries"]
43
  },
44
- function=_noop
45
- ),
46
- 'doc_db': Tool(
47
- name="query_func",
48
- description=f"""This is a tool useful to build an aggregation pipeline to query a MongoDB NoSQL document database with the following collections, {titles_string}.
49
  There may also be more collections in the database if the number of collections is too large to process.
50
  This function also saves the results of the query to a csv file called query.csv.""",
51
- parameters={
52
  "type": "object",
53
  "properties": {
54
  "queries": {
@@ -62,15 +68,14 @@ def tools_call(session_hash, data_source, titles):
62
  },
63
  "required": ["queries", "db_collection"]
64
  },
65
- function=_noop
66
- ),
67
  'graphql': [
68
- Tool(
69
- name="query_func",
70
- description=f"""This is a tool useful to build a GraphQL query for a GraphQL API endpoint with the following types, {titles_string}.
71
  There may also be more types in the GraphQL endpoint if the number of types is too large to process.
72
  This function also saves the results of the query to a csv file called query.csv.""",
73
- parameters={
74
  "type": "object",
75
  "properties": {
76
  "queries": {
@@ -80,15 +85,14 @@ def tools_call(session_hash, data_source, titles):
80
  },
81
  "required": ["queries"]
82
  },
83
- function=_noop
84
- ),
85
- Tool(
86
- name="graphql_schema_query",
87
- description=f"""This is a tool useful to query a GraphQL type and receive back information about its schema. This is useful because
88
  the GraphQL introspection query is too large to be ingested all at once and this allows us to query the schema one type at a time to
89
  view it in manageable bites. You may realize after viewing the schema, that the type you selected was not appropriate for the question
90
  you are attempting answer. You may then query additional types to find the appropriate types to use for your GraphQL API query.""",
91
- parameters={
92
  "type": "object",
93
  "properties": {
94
  "graphql_type": {
@@ -98,14 +102,13 @@ def tools_call(session_hash, data_source, titles):
98
  },
99
  "required": ["graphql_type"]
100
  },
101
- function=_noop
102
- ),
103
- Tool(
104
- name="graphql_csv_query",
105
- description=f"""This is a tool useful to SQL query our query.csv file that is generated from our GraphQL query. This is useful in a situation
106
  where the results of the GraphQL query need additional querying to answer the user question. The query.csv file is converted to a Pandas dataframe
107
  and we query that dataframe with SQL on a table called 'query' before converting it back to a csv file.""",
108
- parameters={
109
  "type": "object",
110
  "properties": {
111
  "csv_query": {
@@ -115,13 +118,13 @@ def tools_call(session_hash, data_source, titles):
115
  },
116
  "required": ["csv_query"]
117
  },
118
- function=_noop
119
- ),
120
  ]
121
  }
122
 
123
- source_tools = query_tools[data_source]
124
- tools = source_tools if isinstance(source_tools, list) else [source_tools]
125
- tools = tools + chart_tools + stats_tools
 
126
 
127
- return tools
 
1
+ from .stats_tools import stats_tool_schemas
2
+ from .chart_tools import chart_tool_schemas
 
 
 
3
 
4
  def tools_call(session_hash, data_source, titles):
5
+ from haystack.tools import Tool
6
+
7
+ _noop = lambda **kwargs: None
8
+
9
+ def make_tool(schema):
10
+ return Tool(
11
+ name=schema["name"],
12
+ description=schema["description"],
13
+ parameters=schema["parameters"],
14
+ function=_noop,
15
+ )
16
 
17
  titles_string = (titles[:625] + '..') if len(titles) > 625 else titles
18
 
19
+ query_tool_schemas = {
20
+ 'file_upload': {
21
+ "name": "query_func",
22
+ "description": f"""This is a tool useful to query a SQLite table called 'data_source' with the following Columns: {titles_string}.
23
  There may also be more columns in the table if the number of columns is too large to process.
24
  This function also saves the results of the query to csv file called query.csv.""",
25
+ "parameters": {
26
  "type": "object",
27
  "properties": {
28
  "queries": {
 
32
  },
33
  "required": ["queries"]
34
  },
35
+ },
36
+ 'sql': {
37
+ "name": "query_func",
38
+ "description": f"""This is a tool useful to query a PostgreSQL database with the following tables, {titles_string}.
 
39
  There may also be more tables in the database if the number of tables is too large to process.
40
  This function also saves the results of the query to csv file called query.csv.""",
41
+ "parameters": {
42
  "type": "object",
43
  "properties": {
44
  "queries": {
 
48
  },
49
  "required": ["queries"]
50
  },
51
+ },
52
+ 'doc_db': {
53
+ "name": "query_func",
54
+ "description": f"""This is a tool useful to build an aggregation pipeline to query a MongoDB NoSQL document database with the following collections, {titles_string}.
 
55
  There may also be more collections in the database if the number of collections is too large to process.
56
  This function also saves the results of the query to a csv file called query.csv.""",
57
+ "parameters": {
58
  "type": "object",
59
  "properties": {
60
  "queries": {
 
68
  },
69
  "required": ["queries", "db_collection"]
70
  },
71
+ },
 
72
  'graphql': [
73
+ {
74
+ "name": "query_func",
75
+ "description": f"""This is a tool useful to build a GraphQL query for a GraphQL API endpoint with the following types, {titles_string}.
76
  There may also be more types in the GraphQL endpoint if the number of types is too large to process.
77
  This function also saves the results of the query to a csv file called query.csv.""",
78
+ "parameters": {
79
  "type": "object",
80
  "properties": {
81
  "queries": {
 
85
  },
86
  "required": ["queries"]
87
  },
88
+ },
89
+ {
90
+ "name": "graphql_schema_query",
91
+ "description": f"""This is a tool useful to query a GraphQL type and receive back information about its schema. This is useful because
 
92
  the GraphQL introspection query is too large to be ingested all at once and this allows us to query the schema one type at a time to
93
  view it in manageable bites. You may realize after viewing the schema, that the type you selected was not appropriate for the question
94
  you are attempting answer. You may then query additional types to find the appropriate types to use for your GraphQL API query.""",
95
+ "parameters": {
96
  "type": "object",
97
  "properties": {
98
  "graphql_type": {
 
102
  },
103
  "required": ["graphql_type"]
104
  },
105
+ },
106
+ {
107
+ "name": "graphql_csv_query",
108
+ "description": f"""This is a tool useful to SQL query our query.csv file that is generated from our GraphQL query. This is useful in a situation
 
109
  where the results of the GraphQL query need additional querying to answer the user question. The query.csv file is converted to a Pandas dataframe
110
  and we query that dataframe with SQL on a table called 'query' before converting it back to a csv file.""",
111
+ "parameters": {
112
  "type": "object",
113
  "properties": {
114
  "csv_query": {
 
118
  },
119
  "required": ["csv_query"]
120
  },
121
+ },
 
122
  ]
123
  }
124
 
125
+ source_schemas = query_tool_schemas[data_source]
126
+ source_tools = [make_tool(s) for s in (source_schemas if isinstance(source_schemas, list) else [source_schemas])]
127
+ chart_tools = [make_tool(s) for s in chart_tool_schemas]
128
+ stats_tools = [make_tool(s) for s in stats_tool_schemas]
129
 
130
+ return source_tools + chart_tools + stats_tools