langroid 0.1.214__py3-none-any.whl → 0.1.217__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.
@@ -13,6 +13,7 @@ from . import base
13
13
  from . import chat_document
14
14
  from . import chat_agent
15
15
  from . import task
16
+ from . import batch
16
17
  from . import tool_message
17
18
  from . import tools
18
19
  from . import special
@@ -32,6 +33,7 @@ __all__ = [
32
33
  "chat_document",
33
34
  "chat_agent",
34
35
  "task",
36
+ "batch",
35
37
  "tool_message",
36
38
  "tools",
37
39
  "special",
langroid/agent/base.py CHANGED
@@ -42,6 +42,7 @@ from langroid.parsing.parser import Parser, ParsingConfig
42
42
  from langroid.prompts.prompts_config import PromptsConfig
43
43
  from langroid.utils.configuration import settings
44
44
  from langroid.utils.constants import NO_ANSWER
45
+ from langroid.utils.output import status
45
46
  from langroid.vector_store.base import VectorStore, VectorStoreConfig
46
47
 
47
48
  console = Console(quiet=settings.quiet)
@@ -517,7 +518,7 @@ class Agent(ABC):
517
518
  with ExitStack() as stack: # for conditionally using rich spinner
518
519
  if not self.llm.get_stream():
519
520
  # show rich spinner only if not streaming!
520
- cm = console.status("LLM responding to message...")
521
+ cm = status("LLM responding to message...")
521
522
  stack.enter_context(cm)
522
523
  output_len = self.config.llm.max_output_tokens
523
524
  if (
langroid/agent/batch.py CHANGED
@@ -1,84 +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,
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
28
29
  sequential: bool = True,
30
+ batch_size: Optional[int] = None,
29
31
  turns: int = -1,
30
- ) -> List[Any]:
32
+ message: Optional[str] = None,
33
+ handle_exceptions: bool = False,
34
+ ) -> list[U]:
31
35
  """
32
- 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.
33
37
  For each item, apply `input_map` to get the initial message to process.
34
38
  For each result, apply `output_map` to get the final result.
35
39
  Args:
36
- task (Task): task to run
37
- items (List[Any]): list of items to process
38
- 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
39
43
  initial message to process
40
- output_map (Callable[[ChatDocument|str], Any]): function to map result
44
+ output_map (Callable[[ChatDocument|str], U]): function to map result
41
45
  to final result
42
46
  sequential (bool): whether to run sequentially
43
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
44
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
45
53
 
46
54
  Returns:
47
- List[Any]: list of final results
55
+ list[Any]: list of final results
48
56
  """
49
-
50
57
  inputs = [input_map(item) for item in items]
51
58
 
52
- async def _do_task(input: str | ChatDocument, i: int) -> Any:
53
- task_i = task.clone(i)
59
+ async def _do_task(input: str | ChatDocument, i: int) -> Optional[ChatDocument]:
60
+ task_i = gen_task(i)
54
61
  if task_i.agent.llm is not None:
55
62
  task_i.agent.llm.set_stream(False)
56
63
  task_i.agent.config.show_stats = False
57
64
 
58
65
  result = await task_i.run_async(input, turns=turns)
59
- return output_map(result)
66
+ return result
60
67
 
61
- async def _do_all() -> List[Any]:
62
- with quiet_mode(not settings.debug), SuppressLoggerWarnings():
63
- if sequential:
64
- results = []
65
- for i, input in enumerate(inputs):
66
- result = await _do_task(input, i)
67
- results.append(result)
68
- return results
69
- return await asyncio.gather(
70
- *(_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,
71
86
  )
72
87
 
73
- # show rich console spinner
88
+ results = [
89
+ r if not isinstance(r, BaseException) else None
90
+ for r in results_with_exceptions
91
+ ]
74
92
 
75
- n = len(items)
76
- with console.status(f"[bold green]Running {n} copies of {task.name}..."):
77
- 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)))
78
111
 
79
112
  return results
80
113
 
