langroid 0.1.85__py3-none-any.whl → 0.1.219__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 (107) hide show
  1. langroid/__init__.py +95 -0
  2. langroid/agent/__init__.py +40 -0
  3. langroid/agent/base.py +222 -91
  4. langroid/agent/batch.py +264 -0
  5. langroid/agent/callbacks/chainlit.py +608 -0
  6. langroid/agent/chat_agent.py +247 -101
  7. langroid/agent/chat_document.py +41 -4
  8. langroid/agent/openai_assistant.py +842 -0
  9. langroid/agent/special/__init__.py +50 -0
  10. langroid/agent/special/doc_chat_agent.py +837 -141
  11. langroid/agent/special/lance_doc_chat_agent.py +258 -0
  12. langroid/agent/special/lance_rag/__init__.py +9 -0
  13. langroid/agent/special/lance_rag/critic_agent.py +136 -0
  14. langroid/agent/special/lance_rag/lance_rag_task.py +80 -0
  15. langroid/agent/special/lance_rag/query_planner_agent.py +180 -0
  16. langroid/agent/special/lance_tools.py +44 -0
  17. langroid/agent/special/neo4j/__init__.py +0 -0
  18. langroid/agent/special/neo4j/csv_kg_chat.py +174 -0
  19. langroid/agent/special/neo4j/neo4j_chat_agent.py +370 -0
  20. langroid/agent/special/neo4j/utils/__init__.py +0 -0
  21. langroid/agent/special/neo4j/utils/system_message.py +46 -0
  22. langroid/agent/special/relevance_extractor_agent.py +127 -0
  23. langroid/agent/special/retriever_agent.py +32 -198
  24. langroid/agent/special/sql/__init__.py +11 -0
  25. langroid/agent/special/sql/sql_chat_agent.py +47 -23
  26. langroid/agent/special/sql/utils/__init__.py +22 -0
  27. langroid/agent/special/sql/utils/description_extractors.py +95 -46
  28. langroid/agent/special/sql/utils/populate_metadata.py +28 -21
  29. langroid/agent/special/table_chat_agent.py +43 -9
  30. langroid/agent/task.py +475 -122
  31. langroid/agent/tool_message.py +75 -13
  32. langroid/agent/tools/__init__.py +13 -0
  33. langroid/agent/tools/duckduckgo_search_tool.py +66 -0
  34. langroid/agent/tools/google_search_tool.py +11 -0
  35. langroid/agent/tools/metaphor_search_tool.py +67 -0
  36. langroid/agent/tools/recipient_tool.py +16 -29
  37. langroid/agent/tools/run_python_code.py +60 -0
  38. langroid/agent/tools/sciphi_search_rag_tool.py +79 -0
  39. langroid/agent/tools/segment_extract_tool.py +36 -0
  40. langroid/cachedb/__init__.py +9 -0
  41. langroid/cachedb/base.py +22 -2
  42. langroid/cachedb/momento_cachedb.py +26 -2
  43. langroid/cachedb/redis_cachedb.py +78 -11
  44. langroid/embedding_models/__init__.py +34 -0
  45. langroid/embedding_models/base.py +21 -2
  46. langroid/embedding_models/models.py +120 -18
  47. langroid/embedding_models/protoc/embeddings.proto +19 -0
  48. langroid/embedding_models/protoc/embeddings_pb2.py +33 -0
  49. langroid/embedding_models/protoc/embeddings_pb2.pyi +50 -0
  50. langroid/embedding_models/protoc/embeddings_pb2_grpc.py +79 -0
  51. langroid/embedding_models/remote_embeds.py +153 -0
  52. langroid/language_models/__init__.py +45 -0
  53. langroid/language_models/azure_openai.py +80 -27
  54. langroid/language_models/base.py +117 -12
  55. langroid/language_models/config.py +5 -0
  56. langroid/language_models/openai_assistants.py +3 -0
  57. langroid/language_models/openai_gpt.py +558 -174
  58. langroid/language_models/prompt_formatter/__init__.py +15 -0
  59. langroid/language_models/prompt_formatter/base.py +4 -6
  60. langroid/language_models/prompt_formatter/hf_formatter.py +135 -0
  61. langroid/language_models/utils.py +18 -21
  62. langroid/mytypes.py +25 -8
  63. langroid/parsing/__init__.py +46 -0
  64. langroid/parsing/document_parser.py +260 -63
  65. langroid/parsing/image_text.py +32 -0
  66. langroid/parsing/parse_json.py +143 -0
  67. langroid/parsing/parser.py +122 -59
  68. langroid/parsing/repo_loader.py +114 -52
  69. langroid/parsing/search.py +68 -63
  70. langroid/parsing/spider.py +3 -2
  71. langroid/parsing/table_loader.py +44 -0
  72. langroid/parsing/url_loader.py +59 -11
  73. langroid/parsing/urls.py +85 -37
  74. langroid/parsing/utils.py +298 -4
  75. langroid/parsing/web_search.py +73 -0
  76. langroid/prompts/__init__.py +11 -0
  77. langroid/prompts/chat-gpt4-system-prompt.md +68 -0
  78. langroid/prompts/prompts_config.py +1 -1
  79. langroid/utils/__init__.py +17 -0
  80. langroid/utils/algorithms/__init__.py +3 -0
  81. langroid/utils/algorithms/graph.py +103 -0
  82. langroid/utils/configuration.py +36 -5
  83. langroid/utils/constants.py +4 -0
  84. langroid/utils/globals.py +2 -2
  85. langroid/utils/logging.py +2 -5
  86. langroid/utils/output/__init__.py +21 -0
  87. langroid/utils/output/printing.py +47 -1
  88. langroid/utils/output/status.py +33 -0
  89. langroid/utils/pandas_utils.py +30 -0
  90. langroid/utils/pydantic_utils.py +616 -2
  91. langroid/utils/system.py +98 -0
  92. langroid/vector_store/__init__.py +40 -0
  93. langroid/vector_store/base.py +203 -6
  94. langroid/vector_store/chromadb.py +59 -32
  95. langroid/vector_store/lancedb.py +463 -0
  96. langroid/vector_store/meilisearch.py +10 -7
  97. langroid/vector_store/momento.py +262 -0
  98. langroid/vector_store/qdrantdb.py +104 -22
  99. {langroid-0.1.85.dist-info → langroid-0.1.219.dist-info}/METADATA +329 -149
  100. langroid-0.1.219.dist-info/RECORD +127 -0
  101. {langroid-0.1.85.dist-info → langroid-0.1.219.dist-info}/WHEEL +1 -1
  102. langroid/agent/special/recipient_validator_agent.py +0 -157
  103. langroid/parsing/json.py +0 -64
  104. langroid/utils/web/selenium_login.py +0 -36
  105. langroid-0.1.85.dist-info/RECORD +0 -94
  106. /langroid/{scripts → agent/callbacks}/__init__.py +0 -0
  107. {langroid-0.1.85.dist-info → langroid-0.1.219.dist-info}/LICENSE +0 -0
