langroid 0.31.1__py3-none-any.whl → 0.33.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (163) hide show
  1. {langroid-0.31.1.dist-info → langroid-0.33.3.dist-info}/METADATA +150 -124
  2. langroid-0.33.3.dist-info/RECORD +7 -0
  3. {langroid-0.31.1.dist-info → langroid-0.33.3.dist-info}/WHEEL +1 -1
  4. langroid-0.33.3.dist-info/entry_points.txt +4 -0
  5. pyproject.toml +317 -212
  6. langroid/__init__.py +0 -106
  7. langroid/agent/.chainlit/config.toml +0 -121
  8. langroid/agent/.chainlit/translations/bn.json +0 -231
  9. langroid/agent/.chainlit/translations/en-US.json +0 -229
  10. langroid/agent/.chainlit/translations/gu.json +0 -231
  11. langroid/agent/.chainlit/translations/he-IL.json +0 -231
  12. langroid/agent/.chainlit/translations/hi.json +0 -231
  13. langroid/agent/.chainlit/translations/kn.json +0 -231
  14. langroid/agent/.chainlit/translations/ml.json +0 -231
  15. langroid/agent/.chainlit/translations/mr.json +0 -231
  16. langroid/agent/.chainlit/translations/ta.json +0 -231
  17. langroid/agent/.chainlit/translations/te.json +0 -231
  18. langroid/agent/.chainlit/translations/zh-CN.json +0 -229
  19. langroid/agent/__init__.py +0 -41
  20. langroid/agent/base.py +0 -1981
  21. langroid/agent/batch.py +0 -398
  22. langroid/agent/callbacks/__init__.py +0 -0
  23. langroid/agent/callbacks/chainlit.py +0 -598
  24. langroid/agent/chat_agent.py +0 -1899
  25. langroid/agent/chat_document.py +0 -454
  26. langroid/agent/helpers.py +0 -0
  27. langroid/agent/junk +0 -13
  28. langroid/agent/openai_assistant.py +0 -882
  29. langroid/agent/special/__init__.py +0 -59
  30. langroid/agent/special/arangodb/__init__.py +0 -0
  31. langroid/agent/special/arangodb/arangodb_agent.py +0 -656
  32. langroid/agent/special/arangodb/system_messages.py +0 -186
  33. langroid/agent/special/arangodb/tools.py +0 -107
  34. langroid/agent/special/arangodb/utils.py +0 -36
  35. langroid/agent/special/doc_chat_agent.py +0 -1466
  36. langroid/agent/special/lance_doc_chat_agent.py +0 -262
  37. langroid/agent/special/lance_rag/__init__.py +0 -9
  38. langroid/agent/special/lance_rag/critic_agent.py +0 -198
  39. langroid/agent/special/lance_rag/lance_rag_task.py +0 -82
  40. langroid/agent/special/lance_rag/query_planner_agent.py +0 -260
  41. langroid/agent/special/lance_tools.py +0 -61
  42. langroid/agent/special/neo4j/__init__.py +0 -0
  43. langroid/agent/special/neo4j/csv_kg_chat.py +0 -174
  44. langroid/agent/special/neo4j/neo4j_chat_agent.py +0 -433
  45. langroid/agent/special/neo4j/system_messages.py +0 -120
  46. langroid/agent/special/neo4j/tools.py +0 -32
  47. langroid/agent/special/relevance_extractor_agent.py +0 -127
  48. langroid/agent/special/retriever_agent.py +0 -56
  49. langroid/agent/special/sql/__init__.py +0 -17
  50. langroid/agent/special/sql/sql_chat_agent.py +0 -654
  51. langroid/agent/special/sql/utils/__init__.py +0 -21
  52. langroid/agent/special/sql/utils/description_extractors.py +0 -190
  53. langroid/agent/special/sql/utils/populate_metadata.py +0 -85
  54. langroid/agent/special/sql/utils/system_message.py +0 -35
  55. langroid/agent/special/sql/utils/tools.py +0 -64
  56. langroid/agent/special/table_chat_agent.py +0 -263
  57. langroid/agent/structured_message.py +0 -9
  58. langroid/agent/task.py +0 -2093
  59. langroid/agent/tool_message.py +0 -393
  60. langroid/agent/tools/__init__.py +0 -38
  61. langroid/agent/tools/duckduckgo_search_tool.py +0 -50
  62. langroid/agent/tools/file_tools.py +0 -234
  63. langroid/agent/tools/google_search_tool.py +0 -39
  64. langroid/agent/tools/metaphor_search_tool.py +0 -67
  65. langroid/agent/tools/orchestration.py +0 -303
  66. langroid/agent/tools/recipient_tool.py +0 -235
  67. langroid/agent/tools/retrieval_tool.py +0 -32
  68. langroid/agent/tools/rewind_tool.py +0 -137
  69. langroid/agent/tools/segment_extract_tool.py +0 -41
  70. langroid/agent/typed_task.py +0 -19
  71. langroid/agent/xml_tool_message.py +0 -382
  72. langroid/agent_config.py +0 -0
  73. langroid/cachedb/__init__.py +0 -17
  74. langroid/cachedb/base.py +0 -58
  75. langroid/cachedb/momento_cachedb.py +0 -108
  76. langroid/cachedb/redis_cachedb.py +0 -153
  77. langroid/embedding_models/__init__.py +0 -39
  78. langroid/embedding_models/base.py +0 -74
  79. langroid/embedding_models/clustering.py +0 -189
  80. langroid/embedding_models/models.py +0 -461
  81. langroid/embedding_models/protoc/__init__.py +0 -0
  82. langroid/embedding_models/protoc/embeddings.proto +0 -19
  83. langroid/embedding_models/protoc/embeddings_pb2.py +0 -33
  84. langroid/embedding_models/protoc/embeddings_pb2.pyi +0 -50
  85. langroid/embedding_models/protoc/embeddings_pb2_grpc.py +0 -79
  86. langroid/embedding_models/remote_embeds.py +0 -153
  87. langroid/exceptions.py +0 -65
  88. langroid/experimental/team-save.py +0 -391
  89. langroid/language_models/.chainlit/config.toml +0 -121
  90. langroid/language_models/.chainlit/translations/en-US.json +0 -231
  91. langroid/language_models/__init__.py +0 -53
  92. langroid/language_models/azure_openai.py +0 -153
  93. langroid/language_models/base.py +0 -678
  94. langroid/language_models/config.py +0 -18
  95. langroid/language_models/mock_lm.py +0 -124
  96. langroid/language_models/openai_gpt.py +0 -1923
  97. langroid/language_models/prompt_formatter/__init__.py +0 -16
  98. langroid/language_models/prompt_formatter/base.py +0 -40
  99. langroid/language_models/prompt_formatter/hf_formatter.py +0 -132
  100. langroid/language_models/prompt_formatter/llama2_formatter.py +0 -75
  101. langroid/language_models/utils.py +0 -147
  102. langroid/mytypes.py +0 -84
  103. langroid/parsing/__init__.py +0 -52
  104. langroid/parsing/agent_chats.py +0 -38
  105. langroid/parsing/code-parsing.md +0 -86
  106. langroid/parsing/code_parser.py +0 -121
  107. langroid/parsing/config.py +0 -0
  108. langroid/parsing/document_parser.py +0 -718
  109. langroid/parsing/image_text.py +0 -32
  110. langroid/parsing/para_sentence_split.py +0 -62
  111. langroid/parsing/parse_json.py +0 -155
  112. langroid/parsing/parser.py +0 -313
  113. langroid/parsing/repo_loader.py +0 -790
  114. langroid/parsing/routing.py +0 -36
  115. langroid/parsing/search.py +0 -275
  116. langroid/parsing/spider.py +0 -102
  117. langroid/parsing/table_loader.py +0 -94
  118. langroid/parsing/url_loader.py +0 -111
  119. langroid/parsing/url_loader_cookies.py +0 -73
  120. langroid/parsing/urls.py +0 -273
  121. langroid/parsing/utils.py +0 -373
  122. langroid/parsing/web_search.py +0 -155
  123. langroid/prompts/__init__.py +0 -9
  124. langroid/prompts/chat-gpt4-system-prompt.md +0 -68
  125. langroid/prompts/dialog.py +0 -17
  126. langroid/prompts/prompts_config.py +0 -5
  127. langroid/prompts/templates.py +0 -141
  128. langroid/pydantic_v1/__init__.py +0 -10
  129. langroid/pydantic_v1/main.py +0 -4
  130. langroid/utils/.chainlit/config.toml +0 -121
  131. langroid/utils/.chainlit/translations/en-US.json +0 -231
  132. langroid/utils/__init__.py +0 -19
  133. langroid/utils/algorithms/__init__.py +0 -3
  134. langroid/utils/algorithms/graph.py +0 -103
  135. langroid/utils/configuration.py +0 -98
  136. langroid/utils/constants.py +0 -30
  137. langroid/utils/docker.py +0 -37
  138. langroid/utils/git_utils.py +0 -252
  139. langroid/utils/globals.py +0 -49
  140. langroid/utils/llms/__init__.py +0 -0
  141. langroid/utils/llms/strings.py +0 -8
  142. langroid/utils/logging.py +0 -135
  143. langroid/utils/object_registry.py +0 -66
  144. langroid/utils/output/__init__.py +0 -20
  145. langroid/utils/output/citations.py +0 -41
  146. langroid/utils/output/printing.py +0 -99
  147. langroid/utils/output/status.py +0 -40
  148. langroid/utils/pandas_utils.py +0 -30
  149. langroid/utils/pydantic_utils.py +0 -602
  150. langroid/utils/system.py +0 -286
  151. langroid/utils/types.py +0 -93
  152. langroid/utils/web/__init__.py +0 -0
  153. langroid/utils/web/login.py +0 -83
  154. langroid/vector_store/__init__.py +0 -50
  155. langroid/vector_store/base.py +0 -357
  156. langroid/vector_store/chromadb.py +0 -214
  157. langroid/vector_store/lancedb.py +0 -401
  158. langroid/vector_store/meilisearch.py +0 -299
  159. langroid/vector_store/momento.py +0 -278
  160. langroid/vector_store/qdrant_cloud.py +0 -6
  161. langroid/vector_store/qdrantdb.py +0 -468
  162. langroid-0.31.1.dist-info/RECORD +0 -162
  163. {langroid-0.31.1.dist-info → langroid-0.33.3.dist-info/licenses}/LICENSE +0 -0