81
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
+
82
157
  def run_batch_agent_method(
83
158
  agent: Agent,
84
159
  method: Callable[
@@ -149,7 +224,7 @@ def run_batch_agent_method(
149
224
  )
150
225
 
151
226
  n = len(items)
152
- with console.status(f"[bold green]Running {n} copies of {agent_name}..."):
227
+ with status(f"[bold green]Running {n} copies of {agent_name}..."):
153
228
  results = asyncio.run(_do_all())
154
229
 
155
230
  return results
@@ -20,8 +20,9 @@ from langroid.language_models.base import (
20
20
  )
21
21
  from langroid.language_models.openai_gpt import OpenAIGPT
22
22
  from langroid.utils.configuration import settings
23
+ from langroid.utils.output import status
23
24
 
24
- console = Console(quiet=settings.quiet)
25
+ console = Console()
25
26
 
26
27
  logger = logging.getLogger(__name__)
27
28
 
@@ -154,6 +155,8 @@ class ChatAgent(Agent):
154
155
  new_agent.llm_functions_handled = self.llm_functions_handled
155
156
  new_agent.llm_functions_usable = self.llm_functions_usable
156
157
  new_agent.llm_function_force = self.llm_function_force
158
+ # Caution - we are copying the vector-db, maybe we don't always want this?
159
+ new_agent.vecdb = self.vecdb
157
160
  return new_agent
158
161
 
159
162
  def _fn_call_available(self) -> bool:
@@ -490,9 +493,7 @@ class ChatAgent(Agent):
490
493
  response.metadata.tool_ids = (
491
494
  []
492
495
  if isinstance(message, str)
493
- else message.metadata.tool_ids
494
- if message is not None
495
- else []
496
+ else message.metadata.tool_ids if message is not None else []
496
497
  )
497
498
  return response
498
499
 
@@ -515,9 +516,7 @@ class ChatAgent(Agent):
515
516
  response.metadata.tool_ids = (
516
517
  []
517
518
  if isinstance(message, str)
518
- else message.metadata.tool_ids
519
- if message is not None
520
- else []
519
+ else message.metadata.tool_ids if message is not None else []
521
520
  )
522
521
  return response
523
522
 
@@ -682,9 +681,12 @@ class ChatAgent(Agent):
682
681
  streamer = self.callbacks.start_llm_stream()
683
682
  self.llm.config.streamer = streamer
684
683
  with ExitStack() as stack: # for conditionally using rich spinner
685
- if not self.llm.get_stream() and not settings.quiet:
684
+ if not self.llm.get_stream():
686
685
  # show rich spinner only if not streaming!
687
- cm = console.status("LLM responding to messages...")
686
+ cm = status(
687
+ "LLM responding to messages...",
688
+ log_if_quiet=False,
689
+ )
688
690
  stack.enter_context(cm)
689
691
  if self.llm.get_stream() and not settings.quiet:
690
692
  console.print(f"[green]{self.indent}", end="")
@@ -80,7 +80,6 @@ class OpenAIAssistantConfig(ChatAgentConfig):
80
80
 
81
81
 
82
82
  class OpenAIAssistant(ChatAgent):
83
-
84
83
  """
85
84
  A ChatAgent powered by OpenAI Assistant API:
86
85
  mainly, in `llm_response` method, we avoid maintaining conversation state,
@@ -12,14 +12,15 @@ langroid with the [hf-embeddings] extra, e.g.:
12
12
  pip install "langroid[hf-embeddings]"
13
13
 
14
14
  """
15
+
15
16
  import logging
16
17
  from contextlib import ExitStack
18
+ from functools import cache
17
19
  from typing import Any, Dict, List, Optional, Set, Tuple, no_type_check
18
20
 
21
+ import nest_asyncio
19
22
  import numpy as np
20
23
  import pandas as pd
21
- from rich import print
22
- from rich.console import Console
23
24
  from rich.prompt import Prompt
24
25
 
25
26
  from langroid.agent.batch import run_batch_tasks
@@ -49,14 +50,18 @@ from langroid.prompts.prompts_config import PromptsConfig
49
50
  from langroid.prompts.templates import SUMMARY_ANSWER_PROMPT_GPT4
50
51
  from langroid.utils.configuration import settings
51
52
  from langroid.utils.constants import NO_ANSWER
52
- from langroid.utils.output.printing import show_if_debug
53
+ from langroid.utils.output import show_if_debug, status
53
54
  from langroid.utils.pydantic_utils import dataframe_to_documents, extract_fields
54
55
  from langroid.vector_store.base import VectorStore, VectorStoreConfig
55
56
  from langroid.vector_store.lancedb import LanceDBConfig
56
57
 
57
- logger = logging.getLogger(__name__)
58
58
 
59
- console = Console()
59
+ @cache
60
+ def apply_nest_asyncio() -> None:
61
+ nest_asyncio.apply()
62
+
63
+
64
+ logger = logging.getLogger(__name__)
60
65
 
61
66
  DEFAULT_DOC_CHAT_INSTRUCTIONS = """
62
67
  Your task is to answer questions about various documents.
@@ -248,10 +253,9 @@ class DocChatAgent(ChatAgent):
248
253
  def ingest_doc_paths(
249
254
  self,
250
255
  paths: List[str],
251
- metadata: List[Dict[str, Any]]
252
- | Dict[str, Any]
253
- | DocMetaData
254
- | List[DocMetaData] = [],
256
+ metadata: (
257
+ List[Dict[str, Any]] | Dict[str, Any] | DocMetaData | List[DocMetaData]
258
+ ) = [],
255
259
  ) -> List[Document]:
256
260
  """Split, ingest docs from specified paths,
257
261
  do not add these to config.doc_paths.
@@ -272,9 +276,11 @@ class DocChatAgent(ChatAgent):
272
276
  ):
273
277
  if isinstance(metadata, list):
274
278
  path2meta = {
275
- p: m
276
- if isinstance(m, dict)
277
- else (isinstance(m, DocMetaData) and m.dict()) # appease mypy
279
+ p: (
280
+ m
281
+ if isinstance(m, dict)
282
+ else (isinstance(m, DocMetaData) and m.dict())
283
+ ) # appease mypy
278
284
  for p, m in zip(all_paths, metadata)
279
285
  }
280
286
  elif isinstance(metadata, dict):
@@ -322,10 +328,9 @@ class DocChatAgent(ChatAgent):
322
328
  self,
323
329
  docs: List[Document],
324
330
  split: bool = True,
325
- metadata: List[Dict[str, Any]]
326
- | Dict[str, Any]
327
- | DocMetaData
328
- | List[DocMetaData] = [],
331
+ metadata: (
332
+ List[Dict[str, Any]] | Dict[str, Any] | DocMetaData | List[DocMetaData]
333
+ ) = [],
329
334
  ) -> int:
330
335
  """
331
336
  Chunk docs into pieces, map each chunk to vec-embedding, store in vec-db
@@ -623,7 +628,7 @@ class DocChatAgent(ChatAgent):
623
628
  query_str = query_str[1:] if query_str is not None else None
624
629
  if self.llm is None:
625
630
  raise ValueError("LLM not set")
626
- with StreamingIfAllowed(self.llm):
631
+ with StreamingIfAllowed(self.llm, self.llm.get_stream()):
627
632
  response = super().llm_response(query_str)
628
633
  if query_str is not None:
629
634
  self.update_dialog(
@@ -649,6 +654,49 @@ class DocChatAgent(ChatAgent):
649
654
  ),
650
655
  )
651
656
 
657
+ async def llm_response_async(
658
+ self,
659
+ query: None | str | ChatDocument = None,
660
+ ) -> Optional[ChatDocument]:
661
+ apply_nest_asyncio()
662
+ if not self.llm_can_respond(query):
663
+ return None
664
+ query_str: str | None
665
+ if isinstance(query, ChatDocument):
666
+ query_str = query.content
667
+ else:
668
+ query_str = query
669
+ if query_str is None or query_str.startswith("!"):
670
+ # direct query to LLM
671
+ query_str = query_str[1:] if query_str is not None else None
672
+ if self.llm is None:
673
+ raise ValueError("LLM not set")
674
+ with StreamingIfAllowed(self.llm, self.llm.get_stream()):
675
+ response = await super().llm_response_async(query_str)
676
+ if query_str is not None:
677
+ self.update_dialog(
678
+ query_str, "" if response is None else response.content
679
+ )
680
+ return response
681
+ if query_str == "":
682
+ return None
683
+ elif query_str == "?" and self.response is not None:
684
+ return self.justify_response()
685
+ elif (query_str.startswith(("summar", "?")) and self.response is None) or (
686
+ query_str == "??"
687
+ ):
688
+ return self.summarize_docs()
689
+ else:
690
+ self.callbacks.show_start_response(entity="llm")
691
+ response = self.answer_from_docs(query_str)
692
+ return ChatDocument(
693
+ content=response.content,
694
+ metadata=ChatDocMetaData(
695
+ source=response.metadata.source,
696
+ sender=Entity.LLM,
697
+ ),
698
+ )
699
+
652
700
  @staticmethod
653
701
  def doc_string(docs: List[Document]) -> str:
654
702
  """
