langroid 0.1.139__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 (97) hide show
  1. langroid/__init__.py +70 -0
  2. langroid/agent/__init__.py +22 -0
  3. langroid/agent/base.py +120 -33
  4. langroid/agent/batch.py +134 -35
  5. langroid/agent/callbacks/__init__.py +0 -0
  6. langroid/agent/callbacks/chainlit.py +608 -0
  7. langroid/agent/chat_agent.py +164 -100
  8. langroid/agent/chat_document.py +19 -2
  9. langroid/agent/openai_assistant.py +20 -10
  10. langroid/agent/special/__init__.py +33 -10
  11. langroid/agent/special/doc_chat_agent.py +521 -108
  12. langroid/agent/special/lance_doc_chat_agent.py +258 -0
  13. langroid/agent/special/lance_rag/__init__.py +9 -0
  14. langroid/agent/special/lance_rag/critic_agent.py +136 -0
  15. langroid/agent/special/lance_rag/lance_rag_task.py +80 -0
  16. langroid/agent/special/lance_rag/query_planner_agent.py +180 -0
  17. langroid/agent/special/lance_tools.py +44 -0
  18. langroid/agent/special/neo4j/__init__.py +0 -0
  19. langroid/agent/special/neo4j/csv_kg_chat.py +174 -0
  20. langroid/agent/special/neo4j/neo4j_chat_agent.py +370 -0
  21. langroid/agent/special/neo4j/utils/__init__.py +0 -0
  22. langroid/agent/special/neo4j/utils/system_message.py +46 -0
  23. langroid/agent/special/relevance_extractor_agent.py +23 -7
  24. langroid/agent/special/retriever_agent.py +29 -174
  25. langroid/agent/special/sql/__init__.py +7 -0
  26. langroid/agent/special/sql/sql_chat_agent.py +47 -23
  27. langroid/agent/special/sql/utils/__init__.py +11 -0
  28. langroid/agent/special/sql/utils/description_extractors.py +95 -46
  29. langroid/agent/special/sql/utils/populate_metadata.py +28 -21
  30. langroid/agent/special/table_chat_agent.py +43 -9
  31. langroid/agent/task.py +423 -114
  32. langroid/agent/tool_message.py +67 -10
  33. langroid/agent/tools/__init__.py +8 -0
  34. langroid/agent/tools/duckduckgo_search_tool.py +66 -0
  35. langroid/agent/tools/google_search_tool.py +11 -0
  36. langroid/agent/tools/metaphor_search_tool.py +67 -0
  37. langroid/agent/tools/recipient_tool.py +6 -24
  38. langroid/agent/tools/sciphi_search_rag_tool.py +79 -0
  39. langroid/cachedb/__init__.py +6 -0
  40. langroid/embedding_models/__init__.py +24 -0
  41. langroid/embedding_models/base.py +9 -1
  42. langroid/embedding_models/models.py +117 -17
  43. langroid/embedding_models/protoc/embeddings.proto +19 -0
  44. langroid/embedding_models/protoc/embeddings_pb2.py +33 -0
  45. langroid/embedding_models/protoc/embeddings_pb2.pyi +50 -0
  46. langroid/embedding_models/protoc/embeddings_pb2_grpc.py +79 -0
  47. langroid/embedding_models/remote_embeds.py +153 -0
  48. langroid/language_models/__init__.py +22 -0
  49. langroid/language_models/azure_openai.py +47 -4
  50. langroid/language_models/base.py +26 -10
  51. langroid/language_models/config.py +5 -0
  52. langroid/language_models/openai_gpt.py +407 -121
  53. langroid/language_models/prompt_formatter/__init__.py +9 -0
  54. langroid/language_models/prompt_formatter/base.py +4 -6
  55. langroid/language_models/prompt_formatter/hf_formatter.py +135 -0
  56. langroid/language_models/utils.py +10 -9
  57. langroid/mytypes.py +10 -4
  58. langroid/parsing/__init__.py +33 -1
  59. langroid/parsing/document_parser.py +259 -63
  60. langroid/parsing/image_text.py +32 -0
  61. langroid/parsing/parse_json.py +143 -0
  62. langroid/parsing/parser.py +20 -7
  63. langroid/parsing/repo_loader.py +108 -46
  64. langroid/parsing/search.py +8 -0
  65. langroid/parsing/table_loader.py +44 -0
  66. langroid/parsing/url_loader.py +59 -13
  67. langroid/parsing/urls.py +18 -9
  68. langroid/parsing/utils.py +130 -9
  69. langroid/parsing/web_search.py +73 -0
  70. langroid/prompts/__init__.py +7 -0
  71. langroid/prompts/chat-gpt4-system-prompt.md +68 -0
  72. langroid/prompts/prompts_config.py +1 -1
  73. langroid/utils/__init__.py +10 -0
  74. langroid/utils/algorithms/__init__.py +3 -0
  75. langroid/utils/configuration.py +0 -1
  76. langroid/utils/constants.py +4 -0
  77. langroid/utils/logging.py +2 -5
  78. langroid/utils/output/__init__.py +15 -2
  79. langroid/utils/output/status.py +33 -0
  80. langroid/utils/pandas_utils.py +30 -0
  81. langroid/utils/pydantic_utils.py +446 -4
  82. langroid/utils/system.py +36 -1
  83. langroid/vector_store/__init__.py +34 -2
  84. langroid/vector_store/base.py +33 -2
  85. langroid/vector_store/chromadb.py +42 -13
  86. langroid/vector_store/lancedb.py +226 -60
  87. langroid/vector_store/meilisearch.py +7 -6
  88. langroid/vector_store/momento.py +3 -2
  89. langroid/vector_store/qdrantdb.py +82 -11
  90. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/METADATA +190 -129
  91. langroid-0.1.219.dist-info/RECORD +127 -0
  92. langroid/agent/special/recipient_validator_agent.py +0 -157
  93. langroid/parsing/json.py +0 -64
  94. langroid/utils/web/selenium_login.py +0 -36
  95. langroid-0.1.139.dist-info/RECORD +0 -103
  96. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/LICENSE +0 -0
  97. {langroid-0.1.139.dist-info → langroid-0.1.219.dist-info}/WHEEL +0 -0