@@ -1,433 +0,0 @@
1
- import logging
2
- from typing import TYPE_CHECKING, Any, Dict, List, Optional, Union
3
-
4
- from rich import print
5
- from rich.console import Console
6
-
7
- from langroid.pydantic_v1 import BaseModel, BaseSettings
8
-
9
- if TYPE_CHECKING:
10
- import neo4j
11
-
12
- from langroid.agent.chat_agent import ChatAgent, ChatAgentConfig
13
- from langroid.agent.chat_document import ChatDocument
14
- from langroid.agent.special.neo4j.system_messages import (
15
- ADDRESSING_INSTRUCTION,
16
- DEFAULT_NEO4J_CHAT_SYSTEM_MESSAGE,
17
- DONE_INSTRUCTION,
18
- SCHEMA_PROVIDED_SYS_MSG,
19
- SCHEMA_TOOLS_SYS_MSG,
20
- )
21
- from langroid.agent.special.neo4j.tools import (
22
- CypherCreationTool,
23
- CypherRetrievalTool,
24
- GraphSchemaTool,
25
- cypher_creation_tool_name,
26
- cypher_retrieval_tool_name,
27
- graph_schema_tool_name,
28
- )
29
- from langroid.agent.tools.orchestration import DoneTool, ForwardTool
30
- from langroid.exceptions import LangroidImportError
31
- from langroid.mytypes import Entity
32
- from langroid.utils.constants import SEND_TO
33
-
34
- logger = logging.getLogger(__name__)
35
-
36
- console = Console()
37
-
38
- NEO4J_ERROR_MSG = "There was an error in your Cypher Query"
39
-
40
-
41
- # TOOLS to be used by the agent
42
-
43
-
44
- class Neo4jSettings(BaseSettings):
45
- uri: str = ""
46
- username: str = ""
47
- password: str = ""
48
- database: str = ""
49
-
50
- class Config:
51
- # This enables the use of environment variables to set the settings,
52
- # e.g. NEO4J_URI, NEO4J_USERNAME, etc.,
53
- # which can either be set in a .env file or in the shell via export cmds.
54
- env_prefix = "NEO4J_"
55
-
56
-
57
- class QueryResult(BaseModel):
58
- success: bool
59
- data: List[Dict[Any, Any]] | str | None = None
60
-
61
-
62
- class Neo4jChatAgentConfig(ChatAgentConfig):
63
- neo4j_settings: Neo4jSettings = Neo4jSettings()
64
- system_message: str = DEFAULT_NEO4J_CHAT_SYSTEM_MESSAGE
65
- kg_schema: Optional[List[Dict[str, Any]]] = None
66
- database_created: bool = False
67
- # whether agent MUST use schema_tools to get schema, i.e.
68
- # schema is NOT initially provided
69
- use_schema_tools: bool = True
70
- use_functions_api: bool = True
71
- use_tools: bool = False
72
- # whether the agent is used in a continuous chat with user,
73
- # as opposed to returning a result from the task.run()
74
- chat_mode: bool = False
75
- addressing_prefix: str = ""
76
-
77
-
78
- class Neo4jChatAgent(ChatAgent):
79
- def __init__(self, config: Neo4jChatAgentConfig):
80
- """Initialize the Neo4jChatAgent.
81
-
82
- Raises:
83
- ValueError: If database information is not provided in the config.
84
- """
85
- self.config: Neo4jChatAgentConfig = config
86
- self._validate_config()
87
- self._import_neo4j()
88
- self._initialize_db()
89
- self._init_tools_sys_message()
90
- self.init_state()
91
-
92
- def init_state(self) -> None:
93
- super().init_state()
94
- self.current_retrieval_cypher_query: str = ""
95
- self.tried_schema: bool = False
96
-
97
- def handle_message_fallback(
98
- self, msg: str | ChatDocument
99
- ) -> str | ForwardTool | None:
100
- """
101
- When LLM sends a no-tool msg, assume user is the intended recipient,
102
- and if in interactive mode, forward the msg to the user.
103
- """
104
-
105
- done_tool_name = DoneTool.default_value("request")
106
- forward_tool_name = ForwardTool.default_value("request")
107
- if isinstance(msg, ChatDocument) and msg.metadata.sender == Entity.LLM:
108
- if self.interactive:
109
- return ForwardTool(agent="User")
110
- else:
111
- if self.config.chat_mode:
112
- return f"""
113
- Since you did not explicitly address the User, it is not clear
114
- whether:
115
- - you intend this to be the final response to the
116
- user's query/request, in which case you must use the
117
- `{forward_tool_name}` to indicate this.
118
- - OR, you FORGOT to use an Appropriate TOOL,
119
- in which case you should use the available tools to
120
- make progress on the user's query/request.
121
- """
122
- return f"""
123
- The intent of your response is not clear:
124
- - if you intended this to be the final answer to the user's query,
125
- then use the `{done_tool_name}` to indicate so,
126
- with the `content` set to the answer or result.
127
- - otherwise, use one of the available tools to make progress
128
- to arrive at the final answer.
129
- """
130
- return None
131
-
132
- def _validate_config(self) -> None:
133
- """Validate the configuration to ensure all necessary fields are present."""
134
- assert isinstance(self.config, Neo4jChatAgentConfig)
135
- if (
136
- self.config.neo4j_settings.username is None
137
- and self.config.neo4j_settings.password is None
138
- and self.config.neo4j_settings.database
139
- ):
140
- raise ValueError("Neo4j env information must be provided")
141
-
142
- def _import_neo4j(self) -> None:
143
- """Dynamically imports the Neo4j module and sets it as a global variable."""
144
- global neo4j
145
- try:
146
- import neo4j
147
- except ImportError:
148
- raise LangroidImportError("neo4j", "neo4j")
149
-
150
- def _initialize_db(self) -> None:
151
- """
152
- Initializes a connection to the Neo4j database using the configuration settings.
153
- """
154
- try:
155
- assert isinstance(self.config, Neo4jChatAgentConfig)
156
- self.driver = neo4j.GraphDatabase.driver(
157
- self.config.neo4j_settings.uri,
158
- auth=(
159
- self.config.neo4j_settings.username,
160
- self.config.neo4j_settings.password,
161
- ),
162
- )
163
- with self.driver.session() as session:
164
- result = session.run("MATCH (n) RETURN count(n) as count")
165
- count = result.single()["count"] # type: ignore
166
- self.config.database_created = count > 0
167
-
168
- # If database has data, get schema
169
- if self.config.database_created:
170
- # this updates self.config.kg_schema
171
- self.graph_schema_tool(None)
172
-
173
- except Exception as e:
174
- raise ConnectionError(f"Failed to initialize Neo4j connection: {e}")
175
-
176
- def close(self) -> None:
177
- """close the connection"""
178
- if self.driver:
179
- self.driver.close()
180
-
181
- def retry_query(self, e: Exception, query: str) -> str:
182
- """
183
- Generate an error message for a failed Cypher query and return it.
184
-
185
- Args:
186
- e (Exception): The exception raised during the Cypher query execution.
187
- query (str): The Cypher query that failed.
188
-
189
- Returns:
190
- str: The error message.
191
- """
192
- logger.error(f"Cypher Query failed: {query}\nException: {e}")
193
-
194
- # Construct the error message
195
- error_message_template = f"""\
196
- {NEO4J_ERROR_MSG}: '{query}'
197
- {str(e)}
198
- Run a new query, correcting the errors.
199
- """
200
-
201
- return error_message_template
202
-
203
- def read_query(
204
- self, query: str, parameters: Optional[Dict[Any, Any]] = None
205
- ) -> QueryResult:
206
- """
207
- Executes a given Cypher query with parameters on the Neo4j database.
208
-
209
- Args:
210
- query (str): The Cypher query string to be executed.
211
- parameters (Optional[Dict[Any, Any]]): A dictionary of parameters for
212
- the query.
213
-
214
- Returns:
215
- QueryResult: An object representing the outcome of the query execution.
216
- """
217
- if not self.driver:
218
- return QueryResult(
219
- success=False, data="No database connection is established."
220
- )
221
-
222
- try:
223
- assert isinstance(self.config, Neo4jChatAgentConfig)
224
- with self.driver.session(
225
- database=self.config.neo4j_settings.database
226
- ) as session:
227
- result = session.run(query, parameters)
228
- if result.peek():
229
- records = [record.data() for record in result]
230
- return QueryResult(success=True, data=records)
231
- else:
232
- return QueryResult(success=True, data=[])
233
- except Exception as e:
234
- logger.error(f"Failed to execute query: {query}\n{e}")
235
- error_message = self.retry_query(e, query)
236
- return QueryResult(success=False, data=error_message)
237
- finally:
238
- self.close()
239
-
240
- def write_query(
241
- self, query: str, parameters: Optional[Dict[Any, Any]] = None
242
- ) -> QueryResult:
243
- """
244
- Executes a write transaction using a given Cypher query on the Neo4j database.
245
- This method should be used for queries that modify the database.
246
-
247
- Args:
248
- query (str): The Cypher query string to be executed.
249
- parameters (dict, optional): A dict of parameters for the Cypher query.
250
-
251
- Returns:
252
- QueryResult: An object representing the outcome of the query execution.
253
- It contains a success flag and an optional error message.
254
- """
255
- # Check if query contains database/collection creation patterns
256
- query_upper = query.upper()
257
- is_creation_query = any(
258
- [
259
- "CREATE" in query_upper,
260
- "MERGE" in query_upper,
261
- "CREATE CONSTRAINT" in query_upper,
262
- "CREATE INDEX" in query_upper,
263
- ]
264
- )
265
-
266
- if is_creation_query:
267
- self.config.database_created = True
268
- logger.info("Detected database/collection creation query")
269
-
270
- if not self.driver:
271
- return QueryResult(
272
- success=False, data="No database connection is established."
273
- )
274
-
275
- try:
276
- assert isinstance(self.config, Neo4jChatAgentConfig)
277
- with self.driver.session(
278
- database=self.config.neo4j_settings.database
279
- ) as session:
280
- session.write_transaction(lambda tx: tx.run(query, parameters))
281
- return QueryResult(success=True)
282
- except Exception as e:
283
- logging.warning(f"An error occurred: {e}")
284
- error_message = self.retry_query(e, query)
285
- return QueryResult(success=False, data=error_message)
286
- finally:
287
- self.close()
288
-
289
- # TODO: test under enterprise edition because community edition doesn't allow
290
- # database creation/deletion
291
- def remove_database(self) -> None:
292
- """Deletes all nodes and relationships from the current Neo4j database."""
293
- delete_query = """
294
- MATCH (n)
295
- DETACH DELETE n
296
- """
297
- response = self.write_query(delete_query)
298
-
299
- if response.success:
300
- print("[green]Database is deleted!")
301
- else:
302
- print("[red]Database is not deleted!")
303
-
304
- def cypher_retrieval_tool(self, msg: CypherRetrievalTool) -> str:
305
- """ "
306
- Handle a CypherRetrievalTool message by executing a Cypher query and
307
- returning the result.
308
- Args:
309
- msg (CypherRetrievalTool): The tool-message to handle.
310
-
311
- Returns:
312
- str: The result of executing the cypher_query.
313
- """
314
- if not self.tried_schema:
315
- return f"""
316
- You did not yet use the `{graph_schema_tool_name}` tool to get the schema
317
- of the neo4j knowledge-graph db. Use that tool first before using
318
- the `{cypher_retrieval_tool_name}` tool, to ensure you know all the correct
319
- node labels, relationship types, and property keys available in
320
- the database.
321
- """
322
- elif not self.config.database_created:
323
- return f"""
324
- You have not yet created the Neo4j database.
325
- Use the `{cypher_creation_tool_name}`
326
- tool to create the database first before using the
327
- `{cypher_retrieval_tool_name}` tool.
328
- """
329
- query = msg.cypher_query
330
- self.current_retrieval_cypher_query = query
331
- logger.info(f"Executing Cypher query: {query}")
332
- response = self.read_query(query)
333
- if isinstance(response.data, list) and len(response.data) == 0:
334
- return """
335
- No results found; check if your query used the right label names --
336
- remember these are case sensitive, so you have to use the exact label
337
- names you found in the schema.
338
- Or retry using one of the RETRY-SUGGESTIONS in your instructions.
339
- """
340
- return str(response.data)
341
-
342
- def cypher_creation_tool(self, msg: CypherCreationTool) -> str:
343
- """ "
344
- Handle a CypherCreationTool message by executing a Cypher query and
345
- returning the result.
346
- Args:
347
- msg (CypherCreationTool): The tool-message to handle.
348
-
349
- Returns:
350
- str: The result of executing the cypher_query.
351
- """
352
- query = msg.cypher_query
353
-
354
- logger.info(f"Executing Cypher query: {query}")
355
- response = self.write_query(query)
356
- if response.success:
357
- self.config.database_created = True
358
- return "Cypher query executed successfully"
359
- else:
360
- return str(response.data)
361
-
362
- # TODO: There are various ways to get the schema. The current one uses the func
363
- # `read_query`, which requires post processing to identify whether the response upon
364
- # the schema query is valid. Another way is to isolate this func from `read_query`.
365
- # The current query works well. But we could use the queries here:
366
- # https://github.com/neo4j/NaLLM/blob/1af09cd117ba0777d81075c597a5081583568f9f/api/
367
- # src/driver/neo4j.py#L30
368
- def graph_schema_tool(
369
- self, msg: GraphSchemaTool | None
370
- ) -> str | Optional[Union[str, List[Dict[Any, Any]]]]:
371
- """
372
- Retrieves the schema of a Neo4j graph database.
373
-
374
- Args:
375
- msg (GraphSchemaTool): An instance of GraphDatabaseSchema, typically
376
- containing information or parameters needed for the database query.
377
-
378
- Returns:
379
- str: The visual representation of the database schema as a string, or a
380
- message stating that the database schema is empty or not valid.
381
-
382
- Raises:
383
- This function does not explicitly raise exceptions but depends on the
384
- behavior of 'self.read_query' method, which might raise exceptions related
385
- to database connectivity or query execution.
386
- """
387
- self.tried_schema = True
388
- if self.config.kg_schema is not None and len(self.config.kg_schema) > 0:
389
- return self.config.kg_schema
390
- schema_result = self.read_query("CALL db.schema.visualization()")
391
- if schema_result.success:
392
- # there is a possibility that the schema is empty, which is a valid response
393
- # the schema.data will be: [{"nodes": [], "relationships": []}]
394
- self.config.kg_schema = schema_result.data # type: ignore
395
- return schema_result.data
396
- else:
397
- return f"Failed to retrieve schema: {schema_result.data}"
398
-
399
- def _init_tools_sys_message(self) -> None:
400
- """Initialize message tools used for chatting."""
401
- self.tried_schema = False
402
- message = self._format_message()
403
- self.config.system_message = self.config.system_message.format(mode=message)
404
- if self.config.chat_mode:
405
- self.config.addressing_prefix = self.config.addressing_prefix or SEND_TO
406
- self.config.system_message += ADDRESSING_INSTRUCTION.format(
407
- prefix=self.config.addressing_prefix
408
- )
409
- else:
410
- self.config.system_message += DONE_INSTRUCTION
411
- super().__init__(self.config)
412
- # Note we are enabling GraphSchemaTool regardless of whether
413
- # self.config.use_schema_tools is True or False, because
414
- # even when schema provided, the agent may later want to get the schema,
415
- # e.g. if the db evolves, or if it needs to bring in the schema
416
- self.enable_message(
417
- [
418
- GraphSchemaTool,
419
- CypherRetrievalTool,
420
- CypherCreationTool,
421
- DoneTool,
422
- ]
423
- )
424
-
425
- def _format_message(self) -> str:
426
- if self.driver is None:
427
- raise ValueError("Database driver None")
428
- assert isinstance(self.config, Neo4jChatAgentConfig)
429
- return (
430
- SCHEMA_TOOLS_SYS_MSG
431
- if self.config.use_schema_tools
432
- else SCHEMA_PROVIDED_SYS_MSG.format(schema=self.graph_schema_tool(None))
433
- )
@@ -1,120 +0,0 @@
1
- from langroid.agent.special.neo4j.tools import (
2
- cypher_creation_tool_name,
3
- cypher_retrieval_tool_name,
4
- graph_schema_tool_name,
5
- )
6
- from langroid.agent.tools.orchestration import DoneTool
7
-
8
- done_tool_name = DoneTool.default_value("request")
9
-
10
- graph_schema_tool_description = f"""
11
- `{graph_schema_tool_name}` tool/function-call to get all the node labels, relationship
12
- types, and property keys available in your Neo4j database. You MUST use
13
- this tool BEFORE attempting to use the `{cypher_retrieval_tool_name}` tool,
14
- to ensure that you are using the correct node labels, relationship types, and
15
- property keys in your `{cypher_retrieval_tool_name}` tool/function-call.
16
- """
17
-
18
- cypher_retrieval_tool_description = f"""
19
- `{cypher_retrieval_tool_name}` tool/function-call to retrieve information from the
20
- graph database to answer questions.
21
- """
22
-
23
- cypher_creation_tool_description = f"""
24
- `{cypher_creation_tool_name}` tool/function-call to execute cypher query that creates
25
- entities/relationships in the graph database.
26
- """
27
-
28
- cypher_query_instructions = """
29
- You must be smart about using the right node labels, relationship types, and property
30
- keys based on the english description. If you are thinking of using a node label,
31
- relationship type, or property key that does not exist, you are probably on the wrong
32
- track, so you should try your best to answer based on an existing table or column.
33
- DO NOT assume any nodes or relationships other than those above.
34
- """
35
-
36
-
37
- # sys msg to use when schema already provided initially,
38
- # so agent does not need to use schema tool, at least initially,
39
- # but may do so later if the db evolves, or if needs to bring in the schema
40
- # to more recent context.
41
- SCHEMA_PROVIDED_SYS_MSG = f"""You are a data scientist and expert in Knowledge Graphs,
42
- with expertise in answering questions by interacting with a Neo4j graph database.
43
-
44
- The schema below describes the Neo4j database structure, node labels,
45
- relationship types, and property keys available in your Neo4j database.
46
-
47
- === SCHEMA ===
48
- {{schema}}
49
- === END SCHEMA ===
50
-
51
- To help with the user's question or database update/creation request,
52
- you have access to these tools:
53
-
54
- - {cypher_retrieval_tool_description}
55
-
56
- - {cypher_creation_tool_description}
57
-
58
- Since the schema has been provided, you may not need to use the tool below,
59
- but you may use it if you need to remind yourself about the schema:
60
-
61
- - {graph_schema_tool_description}
62
-
63
- """
64
-
65
- # sys msg to use when schema is not initially provided,
66
- # and we want agent to use schema tool to get schema
67
- SCHEMA_TOOLS_SYS_MSG = f"""You are a data scientist and expert in Knowledge Graphs,
68
- with expertise in answering questions by querying Neo4j database.
69
- You have access to the following tools:
70
-
71
- - {graph_schema_tool_description}
72
-
73
- - {cypher_retrieval_tool_description}
74
-
75
- - {cypher_creation_tool_description}
76
-
77
- """
78
-
79
- DEFAULT_NEO4J_CHAT_SYSTEM_MESSAGE = f"""
80
- {{mode}}
81
-
82
- You do not need to be able to answer a question with just one query.
83
- You could make a sequence of Cypher queries to find the answer to the question.
84
-
85
- {cypher_query_instructions}
86
-
87
-
88
-
89
- RETRY-SUGGESTIONS:
90
- If you receive a null or other unexpected result,
91
- (a) make sure you use the available TOOLs correctly,
92
- (b) USE `{graph_schema_tool_name}` tool/function-call to get all the node labels,
93
- relationship types, and property keys available in your Neo4j database.
94
- (c) LABELS are CASE-SENSITIVE -- make sure you adhere to the exact label name
95
- you found in the schema.
96
- (d) see if you have made an assumption in your Neo4j query, and try another way,
97
- or use `{cypher_retrieval_tool_name}` to explore the database contents before
98
- submitting your final query.
99
- (e) USE `{cypher_creation_tool_name}` tool/function-call to execute cypher query that
100
- creates entities/relationships in the graph database.
101
- (f) Try APPROXIMATE or PARTIAL MATCHES to strings in the user's query,
102
- e.g. user may ask about "Godfather" instead of "The Godfather",
103
- or try using CASE-INSENSITIVE MATCHES.
104
-
105
- Start by asking what the user needs help with.
106
- """
107
-
108
- ADDRESSING_INSTRUCTION = """
109
- IMPORTANT - Whenever you are NOT writing a CYPHER query, make sure you address the
110
- user using {prefix}User. You MUST use the EXACT syntax {prefix} !!!
111
-
112
- In other words, you ALWAYS EITHER:
113
- - write a CYPHER query using one of the tools,
114
- - OR address the user using {prefix}User.
115
- """
116
-
117
- DONE_INSTRUCTION = f"""
118
- When you finally have the answer to a user's query or request,
119
- use the `{done_tool_name}` with `content` set to the answer or result.
120
- """
@@ -1,32 +0,0 @@
1
- from langroid.agent import ToolMessage
2
-
3
-
4
- class CypherRetrievalTool(ToolMessage):
5
- request: str = "cypher_retrieval_tool"
6
- purpose: str = """To send the <cypher_query> to retrieve
7
- data from the graph database based on provided text description and schema.
8
- """
9
- cypher_query: str
10
-
11
-
12
- cypher_retrieval_tool_name = CypherRetrievalTool.default_value("request")
13
-
14
-
15
- class CypherCreationTool(ToolMessage):
16
- request: str = "cypher_creation_tool"
17
- purpose: str = """
18
- To send the <cypher_query> to create
19
- entities/relationships in the graph database.
20
- """
21
- cypher_query: str
22
-
23
-
24
- cypher_creation_tool_name = CypherCreationTool.default_value("request")
25
-
26
-
27
- class GraphSchemaTool(ToolMessage):
28
- request: str = "graph_schema_tool"
29
- purpose: str = """To get the schema of the graph database."""
30
-
31
-
32
- graph_schema_tool_name = GraphSchemaTool.default_value("request")