@@ -735,7 +783,7 @@ class DocChatAgent(ChatAgent):
735
783
  def llm_hypothetical_answer(self, query: str) -> str:
736
784
  if self.llm is None:
737
785
  raise ValueError("LLM not set")
738
- with console.status("[cyan]LLM generating hypothetical answer..."):
786
+ with status("[cyan]LLM generating hypothetical answer..."):
739
787
  with StreamingIfAllowed(self.llm, False):
740
788
  # TODO: provide an easy way to
741
789
  # Adjust this prompt depending on context.
@@ -755,7 +803,7 @@ class DocChatAgent(ChatAgent):
755
803
  def llm_rephrase_query(self, query: str) -> List[str]:
756
804
  if self.llm is None:
757
805
  raise ValueError("LLM not set")
758
- with console.status("[cyan]LLM generating rephrases of query..."):
806
+ with status("[cyan]LLM generating rephrases of query..."):
759
807
  with StreamingIfAllowed(self.llm, False):
760
808
  rephrases = self.llm_response_forget(
761
809
  f"""
@@ -771,7 +819,7 @@ class DocChatAgent(ChatAgent):
771
819
  ) -> List[Tuple[Document, float]]:
772
820
  # find similar docs using bm25 similarity:
773
821
  # these may sometimes be more likely to contain a relevant verbatim extract
774
- with console.status("[cyan]Searching for similar chunks using bm25..."):
822
+ with status("[cyan]Searching for similar chunks using bm25..."):
775
823
  if self.chunked_docs is None or len(self.chunked_docs) == 0:
776
824
  logger.warning("No chunked docs; cannot use bm25-similarity")
777
825
  return []
@@ -789,7 +837,7 @@ class DocChatAgent(ChatAgent):
789
837
  def get_fuzzy_matches(self, query: str, multiple: int) -> List[Document]:
790
838
  # find similar docs using fuzzy matching:
791
839
  # these may sometimes be more likely to contain a relevant verbatim extract
792
- with console.status("[cyan]Finding fuzzy matches in chunks..."):
840
+ with status("[cyan]Finding fuzzy matches in chunks..."):
793
841
  if self.chunked_docs is None:
794
842
  logger.warning("No chunked docs; cannot use fuzzy matching")
795
843
  return []
@@ -809,7 +857,7 @@ class DocChatAgent(ChatAgent):
809
857
  def rerank_with_cross_encoder(
810
858
  self, query: str, passages: List[Document]
811
859
  ) -> List[Document]:
812
- with console.status("[cyan]Re-ranking retrieved chunks using cross-encoder..."):
860
+ with status("[cyan]Re-ranking retrieved chunks using cross-encoder..."):
813
861
  try:
814
862
  from sentence_transformers import CrossEncoder
815
863
  except ImportError:
@@ -954,7 +1002,7 @@ class DocChatAgent(ChatAgent):
954
1002
  # Note: for dynamic filtering based on a query, users can
955
1003
  # use the `temp_update` context-manager to pass in a `filter` to self.config,
956
1004
  # e.g.:
957
- # with temp_update(self.config, filter="metadata.source=='source1'"):
1005
+ # with temp_update(self.config, {"filter": "metadata.source=='source1'"}):
958
1006
  # docs_scores = self.get_semantic_search_results(query, k=k)
959
1007
  # This avoids having pass the `filter` argument to every function call
960
1008
  # upstream of this one.
@@ -1002,7 +1050,7 @@ class DocChatAgent(ChatAgent):
1002
1050
  if self.vecdb is None:
1003
1051
  raise ValueError("VecDB not set")
1004
1052
 
1005
- with console.status("[cyan]Searching VecDB for relevant doc passages..."):
1053
+ with status("[cyan]Searching VecDB for relevant doc passages..."):
1006
1054
  docs_and_scores: List[Tuple[Document, float]] = []
1007
1055
  for q in [query] + query_proxies:
1008
1056
  docs_and_scores += self.get_semantic_search_results(
@@ -1078,7 +1126,7 @@ class DocChatAgent(ChatAgent):
1078
1126
  # Regardless of whether we are in conversation mode or not,
1079
1127
  # for relevant doc/chunk extraction, we must convert the query
1080
1128
  # to a standalone query to get more relevant results.
1081
- with console.status("[cyan]Converting to stand-alone query...[/cyan]"):
1129
+ with status("[cyan]Converting to stand-alone query...[/cyan]"):
1082
1130
  with StreamingIfAllowed(self.llm, False):
1083
1131
  query = self.llm.followup_to_standalone(self.dialog, query)
1084
1132
  print(f"[orange2]New query: {query}")
@@ -1097,7 +1145,7 @@ class DocChatAgent(ChatAgent):
1097
1145
  if len(passages) == 0:
1098
1146
  return query, []
1099
1147
 
1100
- with console.status("[cyan]LLM Extracting verbatim passages..."):
1148
+ with status("[cyan]LLM Extracting verbatim passages..."):
1101
1149
  with StreamingIfAllowed(self.llm, False):
1102
1150
  # these are async calls, one per passage; turn off streaming
1103
1151
  extracts = self.get_verbatim_extracts(query, passages)
@@ -1198,7 +1246,7 @@ class DocChatAgent(ChatAgent):
1198
1246
  cm = (
1199
1247
  StreamingIfAllowed(self.llm)
1200
1248
  if settings.stream
1201
- else (console.status("LLM Generating final answer..."))
1249
+ else (status("LLM Generating final answer..."))
1202
1250
  )
1203
1251
  stack.enter_context(cm) # type: ignore
1204
1252
  response = self.get_summary_answer(query, extracts)
@@ -9,6 +9,7 @@ For usage see:
9
9
  - example script `examples/docqa/lance_rag.py`.
10
10
 
11
11
  """
12
+
12
13
  import json
13
14
  import logging
14
15
  from typing import Any, Dict, List, Tuple
@@ -162,10 +163,9 @@ class LanceDocChatAgent(DocChatAgent):
162
163
  self,
163
164
  docs: List[Document],
164
165
  split: bool = True,
165
- metadata: List[Dict[str, Any]]
166
- | Dict[str, Any]
167
- | DocMetaData
168
- | List[DocMetaData] = [],
166
+ metadata: (
167
+ List[Dict[str, Any]] | Dict[str, Any] | DocMetaData | List[DocMetaData]
168
+ ) = [],
169
169
  ) -> int:
170
170
  n = super().ingest_docs(docs, split, metadata)
171
171
  tbl = self.vecdb.client.open_table(self.vecdb.config.collection_name)
@@ -2,7 +2,6 @@ from typing import List, Optional
2
2
 