langroid/agent/batch.py CHANGED
@@ -1,73 +1,159 @@
1
1
  import asyncio
2
2
  import copy
3
3
  import inspect
4
- from typing import Any, Callable, Coroutine, List
4
+ from typing import Any, Callable, Coroutine, Iterable, List, Optional, TypeVar
5
5
 
6
6
  from dotenv import load_dotenv
7
- from rich.console import Console
8
7
 
9
8
  from langroid.agent.base import Agent
10
9
  from langroid.agent.chat_document import ChatDocument
11
10
  from langroid.agent.task import Task
12
- from langroid.utils.configuration import quiet_mode, settings
11
+ from langroid.parsing.utils import batched
12
+ from langroid.utils.configuration import quiet_mode
13
13
  from langroid.utils.logging import setup_colored_logging
14
- from langroid.utils.output.printing import SuppressLoggerWarnings
15
-
16
- console = Console(quiet=settings.quiet)
14
+ from langroid.utils.output import SuppressLoggerWarnings, status
17
15
 
18
16
  setup_colored_logging()
19
17
 
20
18
  load_dotenv()
21
19
 
20
+ T = TypeVar("T")
21
+ U = TypeVar("U")
22
22
 
23
- def run_batch_tasks(
24
- task: Task,
25
- items: List[Any],
26
- input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
27
- output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
28
- ) -> List[Any]:
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]:
29
35
  """
30
- Run copies of `task` async/concurrently one per item in `items` list.
36
+ Generate and run copies of a task async/concurrently one per item in `items` list.
31
37
  For each item, apply `input_map` to get the initial message to process.
32
38
  For each result, apply `output_map` to get the final result.
33
39
  Args:
34
- task (Task): task to run
35
- items (List[Any]): list of items to process
36
- input_map (Callable[[Any], str|ChatDocument]): function to map item to
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
37
43
  initial message to process
38
- output_map (Callable[[ChatDocument|str], Any]): function to map result
44
+ output_map (Callable[[ChatDocument|str], U]): function to map result
39
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
40
53
 
41
54
  Returns:
42
- List[Any]: list of final results
55
+ list[Any]: list of final results
43
56
  """