@@ -0,0 +1,264 @@
1
+ import asyncio
2
+ import copy
3
+ import inspect
4
+ from typing import Any, Callable, Coroutine, Iterable, List, Optional, TypeVar
5
+
6
+ from dotenv import load_dotenv
7
+
8
+ from langroid.agent.base import Agent
9
+ from langroid.agent.chat_document import ChatDocument
10
+ from langroid.agent.task import Task
11
+ from langroid.parsing.utils import batched
12
+ from langroid.utils.configuration import quiet_mode
13
+ from langroid.utils.logging import setup_colored_logging
14
+ from langroid.utils.output import SuppressLoggerWarnings, status
15
+
16
+ setup_colored_logging()
17
+
18
+ load_dotenv()
19
+
20
+ T = TypeVar("T")
21
+ U = TypeVar("U")
22
+
23
+
24
+ def run_batch_task_gen(
25
+ gen_task: Callable[[int], Task],
26
+ items: list[T],
27
+ input_map: Callable[[T], str | ChatDocument] = lambda x: str(x),
28
+ output_map: Callable[[ChatDocument | None], U] = lambda x: x, # type: ignore
29
+ sequential: bool = True,
30
+ batch_size: Optional[int] = None,
31
+ turns: int = -1,
32
+ message: Optional[str] = None,
33
+ handle_exceptions: bool = False,
34
+ ) -> list[U]:
35
+ """
36
+ Generate and run copies of a task async/concurrently one per item in `items` list.
37
+ For each item, apply `input_map` to get the initial message to process.
38
+ For each result, apply `output_map` to get the final result.
39
+ Args:
40
+ gen_task (Callable[[int], Task]): generates the tasks to run
41
+ items (list[T]): list of items to process
42
+ input_map (Callable[[T], str|ChatDocument]): function to map item to
43
+ initial message to process
44
+ output_map (Callable[[ChatDocument|str], U]): function to map result
45
+ to final result
46
+ sequential (bool): whether to run sequentially
47
+ (e.g. some APIs such as ooba don't support concurrent requests)
48
+ batch_size (Optional[int]): The number of tasks to run at a time,
49
+ if None, unbatched
50
+ turns (int): number of turns to run, -1 for infinite
51
+ message (Optional[str]): optionally overrides the console status messages
52
+ handle_exceptions: bool: Whether to replace exceptions with outputs of None
53
+
54
+ Returns:
55
+ list[Any]: list of final results
56
+ """
57
+ inputs = [input_map(item) for item in items]
58
+
59
+ async def _do_task(input: str | ChatDocument, i: int) -> Optional[ChatDocument]:
60
+ task_i = gen_task(i)
61
+ if task_i.agent.llm is not None:
62
+ task_i.agent.llm.set_stream(False)
63
+ task_i.agent.config.show_stats = False
64
+
65
+ result = await task_i.run_async(input, turns=turns)
66
+ return result
67
+
68
+ async def _do_all(
69
+ inputs: Iterable[str | ChatDocument], start_idx: int = 0
70
+ ) -> list[U]:
71
+ results: list[Optional[ChatDocument]] = []
72
+ if sequential:
73
+ for i, input in enumerate(inputs):
74
+ try:
75
+ result = await _do_task(input, i + start_idx)
76
+ except BaseException as e:
77
+ if handle_exceptions:
78
+ result = None
79
+ else:
80
+ raise e
81
+ results.append(result)
82
+ else:
83
+ results_with_exceptions = await asyncio.gather(
84
+ *(_do_task(input, i + start_idx) for i, input in enumerate(inputs)),
85
+ return_exceptions=handle_exceptions,
86
+ )
87
+
88
+ results = [
89
+ r if not isinstance(r, BaseException) else None
90
+ for r in results_with_exceptions
91
+ ]
92
+
93
+ return list(map(output_map, results))
94
+
95
+ results: List[U] = []
96
+ if batch_size is None:
97
+ msg = message or f"[bold green]Running {len(items)} tasks:"
98
+
99
+ with status(msg), SuppressLoggerWarnings():
100
+ results = asyncio.run(_do_all(inputs))
101
+ else:
102
+ batches = batched(inputs, batch_size)
103
+
104
+ for batch in batches:
105
+ start_idx = len(results)
106
+ complete_str = f", {start_idx} complete" if start_idx > 0 else ""
107
+ msg = message or f"[bold green]Running {len(items)} tasks{complete_str}:"
108
+
109
+ with status(msg), SuppressLoggerWarnings():
110
+ results.extend(asyncio.run(_do_all(batch, start_idx=start_idx)))
111
+
112
+ return results
113
+
114
+
115
+ def run_batch_tasks(
116
+ task: Task,
117
+ items: list[T],
118
+ input_map: Callable[[T], str | ChatDocument] = lambda x: str(x),
119
+ output_map: Callable[[ChatDocument | None], U] = lambda x: x, # type: ignore
120
+ sequential: bool = True,
121
+ batch_size: Optional[int] = None,
122
+ turns: int = -1,
123
+ ) -> List[U]:
124
+ """
125
+ Run copies of `task` async/concurrently one per item in `items` list.
126
+ For each item, apply `input_map` to get the initial message to process.
127
+ For each result, apply `output_map` to get the final result.
128
+ Args:
129
+ task (Task): task to run
130
+ items (list[T]): list of items to process
131
+ input_map (Callable[[T], str|ChatDocument]): function to map item to
132
+ initial message to process
133
+ output_map (Callable[[ChatDocument|str], U]): function to map result
134
+ to final result
135
+ sequential (bool): whether to run sequentially
136
+ (e.g. some APIs such as ooba don't support concurrent requests)
137
+ batch_size (Optional[int]): The number of tasks to run at a time,
138
+ if None, unbatched
139
+ turns (int): number of turns to run, -1 for infinite
140
+
141
+ Returns:
142
+ list[Any]: list of final results
143
+ """
144
+ message = f"[bold green]Running {len(items)} copies of {task.name}..."
145
+ return run_batch_task_gen(
146
+ lambda i: task.clone(i),
147
+ items,
148
+ input_map,
149
+ output_map,
150
+ sequential,
151
+ batch_size,
152
+ turns,
153
+ message,
154
+ )
155
+
156
+
157
+ def run_batch_agent_method(
158
+ agent: Agent,
159
+ method: Callable[
160
+ [str | ChatDocument | None], Coroutine[Any, Any, ChatDocument | None]
161
+ ],
162
+ items: List[Any],
163
+ input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
164
+ output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
165
+ sequential: bool = True,
166
+ ) -> List[Any]:
167
+ """
168
+ Run the `method` on copies of `agent`, async/concurrently one per
169
+ item in `items` list.
170
+ ASSUMPTION: The `method` is an async method and has signature:
171
+ method(self, input: str|ChatDocument|None) -> ChatDocument|None
172
+ So this would typically be used for the agent's "responder" methods,
173
+ e.g. `llm_response_async` or `agent_responder_async`.
174
+
175
+ For each item, apply `input_map` to get the initial message to process.
176
+ For each result, apply `output_map` to get the final result.
177
+
178
+ Args:
179
+ agent (Agent): agent whose method to run
180
+ method (str): Async method to run on copies of `agent`.
181
+ The method is assumed to have signature:
182
+ `method(self, input: str|ChatDocument|None) -> ChatDocument|None`
183
+ input_map (Callable[[Any], str|ChatDocument]): function to map item to
184
+ initial message to process
185
+ output_map (Callable[[ChatDocument|str], Any]): function to map result
186
+ to final result
187
+ sequential (bool): whether to run sequentially
188
+ (e.g. some APIs such as ooba don't support concurrent requests)
189
+ Returns:
190
+ List[Any]: list of final results
191
+ """
192
+ # Check if the method is async
193
+ method_name = method.__name__
194
+ if not inspect.iscoroutinefunction(method):
195
+ raise ValueError(f"The method {method_name} is not async.")
196
+
197
+ inputs = [input_map(item) for item in items]
198
+ agent_cfg = copy.deepcopy(agent.config)
199
+ assert agent_cfg.llm is not None, "agent must have llm config"
200
+ agent_cfg.llm.stream = False
201
+ agent_cfg.show_stats = False
202
+ agent_cls = type(agent)
203
+ agent_name = agent_cfg.name
204
+
205
+ async def _do_task(input: str | ChatDocument, i: int) -> Any:
206
+ agent_cfg.name = f"{agent_cfg.name}-{i}"
207
+ agent_i = agent_cls(agent_cfg)
208
+ method_i = getattr(agent_i, method_name, None)
209
+ if method_i is None:
210
+ raise ValueError(f"Agent {agent_name} has no method {method_name}")
211
+ result = await method_i(input)
212
+ return output_map(result)
213
+
214
+ async def _do_all() -> List[Any]:
215
+ if sequential:
216
+ results = []
217
+ for i, input in enumerate(inputs):
218
+ result = await _do_task(input, i)
219
+ results.append(result)
220
+ return results
221
+ with quiet_mode(), SuppressLoggerWarnings():
222
+ return await asyncio.gather(
223
+ *(_do_task(input, i) for i, input in enumerate(inputs))
224
+ )
225
+
226
+ n = len(items)
227
+ with status(f"[bold green]Running {n} copies of {agent_name}..."):
228
+ results = asyncio.run(_do_all())
229
+
230
+ return results
231
+
232
+
233
+ def llm_response_batch(
234
+ agent: Agent,
235
+ items: List[Any],
236
+ input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
237
+ output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
238
+ sequential: bool = True,
239
+ ) -> List[Any]:
240
+ return run_batch_agent_method(
241
+ agent,
242
+ agent.llm_response_async,
243
+ items,
244
+ input_map=input_map,
245
+ output_map=output_map,
246
+ sequential=sequential,
247
+ )
248
+
249
+
250
+ def agent_response_batch(
251
+ agent: Agent,
252
+ items: List[Any],
253
+ input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
254
+ output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
255
+ sequential: bool = True,
256
+ ) -> List[Any]:
257
+ return run_batch_agent_method(
258
+ agent,
259
+ agent.agent_response_async,
260
+ items,
261
+ input_map=input_map,
262
+ output_map=output_map,
263
+ sequential=sequential,
264
+ )