3
3
  import pandas as pd
4
4
  import typer
5
- from rich.console import Console
6
5
 
7
6
  from langroid.agent.special.neo4j.neo4j_chat_agent import (
8
7
  Neo4jChatAgent,
@@ -11,9 +10,9 @@ from langroid.agent.special.neo4j.neo4j_chat_agent import (
11
10
  from langroid.agent.tool_message import ToolMessage
12
11
  from langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig
13
12
  from langroid.parsing.table_loader import read_tabular_data
13
+ from langroid.utils.output import status
14
14
  from langroid.vector_store.base import VectorStoreConfig
15
15
 
16
- console = Console()
17
16
  app = typer.Typer()
18
17
 
19
18
 
@@ -159,7 +158,7 @@ class CSVGraphAgent(Neo4jChatAgent):
159
158
  Returns:
160
159
  str: A string indicating the success or failure of the operation.
161
160
  """
162
- with console.status("[cyan]Generating graph database..."):
161
+ with status("[cyan]Generating graph database..."):
163
162
  if self.df is not None and hasattr(self.df, "iterrows"):
164
163
  for counter, (index, row) in enumerate(self.df.iterrows()):
165
164
  row_dict = row.to_dict()
@@ -3,6 +3,7 @@ Agent to retrieve relevant segments from a body of text,
3
3
  that are relevant to a query.
4
4
 
5
5
  """
6
+
6
7
  import logging
7
8
  from typing import Optional, no_type_check
8
9
 
@@ -11,6 +11,7 @@ generating final summary answer based on relevant extracts, it just returns
11
11
  those extracts.
12
12
  See test_retriever_agent.py for example usage.
13
13
  """
14
+
14
15
  import logging
15
16
  from typing import Sequence
16
17
 
@@ -6,6 +6,7 @@ Functionality includes:
6
6
  - adding table and column context
7
7
  - asking a question about a SQL schema
8
8
  """
9
+
9
10
  import logging
10
11
  from typing import Any, Dict, List, Optional, Sequence, Union
11
12
 
@@ -60,9 +60,9 @@ def populate_metadata(
60
60
  Dict: A dictionary containing populated metadata information.
61
61
  """
62
62
  # Fetch basic metadata info using available tools
63
- db_info: Dict[
64
- str, Dict[str, Union[str, Dict[str, str]]]
65
- ] = populate_metadata_with_schema_tools(metadata=metadata, info=info)
63
+ db_info: Dict[str, Dict[str, Union[str, Dict[str, str]]]] = (
64
+ populate_metadata_with_schema_tools(metadata=metadata, info=info)
65
+ )
66
66
 
67
67
  # Iterate over tables to update column metadata
68
68
  for table_name in db_info.keys():
@@ -7,6 +7,7 @@ code to answer the query. The code is passed via the `run_code` tool/function-ca
7
7
  which is handled by the Agent's `run_code` method. This method executes/evaluates
8
8
  the code and returns the result as a string.
9
9
  """
10
+
10
11
  import io
11
12
  import logging
12
13
  import sys
@@ -20,6 +20,7 @@ your `.env` file, e.g. `METAPHOR_API_KEY=your_api_key_here`
20
20
  For more information, please refer to the official docs:
21
21
  https://metaphor.systems/
22
22
  """
23
+
23
24
  from typing import List
24
25
 
25
26
  from langroid.agent.tool_message import ToolMessage
@@ -8,6 +8,7 @@ NOTE: Using this tool requires setting the GOOGLE_API_KEY and GOOGLE_CSE_ID
8
8
  environment variables in your `.env` file, as explained in the
9
9
  [README](https://github.com/langroid/langroid#gear-installation-and-setup).
10
10
  """
11
+
11
12
  from typing import List
12
13
 
13
14
  from langroid.agent.tool_message import ToolMessage
@@ -20,6 +20,7 @@ your `.env` file, e.g. `METAPHOR_API_KEY=your_api_key_here`
20
20
  For more information, please refer to the official docs:
21
21
  https://metaphor.systems/
22
22
  """
23
+
23
24
  from typing import List
24
25
 
25
26
  from langroid.agent.tool_message import ToolMessage
@@ -7,6 +7,7 @@ the method `_get_tool_list()`).
7
7
  See usage examples in `tests/main/test_multi_agent_complex.py` and
8
8
  `tests/main/test_recipient_tool.py`.
9
9
  """
10
+
10
11
  from typing import List, Type
11
12
 
12
13
  from rich import print
@@ -9,6 +9,7 @@ where `port` is the port at which the service is exposed. Currently,
9
9
  supports insecure connections only, and this should NOT be exposed to
10
10
  the internet.
11
11
  """
12
+
12
13
  import atexit
13
14
  import subprocess
14
15
  import time
@@ -4,6 +4,7 @@ from their Transformers library. It searches the hub for a model matching the
4
4
  specified name, and uses the first one it finds. We assume that all matching
5
5
  models will have the same tokenizer, so we just use the first one.
6
6
  """
7
+
7
8
  import logging
8
9
  import re
9
10
  from typing import Any, List, Set, Tuple, Type
langroid/parsing/utils.py CHANGED
@@ -4,7 +4,7 @@ import random
4
4
  import re
5
5
  from functools import cache
6
6
  from itertools import islice
7
- from typing import Any, Iterable, List
7
+ from typing import Iterable, List, Sequence, TypeVar
8
8
 
9
9
  import nltk
10
10
  from faker import Faker
@@ -30,7 +30,10 @@ def download_nltk_resource(resource: str) -> None:
30
30
  nltk.download(resource, quiet=True)
31
31
 
32
32
 
33
- def batched(iterable: Iterable[Any], n: int) -> Iterable[Any]:
33
+ T = TypeVar("T")
34
+
35
+
36
+ def batched(iterable: Iterable[T], n: int) -> Iterable[Sequence[T]]:
34
37
  """Batch data into tuples of length n. The last batch may be shorter."""
35
38
  # batched('ABCDEFG', 3) --> ABC DEF G
36
39
  if n < 1:
@@ -1,16 +1,21 @@
1
- import langroid.utils.output.printing as printing
1
+ from . import printing
2
2
 
3
- from langroid.utils.output.printing import (
3
+ from .printing import (
4
4
  shorten_text,
5
5
  print_long_text,
6
6
  show_if_debug,
7
+ SuppressLoggerWarnings,
7
8
  PrintColored,
8
9
  )
9
10
 
11
+ from .status import status
12
+
10
13
  __all__ = [
11
14
  "printing",
12
15
  "shorten_text",
13
16
  "print_long_text",
14
17
  "show_if_debug",
18
+ "SuppressLoggerWarnings",
15
19
  "PrintColored",
20
+ "status",
16
21
  ]
@@ -0,0 +1,33 @@
1
+ import logging
2
+ from contextlib import AbstractContextManager, ExitStack
3
+ from typing import Any
4
+
5
+ from rich.console import Console
6
+
7
+ from langroid.utils.configuration import quiet_mode, settings
8
+
9
+ console = Console()
10
+ logger = logging.getLogger(__name__)
11
+ logger.setLevel(logging.INFO)
12
+
13
+
14
+ def status(
15
+ msg: str,
16
+ log_if_quiet: bool = True,
17
+ ) -> AbstractContextManager[Any]:
18
+ """
19
+ Displays a rich spinner if not in quiet mode, else optionally logs the message.
20
+ """
21
+ stack = ExitStack()
22
+
23
+ if settings.quiet:
24
+ if log_if_quiet:
25
+ logger.info(msg)
26
+ if settings.quiet and log_if_quiet:
27
+ logger.info(msg)
28
+ else:
29
+ stack.enter_context(console.status(msg))
30
+
31
+ stack.enter_context(quiet_mode(not settings.debug))
32
+
33
+ return stack
@@ -16,9 +16,11 @@ def stringify(x: Any) -> str:
16
16
  for col in df.columns:
17
17
  if df[col].dtype == object:
18
18
  df[col] = df[col].apply(
19
- lambda item: (item[:1000] + "...")
20
- if isinstance(item, str) and len(item) > 1000
21
- else item
19
+ lambda item: (
20
+ (item[:1000] + "...")
21
+ if isinstance(item, str) and len(item) > 1000
22
+ else item
23
+ )
22
24
  )
23
25
 
24
26
  # Limit to 10 rows
@@ -162,7 +162,10 @@ class ChromaDB(VectorStore):
162
162
  return self._docs_from_results(final_results)
163
163
 
164
164
  def delete_collection(self, collection_name: str) -> None:
165
- self.client.delete_collection(name=collection_name)
165
+ try:
166
+ self.client.delete_collection(name=collection_name)
167
+ except Exception:
168
+ pass
166
169
 
167
170
  def similar_texts_with_scores(
168
171
  self, text: str, k: int = 1, where: Optional[str] = None
@@ -198,7 +201,10 @@ class ChromaDB(VectorStore):
198
201
  metadatas = results["metadatas"][0]
199
202
  for m in metadatas:
200
203
  # restore the stringified list of window_ids into the original List[str]
201
- m["window_ids"] = m["window_ids"].split(",")
204
+ if m["window_ids"].strip() == "":
205
+ m["window_ids"] = []
206
+ else:
207
+ m["window_ids"] = m["window_ids"].split(",")
202
208
  docs = [
203
209
  Document(content=d, metadata=DocMetaData(**m))
204
210
  for d, m in zip(contents, metadatas)
@@ -366,7 +366,7 @@ class LanceDB(VectorStore):
366
366
  tbl.add(df)
367
367
 
368
368
  def delete_collection(self, collection_name: str) -> None:
369
- self.client.drop_table(collection_name)
369
+ self.client.drop_table(collection_name, ignore_missing=True)
370
370
 
371
371
  def _lance_result_to_docs(self, result: LanceVectorQueryBuilder) -> List[Document]:
372
372
  if self.is_from_dataframe:
@@ -440,7 +440,10 @@ class LanceDB(VectorStore):
440
440
  embedding = self.embedding_fn([text])[0]
441
441
  tbl = self.client.open_table(self.config.collection_name)
442
442
  result = (
443
- tbl.search(embedding).metric(self.config.distance).where(where).limit(k)
443
+ tbl.search(embedding)
444
+ .metric(self.config.distance)
445
+ .where(where, prefilter=True)
446
+ .limit(k)
444
447
  )
445
448
  docs = self._lance_result_to_docs(result)
446
449
  # note _distance is 1 - cosine
@@ -2,6 +2,7 @@
2
2
  Momento Vector Index.
3
3
  https://docs.momentohq.com/vector-index/develop/api-reference
4
4
  """
5
+
5
6
  import logging
6
7
  import os
7
8
  from typing import List, Optional, Sequence, Tuple, no_type_check
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.1.214
3
+ Version: 0.1.217
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -26,7 +26,7 @@ Requires-Dist: agent-search (>=0.0.7,<0.0.8) ; extra == "sciphi"
26
26
  Requires-Dist: aiohttp (>=3.9.1,<4.0.0)
27
27
  Requires-Dist: async-generator (>=1.10,<2.0)
28
28
  Requires-Dist: autopep8 (>=2.0.2,<3.0.0)
29
- Requires-Dist: black[jupyter] (>=23.3.0,<24.0.0)
29
+ Requires-Dist: black[jupyter] (>=24.3.0,<25.0.0)
30
30
  Requires-Dist: bs4 (>=0.0.1,<0.0.2)
31
31
  Requires-Dist: chainlit (>=1.0.400,<2.0.0) ; extra == "chainlit"
32
32
  Requires-Dist: chromadb (>=0.4.21,<=0.4.23) ; extra == "chromadb"
@@ -232,6 +232,11 @@ teacher_task.run()
232
232
  <summary> <b>Click to expand</b></summary>
233
233
 
234
234
  - **Mar 2024:**
235
+ - **0.1.216:** Improvements to allow concurrent runs of `DocChatAgent`, see the
236
+ [`test_doc_chat_agent.py`](https://github.com/langroid/langroid/blob/main/tests/main/test_doc_chat_agent.py)
237
+ in particular the `test_doc_chat_batch()`;
238
+ New task run utility: [`run_batch_task_gen`](https://github.com/langroid/langroid/blob/main/langroid/agent/batch.py)
239
+ where a task generator can be specified, to generate one task per input.
235
240
  - **0.1.212:** ImagePdfParser: support for extracting text from image-based PDFs.
236
241
  (this means `DocChatAgent` will now work with image-pdfs).
237
242
  - **0.1.194 - 0.1.211:** Misc fixes, improvements, and features:
@@ -1,46 +1,46 @@
1
1
  langroid/__init__.py,sha256=qgY-OqzYSWOc6EytQJN9sH2PwDp1UIzP9lXhrYH6aLU,1645
2
- langroid/agent/__init__.py,sha256=w2pap-rHrp41gMzdtzur2YY_m62LqQhF2Du-AmoIQi4,752
3
- langroid/agent/base.py,sha256=Qr2YJASCWOjIcCjISb_SSSNOEvEw4_Kkl21FZx0aigE,35026
4
- langroid/agent/batch.py,sha256=wGDqCwHwz9ABAAzJFHzqPU50LJMgMLTQzH0avZfWiMA,6559
2
+ langroid/agent/__init__.py,sha256=_D8dxnfdr92ch1CIrUkKjrB5HVvsQdn62b1Fb2kBxV8,785
3
+ langroid/agent/base.py,sha256=jyGFmojrFuOy81lUkNsJlR6mLIOY6kOD20P9dhEcEuw,35059
4
+ langroid/agent/batch.py,sha256=T9dgSPThrmIWxQxqDlGwhHa7yw3XIKE_U30bLMRDpNQ,9481
5
5
  langroid/agent/callbacks/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
6
6
  langroid/agent/callbacks/chainlit.py,sha256=aYuJ8M4VDHr5oymoXL2bpThM7p6P9L45fgJf3MLdkWo,20997
7
- langroid/agent/chat_agent.py,sha256=QCAA56rObVrnKyCdO5pqklUukxkU4aykoUZzZ2tYvU8,38609
7
+ langroid/agent/chat_agent.py,sha256=X5uVMm9qdw3j-FRf4hbN8k8ByaSdtQCTuU8olKE0sbs,38750
8
8
  langroid/agent/chat_document.py,sha256=PL8iA1ZYjXNFVa3kMO8T4sbbM3rzHWpRAY6PN_7n5LQ,7969
9
9
  langroid/agent/helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
10
10
  langroid/agent/junk,sha256=LxfuuW7Cijsg0szAzT81OjWWv1PMNI-6w_-DspVIO2s,339
11
- langroid/agent/openai_assistant.py,sha256=VWRbn_Xal8ezqfzpTOPnM4uifW77L9cISZJgHZ6i7XU,32703
11
+ langroid/agent/openai_assistant.py,sha256=QTLBgnH6Btf2GWzN-WApvra-vPQWvYcXcAOULuIy4Ig,32702
12
12
  langroid/agent/special/__init__.py,sha256=XPE076zD-roskxNBn-A1hnh4AHoMiQN9gk1UDjPaBaU,1201
13
- langroid/agent/special/doc_chat_agent.py,sha256=xe5lz6d_psHTNhBd9QoyZ5nIZE5u8SawsHyhA2Tn8cA,50007
14
- langroid/agent/special/lance_doc_chat_agent.py,sha256=gEZ_MOC_2qbEzi2oRbZpZEgx5MbuYE-T8toE0WmCPvs,10174
13
+ langroid/agent/special/doc_chat_agent.py,sha256=xzUArFTeHS2Mg8x80S_a9W-rrPONeJn-gMwO6l_WxA0,51722
14
+ langroid/agent/special/lance_doc_chat_agent.py,sha256=USp0U3eTaJzwF_3bdqE7CedSLbaqAi2tm-VzygcyLaA,10175
15
15
  langroid/agent/special/lance_rag/__init__.py,sha256=QTbs0IVE2ZgDg8JJy1zN97rUUg4uEPH7SLGctFNumk4,174
16
16
  langroid/agent/special/lance_rag/critic_agent.py,sha256=pi_9eMBxEycbWTddtq_yz-mOb2V4SgGm3zfsOH1HU-Q,5775
17
17
  langroid/agent/special/lance_rag/lance_rag_task.py,sha256=l_HQgrYY-CX2FwIsS961aEF3bYog3GDYo98fj0C0mSk,2889
18
18
  langroid/agent/special/lance_rag/query_planner_agent.py,sha256=_8AwZsuEaoHGjrOrkLU2Lvxuqi4h8PkxBRcPmWPOSHk,8033
19
19
  langroid/agent/special/lance_tools.py,sha256=WypIS-3ZMDqY_PZEGB2K80-o4RfS43_OnER0dyFlsDY,1339
20
20
  langroid/agent/special/neo4j/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
21
- langroid/agent/special/neo4j/csv_kg_chat.py,sha256=YfuyblH9d307ggzN7fUD2mxLorIdexjVAlZ8uVDZqhY,6394
21
+ langroid/agent/special/neo4j/csv_kg_chat.py,sha256=koL3sKtHm3aRkLTiARs54ngrcU3lOR1WaLLc_i8rWOU,6374
22
22
  langroid/agent/special/neo4j/neo4j_chat_agent.py,sha256=vBr6EQ_eJCYAtqDe-gTSvWHT-jRE_fZOPsGWxuDJe4w,13092
23
23
  langroid/agent/special/neo4j/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
24
24
  langroid/agent/special/neo4j/utils/system_message.py,sha256=vRpz1P-OYLLiC6OGYYoK6x77yxVzDxMTCEJSsYUIuG4,2242
25
- langroid/agent/special/relevance_extractor_agent.py,sha256=uJ1jS_7S_gnJeuOUxEren-IHi1kfVx475B8L4H8RcEM,4795
26
- langroid/agent/special/retriever_agent.py,sha256=uu6vqFg85uCVM-_DrXesYe2gH_-WcoHhlsKRlLuZPXk,1867
25
+ langroid/agent/special/relevance_extractor_agent.py,sha256=zIx8GUdVo1aGW6ASla0NPQjYYIpmriK_TYMijqAx3F8,4796
26
+ langroid/agent/special/retriever_agent.py,sha256=lvMvf-u9rSosg4YASuFdUbGLgkzLPknXAbJZfZ1LZCc,1868
27
27
  langroid/agent/special/sql/__init__.py,sha256=qUM-b4FfvIt0gYWP7_niyqR3OwVMMkuK2SyqUYWjyxs,207
28
- langroid/agent/special/sql/sql_chat_agent.py,sha256=YpLWLf0fOd9CM5lld-bW1Cd_DHon3NGqb8y8uQ0dqkA,13745
28
+ langroid/agent/special/sql/sql_chat_agent.py,sha256=ZTK19ToIpSxtedwzsqL38diMtHth6uVDf25Wng2dn7Q,13746
29
29
  langroid/agent/special/sql/utils/__init__.py,sha256=i8oYoyI4aV1LcYktMOhzi_eYbQ6RVt2e7Dj2bXkCZXc,447
30
30
  langroid/agent/special/sql/utils/description_extractors.py,sha256=RZ2R3DmASxB1ijzbA_TuxkhP00Pxcg_tAKlLXGo3rcg,6381
31
- langroid/agent/special/sql/utils/populate_metadata.py,sha256=5-tkmMV50iTT4Af_Lu4k4U9szqNIiINg4qpRLKPVNs0,2985
31
+ langroid/agent/special/sql/utils/populate_metadata.py,sha256=x2OMKfmIBnJESBG3qKt6gvr3H3L4ZQcoxHfNdWfHjZs,2987
32
32
  langroid/agent/special/sql/utils/system_message.py,sha256=qKLHkvQWRQodTtPLPxr1GSLUYUFASZU8x-ybV67cB68,1885
33
33
  langroid/agent/special/sql/utils/tools.py,sha256=6uB2424SLtmapui9ggcEr0ZTiB6_dL1-JRGgN8RK9Js,1332
34
- langroid/agent/special/table_chat_agent.py,sha256=GEUTP-VdtMXq4CcPV80gDQrCEn-ZFb9IhuRMtLN5I1o,9030
34
+ langroid/agent/special/table_chat_agent.py,sha256=rUV7Rv2GFF6Yqv3_uqvgFSs_EdyDUNpdQobTTpjdEtc,9031
35
35
  langroid/agent/task.py,sha256=sFncTES0L_O2IpbnHRrNzad0HhtsbHoQ7j3Cjc9eTt0,49711
36
36
  langroid/agent/tool_message.py,sha256=2kPsQUwi3ZzINTUNj10huKnZLjLp5SXmefacTHx8QDc,8304
37
37
  langroid/agent/tools/__init__.py,sha256=q-maq3k2BXhPAU99G0H6-j_ozoRvx15I1RFpPVicQIU,304
38
- langroid/agent/tools/duckduckgo_search_tool.py,sha256=lgBFIPGdEffyxFuP6NUqRVBXyqypqHHSQBf-06xWsZE,2460
38
+ langroid/agent/tools/duckduckgo_search_tool.py,sha256=yvd735hJkFRgcJF7pgaiIg0OmMw5BMFxqDTyyg1EC9g,2461
39
39
  langroid/agent/tools/extract_tool.py,sha256=u5lL9rKBzaLBOrRyLnTAZ97pQ1uxyLP39XsWMnpaZpw,3789
40
40
  langroid/agent/tools/generator_tool.py,sha256=y0fB0ZObjA0b3L0uSTtrqRCKHDUR95arBftqiUeKD2o,663
41
- langroid/agent/tools/google_search_tool.py,sha256=Cmhvdgr4p_nqTIAiYW8k-TkLd7lgFToLF7x_QiIkJPE,1420
42
- langroid/agent/tools/metaphor_search_tool.py,sha256=x7fI8nN7eL8DXpeE4Ipt8sa7MYxzM0S5IcSaYNbm1P4,2453
43
- langroid/agent/tools/recipient_tool.py,sha256=o4qWuz-Lp2QkOQNy6PkRMT9AEc7btuk8EJXpTg0uPV4,9170
41
+ langroid/agent/tools/google_search_tool.py,sha256=cQxcNtb8XCNpOo_yCeYRwG_y-OATjPgkbr01kea9qWE,1421
42
+ langroid/agent/tools/metaphor_search_tool.py,sha256=NKHss-AkI942_XhfMgUctAwHjIHpqp5NfYIebKV4UcE,2454
43
+ langroid/agent/tools/recipient_tool.py,sha256=61vdKv06qgVdtnE3gxjzV8RvUEy8JhbC9eWa0J0BPdw,9171
44
44
  langroid/agent/tools/run_python_code.py,sha256=V3mHdHQYn0M0PAtyoHxjNvk6KvWWcQ4ugo0TOKc8HyI,1752
45
45
  langroid/agent/tools/sciphi_search_rag_tool.py,sha256=IAEgZY5-euQh8MndMzZnn1XVxaItvWYB2VF9-YHfunk,2496
46
46
  langroid/agent/tools/segment_extract_tool.py,sha256=W39poS7Av2EuJ34tGKhLhzgj3zEyZnBplpSt2goRAp4,1285
@@ -57,7 +57,7 @@ langroid/embedding_models/protoc/embeddings.proto,sha256=_O-SgFpTaylQeOTgSpxhEJ7
57
57
  langroid/embedding_models/protoc/embeddings_pb2.py,sha256=4Q57PhOunv-uZNJrxYrWBXAI0ZtfnVZXFRhRj5JuRSg,1662
58
58
  langroid/embedding_models/protoc/embeddings_pb2.pyi,sha256=UkNy7BrNsmQm0vLb3NtGXy8jVtz-kPWwwFsX-QbQBhQ,1475
59
59
  langroid/embedding_models/protoc/embeddings_pb2_grpc.py,sha256=9dYQqkW3JPyBpSEjeGXTNpSqAkC-6FPtBHyteVob2Y8,2452
60
- langroid/embedding_models/remote_embeds.py,sha256=EeIOS0s9MToKDooGTFa9cx9279I8SDyQybs49vgfRoE,5150
60
+ langroid/embedding_models/remote_embeds.py,sha256=6_kjXByVbqhY9cGwl9R83ZcYC2km-nGieNNAo1McHaY,5151
61
61
  langroid/language_models/__init__.py,sha256=5L9ndEEC8iLJHjDJmYFTnv6-2-3xsxWUMHcugR8IeDs,821
62
62
  langroid/language_models/azure_openai.py,sha256=ncRCbKooqLVOY-PWQUIo9C3yTuKEFbAwyngXT_M4P7k,5989
63
63
  langroid/language_models/base.py,sha256=4ybrbvOnoWzEVzVuZ3AStsl8ELoljiKtgtdykUzRSxg,21014
@@ -66,7 +66,7 @@ langroid/language_models/openai_assistants.py,sha256=9K-DEAL2aSWHeXj2hwCo2RAlK9_
66
66
  langroid/language_models/openai_gpt.py,sha256=6CE6I_hmnHfRIMJMh4qhVeKijgKEm_LNcWNn3vLMLlM,49680
67
67
  langroid/language_models/prompt_formatter/__init__.py,sha256=9JXFF22QNMmbQV1q4nrIeQVTtA3Tx8tEZABLtLBdFyc,352
68
68
  langroid/language_models/prompt_formatter/base.py,sha256=eDS1sgRNZVnoajwV_ZIha6cba5Dt8xjgzdRbPITwx3Q,1221
69
- langroid/language_models/prompt_formatter/hf_formatter.py,sha256=QhVj5DcJYqveLC6nE3DKjsiJ8jY-J__8--NNp-2h8vI,5216
69
+ langroid/language_models/prompt_formatter/hf_formatter.py,sha256=TFL6ppmeQWnzr6CKQzRZFYY810zE1mr8DZnhw6i85ok,5217
70
70
  langroid/language_models/prompt_formatter/llama2_formatter.py,sha256=YdcO88qyBeuMENVIVvVqSYuEpvYSTndUe_jd6hVTko4,2899
71
71
  langroid/language_models/utils.py,sha256=ivbmAUpDewWb-j9HNhnpmFeQbELQaGYRNul4wiP9p3c,4756
72
72
  langroid/mytypes.py,sha256=opL488mtHKob1uJeK_h1-kNjU5GZwkgCfXhBQCsONWU,2614
@@ -87,7 +87,7 @@ langroid/parsing/table_loader.py,sha256=qNM4obT_0Y4tjrxNBCNUYjKQ9oETCZ7FbolKBTcz
87
87
  langroid/parsing/url_loader.py,sha256=Na2TBlKuQkloZzkE2d7xl6mh9olS3CbpgCsJbJ-xhIA,4472
88
88
  langroid/parsing/url_loader_cookies.py,sha256=Lg4sNpRz9MByWq2mde6T0hKv68VZSV3mtMjNEHuFeSU,2327
89
89
  langroid/parsing/urls.py,sha256=Nv4yCWQLLBEjaiRdaZZVQNBEl_cfK_V6cVuPm91wGtU,7686
90
- langroid/parsing/utils.py,sha256=OG_QL7XaT8g5YE72MeB---YSyiZYOI7T36ibUwqKYuk,11729
90
+ langroid/parsing/utils.py,sha256=HdmKQ-5XCQXR5dpMtKT9mCGmb8iy3I_rIoObvGTnY7s,11768
91
91
  langroid/parsing/web_search.py,sha256=XSiSHB4c1Wa8RjWkC4Yh-ac8S7a2WPPYj0n-Ma716RY,4759
92
92
  langroid/prompts/__init__.py,sha256=B0vpJzIJlMR3mFRtoQwyALsFzBHvLp9f92acD8xJA_0,185
93
93
  langroid/prompts/chat-gpt4-system-prompt.md,sha256=Q3uLCJTPQvmUkZN2XDnkBC7M2K3X0F3C3GIQBaFvYvw,5329
@@ -105,22 +105,23 @@ langroid/utils/globals.py,sha256=VkTHhlqSz86oOPq65sjul0XU8I52UNaFC5vwybMQ74w,134
105
105
  langroid/utils/llms/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
106
106
  langroid/utils/llms/strings.py,sha256=CSAX9Z6FQOLXOzbLMe_Opqtc3ruDAKTTk7cPqc6Blh0,263
107
107
  langroid/utils/logging.py,sha256=R8TN-FqVpwZ4Ajgls9TDMthLvPpQd0QVNXK-PJDj1Z8,3917
108
- langroid/utils/output/__init__.py,sha256=Z58-2ZKnGpGNaKw_nEjHV_CHTzjMz-WRSRQnazTLrWU,289
108
+ langroid/utils/output/__init__.py,sha256=4X8Hdo1SEm06NUnggMJrLtW8i1owdDQPrS7J08BaTec,341
109
109
  langroid/utils/output/printing.py,sha256=5EsYB1O4qKhocW19aebOUzK82RD9U5nygbY21yo8gfg,2872
110
- langroid/utils/pandas_utils.py,sha256=nSA1tIgOUTkRDn-IKq7HP8XGJcL6bA110LcPfRF7h8I,707
110
+ langroid/utils/output/status.py,sha256=VoSXmWDuddo1ipCzDAA6qlgffr5E4lSmBD0rIdNxxcs,774
111
+ langroid/utils/pandas_utils.py,sha256=UctS986Jtl_MvU5rA7-GfrjEHXP7MNu8ePhepv0bTn0,755
111
112
  langroid/utils/pydantic_utils.py,sha256=yb-ghaQYL7EIYeiZ0tailvZvAuJZNF7UBXkd3z35OYc,21728
112
113
  langroid/utils/system.py,sha256=l-kFqIWkSD9YHOTka02dnihdbnR1mWVrnKSGK3LuEjo,4577
113
114
  langroid/utils/web/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
114
115
  langroid/utils/web/login.py,sha256=1iz9eUAHa87vpKIkzwkmFa00avwFWivDSAr7QUhK7U0,2528
115
116
  langroid/vector_store/__init__.py,sha256=D82ioqPWxKTTbN0qiPNB-I1GjovhLw1MgDuYhcB3hCs,831
116
117
  langroid/vector_store/base.py,sha256=VZl-pvGs6K-ruTT8SQmDthsCp-VARYaf6OuzKmcXN58,13469
117
- langroid/vector_store/chromadb.py,sha256=lTEB9Fu6GlX2ip88tmK2aimjU_ExS1DCwm1TGybtGE4,7944
118
- langroid/vector_store/lancedb.py,sha256=2MN93h_--_bGXnJ7xAbjuvDJxdownDonsZ9ouwD_vYM,18407
118
+ langroid/vector_store/chromadb.py,sha256=rp-qWmYJc_HR48JYNt1MixjJM90jZTdeZIYghd5CenA,8109
119
+ langroid/vector_store/lancedb.py,sha256=lbl8wZuV6GNw0LnIwOSriSNwoMEba90umQTcQHtMw7Y,18483
119
120
  langroid/vector_store/meilisearch.py,sha256=d2huA9P-NoYRuAQ9ZeXJmMKr7ry8u90RUSR28k2ecQg,11340
120
- langroid/vector_store/momento.py,sha256=j6Eo6oIDN2fe7lsBOlCXJn3uvvERHHTFL5QJfeREeOM,10044
121
+ langroid/vector_store/momento.py,sha256=9cui31TTrILid2KIzUpBkN2Ey3g_CZWOQVdaFsA4Ors,10045
121
122
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
122
123
  langroid/vector_store/qdrantdb.py,sha256=_egbsP9SWBwmI827EDYSSOqfIQSmwNsmJfFTxrLpWYE,13457
123
- langroid-0.1.214.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
124
- langroid-0.1.214.dist-info/METADATA,sha256=CEK6U_0EZOGeseq_Eu7rKzC9kCjGgDPpK35lFaPlia8,47446
125
- langroid-0.1.214.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
126
- langroid-0.1.214.dist-info/RECORD,,
124
+ langroid-0.1.217.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
125
+ langroid-0.1.217.dist-info/METADATA,sha256=fXpMt2st2xDZOREQdeIVVyrpeD4Q3z-_a3PX0HBynOE,47888
126
+ langroid-0.1.217.dist-info/WHEEL,sha256=FMvqSimYX_P7y0a7UY-_Mc83r5zkBZsCYPm7Lr0Bsq4,88
127
+ langroid-0.1.217.dist-info/RECORD,,