44
-
45
57
  inputs = [input_map(item) for item in items]
46
58
 
47
- async def _do_task(input: str | ChatDocument, i: int) -> Any:
48
- task_i = task.clone(i)
49
- if task_i.agent.config.llm is not None:
50
- task_i.agent.config.llm.stream = False
51
- task_i.agent.config.show_stats = False
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
52
64
 
53
- result = await task_i.run_async(input)
54
- return output_map(result)
65
+ result = await task_i.run_async(input, turns=turns)
66
+ return result
55
67
 
56
- async def _do_all() -> List[Any]:
57
- with quiet_mode(not settings.debug), SuppressLoggerWarnings():
58
- return await asyncio.gather(
59
- *(_do_task(input, i) for i, input in enumerate(inputs))
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,
60
86
  )
61
87
 
62
- # show rich console spinner
88
+ results = [
89
+ r if not isinstance(r, BaseException) else None
90
+ for r in results_with_exceptions
91
+ ]
63
92
 
64
- n = len(items)
65
- with console.status(f"[bold green]Running {n} copies of {task.name}..."):
66
- results = asyncio.run(_do_all())
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)))
67
111
 
68
112
  return results
69
113
 
70
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
+
71
157
  def run_batch_agent_method(
72
158
  agent: Agent,
73
159
  method: Callable[
@@ -76,6 +162,7 @@ def run_batch_agent_method(
76
162
  items: List[Any],
77
163
  input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
78
164
  output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
165
+ sequential: bool = True,
79
166
  ) -> List[Any]:
80
167
  """
81
168
  Run the `method` on copies of `agent`, async/concurrently one per
@@ -97,6 +184,8 @@ def run_batch_agent_method(
97
184
  initial message to process
98
185
  output_map (Callable[[ChatDocument|str], Any]): function to map result
99
186
  to final result
187
+ sequential (bool): whether to run sequentially
188
+ (e.g. some APIs such as ooba don't support concurrent requests)
100
189
  Returns:
101
190
  List[Any]: list of final results
102
191
  """
@@ -123,13 +212,19 @@ def run_batch_agent_method(
123
212
  return output_map(result)
124
213
 
125
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
126
221
  with quiet_mode(), SuppressLoggerWarnings():
127
222
  return await asyncio.gather(
128
223
  *(_do_task(input, i) for i, input in enumerate(inputs))
129
224
  )
130
225
 
131
226
  n = len(items)
132
- with console.status(f"[bold green]Running {n} copies of {agent_name}..."):
227
+ with status(f"[bold green]Running {n} copies of {agent_name}..."):
133
228
  results = asyncio.run(_do_all())
134
229
 
135
230
  return results
@@ -140,6 +235,7 @@ def llm_response_batch(
140
235
  items: List[Any],
141
236
  input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
142
237
  output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
238
+ sequential: bool = True,
143
239
  ) -> List[Any]:
144
240
  return run_batch_agent_method(
145
241
  agent,
@@ -147,6 +243,7 @@ def llm_response_batch(
147
243
  items,
148
244
  input_map=input_map,
149
245
  output_map=output_map,
246
+ sequential=sequential,
150
247
  )
151
248
 
152
249
 
@@ -155,6 +252,7 @@ def agent_response_batch(
155
252
  items: List[Any],
156
253
  input_map: Callable[[Any], str | ChatDocument] = lambda x: str(x),
157
254
  output_map: Callable[[ChatDocument | None], Any] = lambda x: x,
255
+ sequential: bool = True,
158
256
  ) -> List[Any]:
159
257
  return run_batch_agent_method(
160
258
  agent,
@@ -162,4 +260,5 @@ def agent_response_batch(
162
260
  items,
163
261
  input_map=input_map,
164
262
  output_map=output_map,
263
+ sequential=sequential,
165
264
  )
File without changes