langroid 0.1.31__tar.gz → 0.1.33__tar.gz
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.
- {langroid-0.1.31 → langroid-0.1.33}/PKG-INFO +8 -4
- {langroid-0.1.31 → langroid-0.1.33}/README.md +7 -3
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/special/retriever_agent.py +5 -2
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/task.py +7 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/cachedb/momento_cachedb.py +1 -1
- {langroid-0.1.31 → langroid-0.1.33}/langroid/language_models/openai_gpt.py +1 -1
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/repo_loader.py +1 -1
- {langroid-0.1.31 → langroid-0.1.33}/langroid/prompts/templates.py +9 -1
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/configuration.py +4 -0
- {langroid-0.1.31 → langroid-0.1.33}/pyproject.toml +1 -1
- langroid-0.1.33/setup.py +88 -0
- langroid-0.1.31/setup.py +0 -88
- {langroid-0.1.31 → langroid-0.1.33}/LICENSE +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/base.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/chat_agent.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/chat_document.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/helpers.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/junk +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/special/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/special/doc_chat_agent.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/special/recipient_validator_agent.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/special/table_chat_agent.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent/tool_message.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/agent_config.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/cachedb/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/cachedb/base.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/cachedb/redis_cachedb.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/embedding_models/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/embedding_models/base.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/embedding_models/clustering.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/embedding_models/models.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/language_models/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/language_models/base.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/language_models/utils.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/mytypes.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/agent_chats.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/code-parsing.md +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/code_parser.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/json.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/para_sentence_split.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/parser.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/pdf_parser.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/table_loader.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/url_loader.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/url_loader_cookies.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/urls.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/parsing/utils.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/prompts/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/prompts/dialog.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/prompts/prompts_config.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/prompts/transforms.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/scripts/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/constants.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/docker.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/llms/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/llms/strings.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/logging.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/output/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/output/printing.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/system.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/web/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/web/login.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/utils/web/selenium_login.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/vector_store/__init__.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/vector_store/base.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/vector_store/chromadb.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/vector_store/qdrant_cloud.py +0 -0
- {langroid-0.1.31 → langroid-0.1.33}/langroid/vector_store/qdrantdb.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.1
|
2
2
|
Name: langroid
|
3
|
-
Version: 0.1.
|
3
|
+
Version: 0.1.33
|
4
4
|
Summary: Harness LLMs with Multi-Agent Programming
|
5
5
|
License: MIT
|
6
6
|
Author: Prasad Chalasani
|
@@ -154,7 +154,8 @@ Here is what it looks like in action:
|
|
154
154
|
Agents with specific skills, wrap them in Tasks, and combine tasks in a flexible way.
|
155
155
|
- **LLM Support**: Langroid supports OpenAI LLMs including GPT-3.5-Turbo,
|
156
156
|
GPT-4-0613
|
157
|
-
- **Caching of LLM
|
157
|
+
- **Caching of LLM responses:** Langroid supports [Redis](https://redis.com/try-free/) and
|
158
|
+
[Momento](https://www.gomomento.com/) to cache LLM responses.
|
158
159
|
- **Vector-stores**: [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) are currently supported.
|
159
160
|
Vector stores allow for Retrieval-Augmented-Generation (RAG).
|
160
161
|
- **Grounding and source-citation:** Access to external documents via vector-stores
|
@@ -226,14 +227,16 @@ All of the below are optional and not strictly needed to run any of the examples
|
|
226
227
|
If you skip setting up these, Langroid will use Qdrant in local-storage mode.
|
227
228
|
Alternatively [Chroma](https://docs.trychroma.com/) is also currently supported.
|
228
229
|
We use the local-storage version of Chroma, so there is no need for an API key.
|
230
|
+
Langroid uses Qdrant by default.
|
229
231
|
- **Redis** Password, host, port: This is optional, and only needed to cache LLM API responses
|
230
232
|
using Redis Cloud. Redis [offers](https://redis.com/try-free/) a free 30MB Redis account
|
231
233
|
which is more than sufficient to try out Langroid and even beyond.
|
232
234
|
If you don't set up these, Langroid will use a pure-python
|
233
235
|
Redis in-memory cache via the [Fakeredis](https://fakeredis.readthedocs.io/en/latest/) library.
|
234
236
|
- **Momento** Serverless Caching of LLM API responses (as an alternative to Redis).
|
235
|
-
To use Momento instead of Redis
|
236
|
-
|
237
|
+
To use Momento instead of Redis:
|
238
|
+
- enter your Momento Token in the `.env` file, as the value of `MOMENTO_AUTH_TOKEN` (see example file below),
|
239
|
+
- in the `.env` file set `CACHE_TYPE=momento` (instead of `CACHE_TYPE=redis` which is the default).
|
237
240
|
- **GitHub** Personal Access Token (required for apps that need to analyze git
|
238
241
|
repos; token-based API calls are less rate-limited). See this
|
239
242
|
[GitHub page](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).
|
@@ -242,6 +245,7 @@ If you add all of these optional variables, your `.env` file should look like th
|
|
242
245
|
```bash
|
243
246
|
OPENAI_API_KEY=your-key-here-without-quotes
|
244
247
|
GITHUB_ACCESS_TOKEN=your-personal-access-token-no-quotes
|
248
|
+
CACHE_TYPE=redis # or momento
|
245
249
|
REDIS_PASSWORD=your-redis-password-no-quotes
|
246
250
|
REDIS_HOST=your-redis-hostname-no-quotes
|
247
251
|
REDIS_PORT=your-redis-port-no-quotes
|
@@ -94,7 +94,8 @@ Here is what it looks like in action:
|
|
94
94
|
Agents with specific skills, wrap them in Tasks, and combine tasks in a flexible way.
|
95
95
|
- **LLM Support**: Langroid supports OpenAI LLMs including GPT-3.5-Turbo,
|
96
96
|
GPT-4-0613
|
97
|
-
- **Caching of LLM
|
97
|
+
- **Caching of LLM responses:** Langroid supports [Redis](https://redis.com/try-free/) and
|
98
|
+
[Momento](https://www.gomomento.com/) to cache LLM responses.
|
98
99
|
- **Vector-stores**: [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) are currently supported.
|
99
100
|
Vector stores allow for Retrieval-Augmented-Generation (RAG).
|
100
101
|
- **Grounding and source-citation:** Access to external documents via vector-stores
|
@@ -166,14 +167,16 @@ All of the below are optional and not strictly needed to run any of the examples
|
|
166
167
|
If you skip setting up these, Langroid will use Qdrant in local-storage mode.
|
167
168
|
Alternatively [Chroma](https://docs.trychroma.com/) is also currently supported.
|
168
169
|
We use the local-storage version of Chroma, so there is no need for an API key.
|
170
|
+
Langroid uses Qdrant by default.
|
169
171
|
- **Redis** Password, host, port: This is optional, and only needed to cache LLM API responses
|
170
172
|
using Redis Cloud. Redis [offers](https://redis.com/try-free/) a free 30MB Redis account
|
171
173
|
which is more than sufficient to try out Langroid and even beyond.
|
172
174
|
If you don't set up these, Langroid will use a pure-python
|
173
175
|
Redis in-memory cache via the [Fakeredis](https://fakeredis.readthedocs.io/en/latest/) library.
|
174
176
|
- **Momento** Serverless Caching of LLM API responses (as an alternative to Redis).
|
175
|
-
To use Momento instead of Redis
|
176
|
-
|
177
|
+
To use Momento instead of Redis:
|
178
|
+
- enter your Momento Token in the `.env` file, as the value of `MOMENTO_AUTH_TOKEN` (see example file below),
|
179
|
+
- in the `.env` file set `CACHE_TYPE=momento` (instead of `CACHE_TYPE=redis` which is the default).
|
177
180
|
- **GitHub** Personal Access Token (required for apps that need to analyze git
|
178
181
|
repos; token-based API calls are less rate-limited). See this
|
179
182
|
[GitHub page](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).
|
@@ -182,6 +185,7 @@ If you add all of these optional variables, your `.env` file should look like th
|
|
182
185
|
```bash
|
183
186
|
OPENAI_API_KEY=your-key-here-without-quotes
|
184
187
|
GITHUB_ACCESS_TOKEN=your-personal-access-token-no-quotes
|
188
|
+
CACHE_TYPE=redis # or momento
|
185
189
|
REDIS_PASSWORD=your-redis-password-no-quotes
|
186
190
|
REDIS_HOST=your-redis-hostname-no-quotes
|
187
191
|
REDIS_PORT=your-redis-port-no-quotes
|
@@ -177,7 +177,7 @@ class RetrieverAgent(DocChatAgent, ABC):
|
|
177
177
|
list of Document objects
|
178
178
|
"""
|
179
179
|
doc_contents = "\n\n".join(
|
180
|
-
[f"DOC: ID={d.id()},
|
180
|
+
[f"DOC: ID={d.id()}, CONTENT: {d.content}" for d in docs]
|
181
181
|
)
|
182
182
|
prompt = f"""
|
183
183
|
Given the following QUERY:
|
@@ -186,8 +186,11 @@ class RetrieverAgent(DocChatAgent, ABC):
|
|
186
186
|
{doc_contents}
|
187
187
|
|
188
188
|
Find at most {self.config.n_matches} DOCs that are most relevant to the QUERY.
|
189
|
-
Return your as a sequence of DOC IDS ONLY, for example:
|
189
|
+
Return your answer as a sequence of DOC IDS ONLY, for example:
|
190
190
|
"id1 id2 id3..."
|
191
|
+
If there are no relevant docs, simply say {NO_ANSWER}.
|
192
|
+
Even if there is only one relevant doc, return it as a single ID.
|
193
|
+
Do not give any explanations or justifications.
|
191
194
|
"""
|
192
195
|
default_response = Document(
|
193
196
|
content=NO_ANSWER,
|
@@ -61,6 +61,7 @@ class Task:
|
|
61
61
|
user_message: str = "",
|
62
62
|
restart: bool = False,
|
63
63
|
default_human_response: Optional[str] = None,
|
64
|
+
interactive: bool = True,
|
64
65
|
only_user_quits_root: bool = True,
|
65
66
|
erase_substeps: bool = False,
|
66
67
|
):
|
@@ -84,6 +85,9 @@ class Task:
|
|
84
85
|
restart (bool): if true, resets the agent's message history
|
85
86
|
default_human_response (str): default response from user; useful for
|
86
87
|
testing, to avoid interactive input from user.
|
88
|
+
interactive (bool): if true, wait for human input after each non-human
|
89
|
+
response (prevents infinite loop of non-human responses).
|
90
|
+
Default is true. If false, then `default_human_response` is set to ""
|
87
91
|
only_user_quits_root (bool): if true, only user can quit the root task.
|
88
92
|
erase_substeps (bool): if true, when task completes, erase intermediate
|
89
93
|
conversation with subtasks from this agent's `message_history`, and also
|
@@ -111,6 +115,9 @@ class Task:
|
|
111
115
|
self.agent = agent
|
112
116
|
self.name = name or agent.config.name
|
113
117
|
self.default_human_response = default_human_response
|
118
|
+
self.interactive = interactive
|
119
|
+
if not interactive:
|
120
|
+
self.default_human_response = ""
|
114
121
|
if default_human_response is not None:
|
115
122
|
self.agent.default_human_response = default_human_response
|
116
123
|
self.only_user_quits_root = only_user_quits_root
|
@@ -15,7 +15,7 @@ logger = logging.getLogger(__name__)
|
|
15
15
|
|
16
16
|
|
17
17
|
class MomentoCacheConfig(BaseModel):
|
18
|
-
"""Configuration model for
|
18
|
+
"""Configuration model for Momento Cache."""
|
19
19
|
|
20
20
|
ttl: int = 60 * 60 * 24 * 7 # 1 week
|
21
21
|
cachename: str = "langroid_momento_cache"
|
@@ -224,7 +224,7 @@ class OpenAIGPT(LanguageModel):
|
|
224
224
|
hashed_key = hashlib.sha256(raw_key.encode()).hexdigest()
|
225
225
|
|
226
226
|
if not settings.cache:
|
227
|
-
# when
|
227
|
+
# when caching disabled, return the hashed_key and none result
|
228
228
|
return hashed_key, None
|
229
229
|
# Try to get the result from the cache
|
230
230
|
return hashed_key, self.cache.retrieve(hashed_key)
|
@@ -96,7 +96,7 @@ class RepoLoader:
|
|
96
96
|
json.dump({"junk": "ignore"}, f)
|
97
97
|
with open(self.log_file, "r") as f:
|
98
98
|
log = json.load(f)
|
99
|
-
if self.url in log:
|
99
|
+
if self.url in log and os.path.exists(log[self.url]):
|
100
100
|
logger.info(f"Repo Already downloaded in {log[self.url]}")
|
101
101
|
self.clone_path = log[self.url]
|
102
102
|
|
@@ -55,7 +55,15 @@ SUMMARY_ANSWER_PROMPT_GPT4 = f"""
|
|
55
55
|
and even if the answer contradicts other parts of the document. The only
|
56
56
|
important thing is that your answer is consistent with and supported by the
|
57
57
|
extracts. Compose your complete answer and cite all supporting sources on a
|
58
|
-
separate separate line as
|
58
|
+
separate separate line as follows. For each SOURCE, (a) show the source name,
|
59
|
+
and (b) the exact EXTRACT from the source that supports your answer.
|
60
|
+
DO NOT SHOW THE FULL EXTRACT; only show the FIRST 3 words and LAST 3 words.
|
61
|
+
For example:
|
62
|
+
SOURCE: https://en.wikipedia.org/wiki/Tree
|
63
|
+
EXTRACTS: "The tree species ... oak, maple, and birch."
|
64
|
+
|
65
|
+
SOURCE: https://en.wikipedia.org/wiki/Oak
|
66
|
+
EXTRACTS: "The oak trees ... longevity and strength."
|
59
67
|
|
60
68
|
{{extracts}}
|
61
69
|
|
@@ -1,9 +1,12 @@
|
|
1
1
|
from typing import List
|
2
2
|
|
3
|
+
from dotenv import load_dotenv
|
3
4
|
from pydantic import BaseSettings
|
4
5
|
|
5
6
|
|
6
7
|
class Settings(BaseSettings):
|
8
|
+
# NOTE all of these can be overridden in your .env file with upper-case names,
|
9
|
+
# for example CACHE_TYPE=momento
|
7
10
|
debug: bool = False # show debug messages?
|
8
11
|
progress: bool = False # show progress spinners/bars?
|
9
12
|
stream: bool = True # stream output?
|
@@ -17,6 +20,7 @@ class Settings(BaseSettings):
|
|
17
20
|
extra = "forbid"
|
18
21
|
|
19
22
|
|
23
|
+
load_dotenv() # get settings from .env file
|
20
24
|
settings = Settings()
|
21
25
|
|
22
26
|
|
langroid-0.1.33/setup.py
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
from setuptools import setup
|
3
|
+
|
4
|
+
packages = \
|
5
|
+
['langroid',
|
6
|
+
'langroid.agent',
|
7
|
+
'langroid.agent.special',
|
8
|
+
'langroid.cachedb',
|
9
|
+
'langroid.embedding_models',
|
10
|
+
'langroid.language_models',
|
11
|
+
'langroid.parsing',
|
12
|
+
'langroid.prompts',
|
13
|
+
'langroid.scripts',
|
14
|
+
'langroid.utils',
|
15
|
+
'langroid.utils.llms',
|
16
|
+
'langroid.utils.output',
|
17
|
+
'langroid.utils.web',
|
18
|
+
'langroid.vector_store']
|
19
|
+
|
20
|
+
package_data = \
|
21
|
+
{'': ['*']}
|
22
|
+
|
23
|
+
install_requires = \
|
24
|
+
['autopep8>=2.0.2,<3.0.0',
|
25
|
+
'black[jupyter]>=23.3.0,<24.0.0',
|
26
|
+
'bs4>=0.0.1,<0.0.2',
|
27
|
+
'chromadb>=0.3.21,<0.4.0',
|
28
|
+
'colorlog>=6.7.0,<7.0.0',
|
29
|
+
'faker>=18.9.0,<19.0.0',
|
30
|
+
'fakeredis>=2.12.1,<3.0.0',
|
31
|
+
'fire>=0.5.0,<0.6.0',
|
32
|
+
'flake8>=6.0.0,<7.0.0',
|
33
|
+
'halo>=0.0.31,<0.0.32',
|
34
|
+
'mkdocs-awesome-pages-plugin>=2.8.0,<3.0.0',
|
35
|
+
'mkdocs-gen-files>=0.4.0,<0.5.0',
|
36
|
+
'mkdocs-jupyter>=0.24.1,<0.25.0',
|
37
|
+
'mkdocs-literate-nav>=0.6.0,<0.7.0',
|
38
|
+
'mkdocs-material>=9.1.5,<10.0.0',
|
39
|
+
'mkdocs-section-index>=0.3.5,<0.4.0',
|
40
|
+
'mkdocs>=1.4.2,<2.0.0',
|
41
|
+
'mkdocstrings[python]>=0.21.2,<0.22.0',
|
42
|
+
'momento>=1.7.0,<2.0.0',
|
43
|
+
'mypy>=1.2.0,<2.0.0',
|
44
|
+
'nltk>=3.8.1,<4.0.0',
|
45
|
+
'openai>=0.27.5,<0.28.0',
|
46
|
+
'pandas>=2.0.3,<3.0.0',
|
47
|
+
'pre-commit>=3.3.2,<4.0.0',
|
48
|
+
'pydantic==1.10.11',
|
49
|
+
'pygithub>=1.58.1,<2.0.0',
|
50
|
+
'pygments>=2.15.1,<3.0.0',
|
51
|
+
'pyparsing>=3.0.9,<4.0.0',
|
52
|
+
'pypdf>=3.12.2,<4.0.0',
|
53
|
+
'python-dotenv>=1.0.0,<2.0.0',
|
54
|
+
'qdrant-client>=1.3.1,<2.0.0',
|
55
|
+
'redis>=4.5.5,<5.0.0',
|
56
|
+
'requests-oauthlib>=1.3.1,<2.0.0',
|
57
|
+
'requests>=2.31.0,<3.0.0',
|
58
|
+
'rich>=13.3.4,<14.0.0',
|
59
|
+
'ruff>=0.0.270,<0.0.271',
|
60
|
+
'tiktoken>=0.3.3,<0.4.0',
|
61
|
+
'trafilatura>=1.5.0,<2.0.0',
|
62
|
+
'typer>=0.7.0,<0.8.0',
|
63
|
+
'types-redis>=4.5.5.2,<5.0.0.0',
|
64
|
+
'types-requests>=2.31.0.1,<3.0.0.0',
|
65
|
+
'wget>=3.2,<4.0']
|
66
|
+
|
67
|
+
extras_require = \
|
68
|
+
{'hf-embeddings': ['sentence-transformers==2.2.2', 'torch==2.0.0']}
|
69
|
+
|
70
|
+
setup_kwargs = {
|
71
|
+
'name': 'langroid',
|
72
|
+
'version': '0.1.33',
|
73
|
+
'description': 'Harness LLMs with Multi-Agent Programming',
|
74
|
+
'long_description': '<div align="center">\n <img src="docs/assets/langroid-card-lambda-ossem-rust-1200-630.png" alt="Logo" \n width="400" align="center">\n</div>\n\n<div align="center">\n\n[](https://github.com/langroid/langroid/actions/workflows/pytest.yml)\n[](https://codecov.io/gh/langroid/langroid)\n[](https://github.com/langroid/langroid/actions/workflows/validate.yml)\n[](https://github.com/langroid/langroid/actions/workflows/mkdocs-deploy.yml)\n[](https://langroid.github.io/langroid)\n[](https://discord.gg/ZU36McDgDs)\n\n\n</div>\n\n<h3 align="center">\n <a target="_blank" \n href="https://langroid.github.io/langroid/" rel="dofollow">\n <strong>Documentation</strong></a>\n ·\n <a target="_blank" href="https://github.com/langroid/langroid-examples" rel="dofollow">\n <strong>Examples Repo</strong></a>\n ·\n <a target="_blank" href="https://discord.gg/ZU36McDgDs" rel="dofollow">\n <strong>Discord</strong></a>\n ·\n <a target="_blank" href="./CONTRIBUTING.md" rel="dofollow">\n <strong>Contributing</strong></a>\n\n <br />\n</h3>\n\n`Langroid` is an intuitive, lightweight, extensible and principled\nPython framework to easily build LLM-powered applications. \nYou set up Agents, equip them with optional components (LLM, \nvector-store and methods), assign them tasks, and have them \ncollaboratively solve a problem by exchanging messages. \nThis Multi-Agent paradigm is inspired by the\n[Actor Framework](https://en.wikipedia.org/wiki/Actor_model)\n(but you do not need to know anything about this!).\nWe welcome contributions -- See the [contributions](./CONTRIBUTING.md) document\nfor ideas on what to contribute.\n\n**Questions, Feedback, Ideas? Join us on [Discord](https://discord.gg/ZU36McDgDs)!**\n\n<details>\n<summary> <b>:fire: Updates/Releases</b></summary>\n\n- **0.1.30 (July 2023)**: Added [`TableChatAgent`](langroid/agent/special/table_chat_agent.py) to \n [chat](examples/data-qa/table_chat.py) with tabular datasets (dataframes, files, URLs): LLM generates Pandas code,\n and code is executed via using Langroid tool/function-call mechanism. \n- **(July 2023)** Demo: 3-agent system for Audience [Targeting](https://langroid.github.io/langroid/demos/targeting/audience-targeting/).\n- **0.1.27 (July 2023)**: Added [support](langroid/cachedb/momento_cachedb.py) \n for [Momento Serverless Cache](https://www.gomomento.com/) as an alternative to Redis.\n- **0.1.24 (July 2023)**: [`DocChatAgent`](langroid/agent/special/doc_chat_agent.py) \n now [accepts](langroid/parsing/pdf_parser.py) PDF files or URLs.\n\n</details>\n\n# :rocket: Demo\nSuppose you want to extract structured information about the key terms \nof a commercial lease document. You can easily do this with Langroid using a two-agent system,\nas we show in the [langroid-examples](https://github.com/langroid/langroid-examples/blob/main/examples/docqa/chat_multi_extract.py) repo.\nThe demo showcases just a few of the many features of Langroid, such as:\n- Multi-agent collaboration: `LeaseExtractor` is in charge of the task, and its LLM (GPT4) generates questions \nto be answered by the `DocAgent`.\n- Retrieval augmented question-answering, with **source-citation**: `DocAgent` LLM (GPT4) uses retrieval from a vector-store to \nanswer the `LeaseExtractor`\'s questions, cites the specific excerpt supporting the answer. \n- Function-calling (also known as tool/plugin): When it has all the information it \nneeds, the `LeaseExtractor` LLM presents the information in a structured \nformat using a Function-call. \n\nHere is what it looks like in action:\n\n\n\n\n# :zap: Highlights\n\n- **Agents as first-class citizens:** The [Agent](https://langroid.github.io/langroid/reference/agent/base/#langroid.agent.base.Agent) class encapsulates LLM conversation state,\n and optionally a vector-store and tools. Agents are a core abstraction in Langroid;\n Agents act as _message transformers_, and by default provide 3 _responder_ methods, one corresponding to each entity: LLM, Agent, User.\n- **Tasks:** A [Task](https://langroid.github.io/langroid/reference/agent/task/) class wraps an Agent, and gives the agent instructions (or roles, or goals), \n manages iteration over an Agent\'s responder methods, \n and orchestrates multi-agent interactions via hierarchical, recursive\n task-delegation. The `Task.run()` method has the same \n type-signature as an Agent\'s responder\'s methods, and this is key to how \n a task of an agent can delegate to other sub-tasks: from the point of view of a Task,\n sub-tasks are simply additional responders, to be used in a round-robin fashion \n after the agent\'s own responders.\n- **Modularity, Reusabilily, Loose coupling:** The `Agent` and `Task` abstractions allow users to design\n Agents with specific skills, wrap them in Tasks, and combine tasks in a flexible way.\n- **LLM Support**: Langroid supports OpenAI LLMs including GPT-3.5-Turbo,\n GPT-4-0613\n- **Caching of LLM responses:** Langroid supports [Redis](https://redis.com/try-free/) and \n [Momento](https://www.gomomento.com/) to cache LLM responses.\n- **Vector-stores**: [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) are currently supported.\n Vector stores allow for Retrieval-Augmented-Generation (RAG).\n- **Grounding and source-citation:** Access to external documents via vector-stores \n allows for grounding and source-citation.\n- **Observability, Logging, Lineage:** Langroid generates detailed logs of multi-agent interactions and\n maintains provenance/lineage of messages, so that you can trace back\n the origin of a message.\n- **Tools/Plugins/Function-calling**: Langroid supports OpenAI\'s recently\n released [function calling](https://platform.openai.com/docs/guides/gpt/function-calling)\n feature. In addition, Langroid has its own native equivalent, which we\n call **tools** (also known as "plugins" in other contexts). Function\n calling and tools have the same developer-facing interface, implemented\n using [Pydantic](https://docs.pydantic.dev/latest/),\n which makes it very easy to define tools/functions and enable agents\n to use them. Benefits of using Pydantic are that you never have to write\n complex JSON specs for function calling, and when the LLM\n hallucinates malformed JSON, the Pydantic error message is sent back to\n the LLM so it can fix it!\n\n--- \n\n# :gear: Installation and Setup\n\n### Install `langroid`\nLangroid requires Python 3.11+. We recommend using a virtual environment.\nUse `pip` to install `langroid` (from PyPi) to your virtual environment:\n```bash\npip install langroid\n```\nThe core Langroid package lets you use OpenAI Embeddings models via their API. \nIf you instead want to use the `all-MiniLM-L6-v2` embeddings model\nfrom from HuggingFace, install Langroid like this:\n```bash\npip install langroid[hf-embeddings]\n```\nNote that this will install `torch` and `sentence-transformers` libraries.\n\n### Set up environment variables (API keys, etc)\n\nTo get started, all you need is an OpenAI API Key.\nIf you don\'t have one, see [this OpenAI Page](https://help.openai.com/en/collections/3675940-getting-started-with-openai-api).\nCurrently only OpenAI models are supported. Others will be added later\n(Pull Requests welcome!).\n\nIn the root of the repo, copy the `.env-template` file to a new file `.env`: \n```bash\ncp .env-template .env\n```\nThen insert your OpenAI API Key. \nYour `.env` file should look like this:\n```bash\nOPENAI_API_KEY=your-key-here-without-quotes\n````\n\nAlternatively, you can set this as an environment variable in your shell\n(you will need to do this every time you open a new shell):\n```bash\nexport OPENAI_API_KEY=your-key-here-without-quotes\n```\n\n\n<details>\n<summary><b>Optional Setup Instructions (click to expand) </b></summary>\n\nAll of the below are optional and not strictly needed to run any of the examples.\n\n- **Qdrant** Vector Store API Key, URL. This is only required if you want to use Qdrant cloud.\n You can sign up for a free 1GB account at [Qdrant cloud](https://cloud.qdrant.io).\n If you skip setting up these, Langroid will use Qdrant in local-storage mode.\n Alternatively [Chroma](https://docs.trychroma.com/) is also currently supported. \n We use the local-storage version of Chroma, so there is no need for an API key.\n Langroid uses Qdrant by default.\n- **Redis** Password, host, port: This is optional, and only needed to cache LLM API responses\n using Redis Cloud. Redis [offers](https://redis.com/try-free/) a free 30MB Redis account\n which is more than sufficient to try out Langroid and even beyond.\n If you don\'t set up these, Langroid will use a pure-python \n Redis in-memory cache via the [Fakeredis](https://fakeredis.readthedocs.io/en/latest/) library.\n- **Momento** Serverless Caching of LLM API responses (as an alternative to Redis). \n To use Momento instead of Redis:\n - enter your Momento Token in the `.env` file, as the value of `MOMENTO_AUTH_TOKEN` (see example file below),\n - in the `.env` file set `CACHE_TYPE=momento` (instead of `CACHE_TYPE=redis` which is the default).\n- **GitHub** Personal Access Token (required for apps that need to analyze git\n repos; token-based API calls are less rate-limited). See this\n [GitHub page](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).\n\nIf you add all of these optional variables, your `.env` file should look like this:\n```bash\nOPENAI_API_KEY=your-key-here-without-quotes\nGITHUB_ACCESS_TOKEN=your-personal-access-token-no-quotes\nCACHE_TYPE=redis # or momento\nREDIS_PASSWORD=your-redis-password-no-quotes\nREDIS_HOST=your-redis-hostname-no-quotes\nREDIS_PORT=your-redis-port-no-quotes\nMOMENTO_AUTH_TOKEN=your-momento-token-no-quotes # instead of REDIS* variables\nQDRANT_API_KEY=your-key\nQDRANT_API_URL=https://your.url.here:6333 # note port number must be included\n```\n</details>\n\n---\n\n# :tada: Usage Examples\n\nThese are quick teasers to give a glimpse of what you can do with Langroid\nand how your code would look. \n\n:warning: The code snippets below are intended to give a flavor of the code\nand they are **not** complete runnable examples! For that we encourage you to \nconsult the [`langroid-examples`](https://github.com/langroid/langroid-examples) \nrepository.\n\n:information_source: The various LLM prompts and instructions in Langroid\nhave been tested to work well with GPT4.\nSwitching to GPT3.5-Turbo is easy via a config flag\n(e.g., `cfg = OpenAIGPTConfig(chat_model=OpenAIChatModel.GPT3_5_TURBO)`),\nand may suffice for some applications, but in general you may see inferior results.\n\n\n:book: Also see the\n[`Getting Started Guide`](https://langroid.github.io/langroid/quick-start/)\nfor a detailed tutorial.\n\nClick to expand any of the code examples below:\n\n<details>\n<summary> <b> Direct interaction with OpenAI LLM </b> </summary>\n\n```python\nfrom langroid.language_models.openai_gpt import ( \n OpenAIGPTConfig, OpenAIChatModel, OpenAIGPT,\n)\nfrom langroid.language_models.base import LLMMessage, Role\n\ncfg = OpenAIGPTConfig(chat_model=OpenAIChatModel.GPT4)\n\nmdl = OpenAIGPT(cfg)\n\nmessages = [\n LLMMessage(content="You are a helpful assistant", role=Role.SYSTEM), \n LLMMessage(content="What is the capital of Ontario?", role=Role.USER),\n]\nresponse = mdl.chat(messages, max_tokens=200)\nprint(response.message)\n```\n</details>\n\n<details>\n<summary> <b> Define an agent, set up a task, and run it </b> </summary>\n\n```python\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\n\nconfig = ChatAgentConfig(\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=None, # no vector store\n)\nagent = ChatAgent(config)\n# get response from agent\'s LLM, and put this in an interactive loop...\n# answer = agent.llm_response("What is the capital of Ontario?")\n # ... OR instead, set up a task (which has a built-in loop) and run it\ntask = Task(agent, name="Bot") \ntask.run() # ... a loop seeking response from LLM or User at each turn\n```\n</details>\n\n<details>\n<summary><b> Three communicating agents </b></summary>\n\n```python\n\nA toy numbers game, where when given a number `n`:\n- `repeater_agent`\'s LLM simply returns `n`,\n- `even_agent`\'s LLM returns `n/2` if `n` is even, else says "DO-NOT-KNOW"\n- `odd_agent`\'s LLM returns `3*n+1` if `n` is odd, else says "DO-NOT-KNOW"\n\nFirst define the 3 agents, and set up their tasks with instructions:\n\n```python\nfrom langroid.utils.constants import NO_ANSWER\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\nconfig = ChatAgentConfig(\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb = None,\n)\nrepeater_agent = ChatAgent(config)\nrepeater_task = Task(\n repeater_agent,\n name = "Repeater",\n system_message="""\n Your job is to repeat whatever number you receive.\n """,\n llm_delegate=True, # LLM takes charge of task\n single_round=False, \n)\neven_agent = ChatAgent(config)\neven_task = Task(\n even_agent,\n name = "EvenHandler",\n system_message=f"""\n You will be given a number. \n If it is even, divide by 2 and say the result, nothing else.\n If it is odd, say {NO_ANSWER}\n """,\n single_round=True, # task done after 1 step() with valid response\n)\n\nodd_agent = ChatAgent(config)\nodd_task = Task(\n odd_agent,\n name = "OddHandler",\n system_message=f"""\n You will be given a number n. \n If it is odd, return (n*3+1), say nothing else. \n If it is even, say {NO_ANSWER}\n """,\n single_round=True, # task done after 1 step() with valid response\n)\n```\nThen add the `even_task` and `odd_task` as sub-tasks of `repeater_task`, \nand run the `repeater_task`, kicking it off with a number as input:\n```python\nrepeater_task.add_sub_task([even_task, odd_task])\nrepeater_task.run("3")\n```\n\n</details>\n\n<details>\n<summary><b> Simple Tool/Function-calling example </b></summary>\n\nLangroid leverages Pydantic to support OpenAI\'s\n[Function-calling API](https://platform.openai.com/docs/guides/gpt/function-calling)\nas well as its own native tools. The benefits are that you don\'t have to write\nany JSON to specify the schema, and also if the LLM hallucinates a malformed\ntool syntax, Langroid sends the Pydantic validation error (suitiably sanitized) \nto the LLM so it can fix it!\n\nSimple example: Say the agent has a secret list of numbers, \nand we want the LLM to find the smallest number in the list. \nWe want to give the LLM a `probe` tool/function which takes a\nsingle number `n` as argument. The tool handler method in the agent\nreturns how many numbers in its list are at most `n`.\n\nFirst define the tool using Langroid\'s `ToolMessage` class:\n\n\n```python\nfrom langroid.agent.tool_message import ToolMessage\nclass ProbeTool(ToolMessage):\n request: str = "probe" # specifies which agent method handles this tool\n purpose: str = """\n To find how many numbers in my list are less than or equal to \n the <number> you specify.\n """ # description used to instruct the LLM on when/how to use the tool\n number: int # required argument to the tool\n```\n\nThen define a `SpyGameAgent` as a subclass of `ChatAgent`, \nwith a method `probe` that handles this tool:\n\n```python\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nclass SpyGameAgent(ChatAgent):\n def __init__(self, config: ChatAgentConfig):\n super().__init__(config)\n self.numbers = [3, 4, 8, 11, 15, 25, 40, 80, 90]\n\n def probe(self, msg: ProbeTool) -> str:\n # return how many numbers in self.numbers are less or equal to msg.number\n return str(len([n for n in self.numbers if n <= msg.number]))\n```\n\nWe then instantiate the agent and enable it to use and respond to the tool:\n\n```python\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\nspy_game_agent = SpyGameAgent(\n ChatAgentConfig(\n name="Spy",\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=None,\n use_tools=False, # don\'t use Langroid native tool\n use_functions_api=True, # use OpenAI function-call API\n )\n)\nspy_game_agent.enable_message(ProbeTool)\n```\n\nFor a full working example see the\n[chat-agent-tool.py](https://github.com/langroid/langroid-examples/blob/main/examples/quick-start/chat-agent-tool.py)\nscript in the `langroid-examples` repo.\n</details>\n\n<details>\n<summary> <b>Tool/Function-calling to extract structured information from text </b> </summary>\n\nSuppose you want an agent to extract \nthe key terms of a lease, from a lease document, as a nested JSON structure.\nFirst define the desired structure via Pydantic models:\n\n```python\nfrom pydantic import BaseModel\nclass LeasePeriod(BaseModel):\n start_date: str\n end_date: str\n\n\nclass LeaseFinancials(BaseModel):\n monthly_rent: str\n deposit: str\n\nclass Lease(BaseModel):\n period: LeasePeriod\n financials: LeaseFinancials\n address: str\n```\n\nThen define the `LeaseMessage` tool as a subclass of Langroid\'s `ToolMessage`.\nNote the tool has a required argument `terms` of type `Lease`:\n\n```python\nclass LeaseMessage(ToolMessage):\n request: str = "lease_info"\n purpose: str = """\n Collect information about a Commercial Lease.\n """\n terms: Lease\n```\n\nThen define a `LeaseExtractorAgent` with a method `lease_info` that handles this tool,\ninstantiate the agent, and enable it to use and respond to this tool:\n\n```python\nclass LeaseExtractorAgent(ChatAgent):\n def lease_info(self, message: LeaseMessage) -> str:\n print(\n f"""\n DONE! Successfully extracted Lease Info:\n {message.terms}\n """\n )\n return json.dumps(message.terms.dict())\n \nlease_extractor_agent = LeaseExtractorAgent(\n ChatAgentConfig(\n llm=OpenAIGPTConfig(),\n use_functions_api=False,\n use_tools=True,\n )\n)\nlease_extractor_agent.enable_message(LeaseMessage)\n```\n\nSee the [`chat_multi_extract.py`](https://github.com/langroid/langroid-examples/blob/main/examples/docqa/chat_multi_extract.py)\nscript in the `langroid-examples` repo for a full working example.\n</details>\n\n<details>\n<summary><b> Chat with documents (file paths, URLs, etc) </b></summary>\n\nLangroid provides a specialized agent class `DocChatAgent` for this purpose.\nIt incorporates document sharding, embedding, storage in a vector-DB, \nand retrieval-augmented query-answer generation.\nUsing this class to chat with a collection of documents is easy.\nFirst create a `DocChatAgentConfig` instance, with a \n`doc_paths` field that specifies the documents to chat with.\n\n```python\nfrom langroid.agent.doc_chat_agent import DocChatAgentConfig\nconfig = DocChatAgentConfig(\n doc_paths = [\n "https://en.wikipedia.org/wiki/Language_model",\n "https://en.wikipedia.org/wiki/N-gram_language_model",\n "/path/to/my/notes-on-language-models.txt",\n ]\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=VectorStoreConfig(\n type="qdrant",\n ),\n)\n```\n\nThen instantiate the `DocChatAgent`, ingest the docs into the vector-store:\n\n```python\nagent = DocChatAgent(config)\nagent.ingest()\n```\nThen we can either ask the agent one-off questions,\n```python\nagent.chat("What is a language model?")\n```\nor wrap it in a `Task` and run an interactive loop with the user:\n```python\nfrom langroid.task import Task\ntask = Task(agent)\ntask.run()\n```\n\nSee full working scripts in the \n[`docqa`](https://github.com/langroid/langroid-examples/tree/main/examples/docqa)\nfolder of the `langroid-examples` repo.\n</details>\n\n<details>\n<summary><b> :fire: Chat with tabular data (file paths, URLs, dataframes) </b></summary>\n\nUsing Langroid you can set up a `TableChatAgent` with a dataset (file path, URL or dataframe),\nand query it. The Agent\'s LLM generates Pandas code to answer the query, \nvia function-calling (or tool/plugin), and the Agent\'s function-handling method\nexecutes the code and returns the answer.\n\nHere is how you can do this:\n\n```python\nfrom langroid.agent.special.table_chat_agent import TableChatAgent, TableChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\n```\n\nSet up a `TableChatAgent` for a data file, URL or dataframe\n(Ensure the data table has a header row; the delimiter/separator is auto-detected):\n```python\ndataset = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"\n# or dataset = "/path/to/my/data.csv"\n# or dataset = pd.read_csv("/path/to/my/data.csv")\nagent = TableChatAgent(\n config=TableChatAgentConfig(\n data=dataset, \n llm=OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n )\n)\n```\nSet up a task, and ask one-off questions like this: \n\n```python\ntask = Task(\n agent, \n name = "DataAssistant",\n default_human_response="", # to avoid waiting for user input\n)\nresult = task.run(\n "What is the average alcohol content of wines with a quality rating above 7?",\n turns=2 # return after user question, LLM fun-call/tool response, Agent code-exec result\n) \nprint(result.content)\n```\nOr alternatively, set up a task and run it in an interactive loop with the user:\n\n```python\ntask = Task(agent, name="DataAssistant")\ntask.run()\n``` \n\nFor a full working example see the \n[`table_chat.py`](https://github.com/langroid/langroid-examples/tree/main/examples/data-qa/table_chat.py)\nscript in the `langroid-examples` repo.\n\n\n</details>\n\n---\n\n# :heart: Thank you to our [supporters](https://github.com/langroid/langroid/stargazers)\n\nIf you like this repo, don\'t forget to leave a star :star: !\n\n# Contributors\n\n- Prasad Chalasani (IIT BTech/CS, CMU PhD/ML; Independent ML Consultant)\n- Somesh Jha (IIT BTech/CS, CMU PhD/CS; Professor of CS, U Wisc at Madison)\n- Mohannad Alhanahnah (Research Associate, U Wisc at Madison)\n- Ashish Hooda (IIT BTech/CS; PhD Candidate, U Wisc at Madison)\n\n',
|
75
|
+
'author': 'Prasad Chalasani',
|
76
|
+
'author_email': 'pchalasani@gmail.com',
|
77
|
+
'maintainer': 'None',
|
78
|
+
'maintainer_email': 'None',
|
79
|
+
'url': 'None',
|
80
|
+
'packages': packages,
|
81
|
+
'package_data': package_data,
|
82
|
+
'install_requires': install_requires,
|
83
|
+
'extras_require': extras_require,
|
84
|
+
'python_requires': '>=3.8.1,<3.12',
|
85
|
+
}
|
86
|
+
|
87
|
+
|
88
|
+
setup(**setup_kwargs)
|
langroid-0.1.31/setup.py
DELETED
@@ -1,88 +0,0 @@
|
|
1
|
-
# -*- coding: utf-8 -*-
|
2
|
-
from setuptools import setup
|
3
|
-
|
4
|
-
packages = \
|
5
|
-
['langroid',
|
6
|
-
'langroid.agent',
|
7
|
-
'langroid.agent.special',
|
8
|
-
'langroid.cachedb',
|
9
|
-
'langroid.embedding_models',
|
10
|
-
'langroid.language_models',
|
11
|
-
'langroid.parsing',
|
12
|
-
'langroid.prompts',
|
13
|
-
'langroid.scripts',
|
14
|
-
'langroid.utils',
|
15
|
-
'langroid.utils.llms',
|
16
|
-
'langroid.utils.output',
|
17
|
-
'langroid.utils.web',
|
18
|
-
'langroid.vector_store']
|
19
|
-
|
20
|
-
package_data = \
|
21
|
-
{'': ['*']}
|
22
|
-
|
23
|
-
install_requires = \
|
24
|
-
['autopep8>=2.0.2,<3.0.0',
|
25
|
-
'black[jupyter]>=23.3.0,<24.0.0',
|
26
|
-
'bs4>=0.0.1,<0.0.2',
|
27
|
-
'chromadb>=0.3.21,<0.4.0',
|
28
|
-
'colorlog>=6.7.0,<7.0.0',
|
29
|
-
'faker>=18.9.0,<19.0.0',
|
30
|
-
'fakeredis>=2.12.1,<3.0.0',
|
31
|
-
'fire>=0.5.0,<0.6.0',
|
32
|
-
'flake8>=6.0.0,<7.0.0',
|
33
|
-
'halo>=0.0.31,<0.0.32',
|
34
|
-
'mkdocs-awesome-pages-plugin>=2.8.0,<3.0.0',
|
35
|
-
'mkdocs-gen-files>=0.4.0,<0.5.0',
|
36
|
-
'mkdocs-jupyter>=0.24.1,<0.25.0',
|
37
|
-
'mkdocs-literate-nav>=0.6.0,<0.7.0',
|
38
|
-
'mkdocs-material>=9.1.5,<10.0.0',
|
39
|
-
'mkdocs-section-index>=0.3.5,<0.4.0',
|
40
|
-
'mkdocs>=1.4.2,<2.0.0',
|
41
|
-
'mkdocstrings[python]>=0.21.2,<0.22.0',
|
42
|
-
'momento>=1.7.0,<2.0.0',
|
43
|
-
'mypy>=1.2.0,<2.0.0',
|
44
|
-
'nltk>=3.8.1,<4.0.0',
|
45
|
-
'openai>=0.27.5,<0.28.0',
|
46
|
-
'pandas>=2.0.3,<3.0.0',
|
47
|
-
'pre-commit>=3.3.2,<4.0.0',
|
48
|
-
'pydantic==1.10.11',
|
49
|
-
'pygithub>=1.58.1,<2.0.0',
|
50
|
-
'pygments>=2.15.1,<3.0.0',
|
51
|
-
'pyparsing>=3.0.9,<4.0.0',
|
52
|
-
'pypdf>=3.12.2,<4.0.0',
|
53
|
-
'python-dotenv>=1.0.0,<2.0.0',
|
54
|
-
'qdrant-client>=1.3.1,<2.0.0',
|
55
|
-
'redis>=4.5.5,<5.0.0',
|
56
|
-
'requests-oauthlib>=1.3.1,<2.0.0',
|
57
|
-
'requests>=2.31.0,<3.0.0',
|
58
|
-
'rich>=13.3.4,<14.0.0',
|
59
|
-
'ruff>=0.0.270,<0.0.271',
|
60
|
-
'tiktoken>=0.3.3,<0.4.0',
|
61
|
-
'trafilatura>=1.5.0,<2.0.0',
|
62
|
-
'typer>=0.7.0,<0.8.0',
|
63
|
-
'types-redis>=4.5.5.2,<5.0.0.0',
|
64
|
-
'types-requests>=2.31.0.1,<3.0.0.0',
|
65
|
-
'wget>=3.2,<4.0']
|
66
|
-
|
67
|
-
extras_require = \
|
68
|
-
{'hf-embeddings': ['sentence-transformers==2.2.2', 'torch==2.0.0']}
|
69
|
-
|
70
|
-
setup_kwargs = {
|
71
|
-
'name': 'langroid',
|
72
|
-
'version': '0.1.31',
|
73
|
-
'description': 'Harness LLMs with Multi-Agent Programming',
|
74
|
-
'long_description': '<div align="center">\n <img src="docs/assets/langroid-card-lambda-ossem-rust-1200-630.png" alt="Logo" \n width="400" align="center">\n</div>\n\n<div align="center">\n\n[](https://github.com/langroid/langroid/actions/workflows/pytest.yml)\n[](https://codecov.io/gh/langroid/langroid)\n[](https://github.com/langroid/langroid/actions/workflows/validate.yml)\n[](https://github.com/langroid/langroid/actions/workflows/mkdocs-deploy.yml)\n[](https://langroid.github.io/langroid)\n[](https://discord.gg/ZU36McDgDs)\n\n\n</div>\n\n<h3 align="center">\n <a target="_blank" \n href="https://langroid.github.io/langroid/" rel="dofollow">\n <strong>Documentation</strong></a>\n ·\n <a target="_blank" href="https://github.com/langroid/langroid-examples" rel="dofollow">\n <strong>Examples Repo</strong></a>\n ·\n <a target="_blank" href="https://discord.gg/ZU36McDgDs" rel="dofollow">\n <strong>Discord</strong></a>\n ·\n <a target="_blank" href="./CONTRIBUTING.md" rel="dofollow">\n <strong>Contributing</strong></a>\n\n <br />\n</h3>\n\n`Langroid` is an intuitive, lightweight, extensible and principled\nPython framework to easily build LLM-powered applications. \nYou set up Agents, equip them with optional components (LLM, \nvector-store and methods), assign them tasks, and have them \ncollaboratively solve a problem by exchanging messages. \nThis Multi-Agent paradigm is inspired by the\n[Actor Framework](https://en.wikipedia.org/wiki/Actor_model)\n(but you do not need to know anything about this!).\nWe welcome contributions -- See the [contributions](./CONTRIBUTING.md) document\nfor ideas on what to contribute.\n\n**Questions, Feedback, Ideas? Join us on [Discord](https://discord.gg/ZU36McDgDs)!**\n\n<details>\n<summary> <b>:fire: Updates/Releases</b></summary>\n\n- **0.1.30 (July 2023)**: Added [`TableChatAgent`](langroid/agent/special/table_chat_agent.py) to \n [chat](examples/data-qa/table_chat.py) with tabular datasets (dataframes, files, URLs): LLM generates Pandas code,\n and code is executed via using Langroid tool/function-call mechanism. \n- **(July 2023)** Demo: 3-agent system for Audience [Targeting](https://langroid.github.io/langroid/demos/targeting/audience-targeting/).\n- **0.1.27 (July 2023)**: Added [support](langroid/cachedb/momento_cachedb.py) \n for [Momento Serverless Cache](https://www.gomomento.com/) as an alternative to Redis.\n- **0.1.24 (July 2023)**: [`DocChatAgent`](langroid/agent/special/doc_chat_agent.py) \n now [accepts](langroid/parsing/pdf_parser.py) PDF files or URLs.\n\n</details>\n\n# :rocket: Demo\nSuppose you want to extract structured information about the key terms \nof a commercial lease document. You can easily do this with Langroid using a two-agent system,\nas we show in the [langroid-examples](https://github.com/langroid/langroid-examples/blob/main/examples/docqa/chat_multi_extract.py) repo.\nThe demo showcases just a few of the many features of Langroid, such as:\n- Multi-agent collaboration: `LeaseExtractor` is in charge of the task, and its LLM (GPT4) generates questions \nto be answered by the `DocAgent`.\n- Retrieval augmented question-answering, with **source-citation**: `DocAgent` LLM (GPT4) uses retrieval from a vector-store to \nanswer the `LeaseExtractor`\'s questions, cites the specific excerpt supporting the answer. \n- Function-calling (also known as tool/plugin): When it has all the information it \nneeds, the `LeaseExtractor` LLM presents the information in a structured \nformat using a Function-call. \n\nHere is what it looks like in action:\n\n\n\n\n# :zap: Highlights\n\n- **Agents as first-class citizens:** The [Agent](https://langroid.github.io/langroid/reference/agent/base/#langroid.agent.base.Agent) class encapsulates LLM conversation state,\n and optionally a vector-store and tools. Agents are a core abstraction in Langroid;\n Agents act as _message transformers_, and by default provide 3 _responder_ methods, one corresponding to each entity: LLM, Agent, User.\n- **Tasks:** A [Task](https://langroid.github.io/langroid/reference/agent/task/) class wraps an Agent, and gives the agent instructions (or roles, or goals), \n manages iteration over an Agent\'s responder methods, \n and orchestrates multi-agent interactions via hierarchical, recursive\n task-delegation. The `Task.run()` method has the same \n type-signature as an Agent\'s responder\'s methods, and this is key to how \n a task of an agent can delegate to other sub-tasks: from the point of view of a Task,\n sub-tasks are simply additional responders, to be used in a round-robin fashion \n after the agent\'s own responders.\n- **Modularity, Reusabilily, Loose coupling:** The `Agent` and `Task` abstractions allow users to design\n Agents with specific skills, wrap them in Tasks, and combine tasks in a flexible way.\n- **LLM Support**: Langroid supports OpenAI LLMs including GPT-3.5-Turbo,\n GPT-4-0613\n- **Caching of LLM prompts, responses:** Langroid uses [Redis](https://redis.com/try-free/) for caching.\n- **Vector-stores**: [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) are currently supported.\n Vector stores allow for Retrieval-Augmented-Generation (RAG).\n- **Grounding and source-citation:** Access to external documents via vector-stores \n allows for grounding and source-citation.\n- **Observability, Logging, Lineage:** Langroid generates detailed logs of multi-agent interactions and\n maintains provenance/lineage of messages, so that you can trace back\n the origin of a message.\n- **Tools/Plugins/Function-calling**: Langroid supports OpenAI\'s recently\n released [function calling](https://platform.openai.com/docs/guides/gpt/function-calling)\n feature. In addition, Langroid has its own native equivalent, which we\n call **tools** (also known as "plugins" in other contexts). Function\n calling and tools have the same developer-facing interface, implemented\n using [Pydantic](https://docs.pydantic.dev/latest/),\n which makes it very easy to define tools/functions and enable agents\n to use them. Benefits of using Pydantic are that you never have to write\n complex JSON specs for function calling, and when the LLM\n hallucinates malformed JSON, the Pydantic error message is sent back to\n the LLM so it can fix it!\n\n--- \n\n# :gear: Installation and Setup\n\n### Install `langroid`\nLangroid requires Python 3.11+. We recommend using a virtual environment.\nUse `pip` to install `langroid` (from PyPi) to your virtual environment:\n```bash\npip install langroid\n```\nThe core Langroid package lets you use OpenAI Embeddings models via their API. \nIf you instead want to use the `all-MiniLM-L6-v2` embeddings model\nfrom from HuggingFace, install Langroid like this:\n```bash\npip install langroid[hf-embeddings]\n```\nNote that this will install `torch` and `sentence-transformers` libraries.\n\n### Set up environment variables (API keys, etc)\n\nTo get started, all you need is an OpenAI API Key.\nIf you don\'t have one, see [this OpenAI Page](https://help.openai.com/en/collections/3675940-getting-started-with-openai-api).\nCurrently only OpenAI models are supported. Others will be added later\n(Pull Requests welcome!).\n\nIn the root of the repo, copy the `.env-template` file to a new file `.env`: \n```bash\ncp .env-template .env\n```\nThen insert your OpenAI API Key. \nYour `.env` file should look like this:\n```bash\nOPENAI_API_KEY=your-key-here-without-quotes\n````\n\nAlternatively, you can set this as an environment variable in your shell\n(you will need to do this every time you open a new shell):\n```bash\nexport OPENAI_API_KEY=your-key-here-without-quotes\n```\n\n\n<details>\n<summary><b>Optional Setup Instructions (click to expand) </b></summary>\n\nAll of the below are optional and not strictly needed to run any of the examples.\n\n- **Qdrant** Vector Store API Key, URL. This is only required if you want to use Qdrant cloud.\n You can sign up for a free 1GB account at [Qdrant cloud](https://cloud.qdrant.io).\n If you skip setting up these, Langroid will use Qdrant in local-storage mode.\n Alternatively [Chroma](https://docs.trychroma.com/) is also currently supported. \n We use the local-storage version of Chroma, so there is no need for an API key.\n- **Redis** Password, host, port: This is optional, and only needed to cache LLM API responses\n using Redis Cloud. Redis [offers](https://redis.com/try-free/) a free 30MB Redis account\n which is more than sufficient to try out Langroid and even beyond.\n If you don\'t set up these, Langroid will use a pure-python \n Redis in-memory cache via the [Fakeredis](https://fakeredis.readthedocs.io/en/latest/) library.\n- **Momento** Serverless Caching of LLM API responses (as an alternative to Redis). \n To use Momento instead of Redis, simply enter your Momento Token in the `.env` file,\n as the value of `MOMENTO_AUTH_TOKEN` (see example file below).\n- **GitHub** Personal Access Token (required for apps that need to analyze git\n repos; token-based API calls are less rate-limited). See this\n [GitHub page](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens).\n\nIf you add all of these optional variables, your `.env` file should look like this:\n```bash\nOPENAI_API_KEY=your-key-here-without-quotes\nGITHUB_ACCESS_TOKEN=your-personal-access-token-no-quotes\nREDIS_PASSWORD=your-redis-password-no-quotes\nREDIS_HOST=your-redis-hostname-no-quotes\nREDIS_PORT=your-redis-port-no-quotes\nMOMENTO_AUTH_TOKEN=your-momento-token-no-quotes # instead of REDIS* variables\nQDRANT_API_KEY=your-key\nQDRANT_API_URL=https://your.url.here:6333 # note port number must be included\n```\n</details>\n\n---\n\n# :tada: Usage Examples\n\nThese are quick teasers to give a glimpse of what you can do with Langroid\nand how your code would look. \n\n:warning: The code snippets below are intended to give a flavor of the code\nand they are **not** complete runnable examples! For that we encourage you to \nconsult the [`langroid-examples`](https://github.com/langroid/langroid-examples) \nrepository.\n\n:information_source: The various LLM prompts and instructions in Langroid\nhave been tested to work well with GPT4.\nSwitching to GPT3.5-Turbo is easy via a config flag\n(e.g., `cfg = OpenAIGPTConfig(chat_model=OpenAIChatModel.GPT3_5_TURBO)`),\nand may suffice for some applications, but in general you may see inferior results.\n\n\n:book: Also see the\n[`Getting Started Guide`](https://langroid.github.io/langroid/quick-start/)\nfor a detailed tutorial.\n\nClick to expand any of the code examples below:\n\n<details>\n<summary> <b> Direct interaction with OpenAI LLM </b> </summary>\n\n```python\nfrom langroid.language_models.openai_gpt import ( \n OpenAIGPTConfig, OpenAIChatModel, OpenAIGPT,\n)\nfrom langroid.language_models.base import LLMMessage, Role\n\ncfg = OpenAIGPTConfig(chat_model=OpenAIChatModel.GPT4)\n\nmdl = OpenAIGPT(cfg)\n\nmessages = [\n LLMMessage(content="You are a helpful assistant", role=Role.SYSTEM), \n LLMMessage(content="What is the capital of Ontario?", role=Role.USER),\n]\nresponse = mdl.chat(messages, max_tokens=200)\nprint(response.message)\n```\n</details>\n\n<details>\n<summary> <b> Define an agent, set up a task, and run it </b> </summary>\n\n```python\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\n\nconfig = ChatAgentConfig(\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=None, # no vector store\n)\nagent = ChatAgent(config)\n# get response from agent\'s LLM, and put this in an interactive loop...\n# answer = agent.llm_response("What is the capital of Ontario?")\n # ... OR instead, set up a task (which has a built-in loop) and run it\ntask = Task(agent, name="Bot") \ntask.run() # ... a loop seeking response from LLM or User at each turn\n```\n</details>\n\n<details>\n<summary><b> Three communicating agents </b></summary>\n\n```python\n\nA toy numbers game, where when given a number `n`:\n- `repeater_agent`\'s LLM simply returns `n`,\n- `even_agent`\'s LLM returns `n/2` if `n` is even, else says "DO-NOT-KNOW"\n- `odd_agent`\'s LLM returns `3*n+1` if `n` is odd, else says "DO-NOT-KNOW"\n\nFirst define the 3 agents, and set up their tasks with instructions:\n\n```python\nfrom langroid.utils.constants import NO_ANSWER\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\nconfig = ChatAgentConfig(\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb = None,\n)\nrepeater_agent = ChatAgent(config)\nrepeater_task = Task(\n repeater_agent,\n name = "Repeater",\n system_message="""\n Your job is to repeat whatever number you receive.\n """,\n llm_delegate=True, # LLM takes charge of task\n single_round=False, \n)\neven_agent = ChatAgent(config)\neven_task = Task(\n even_agent,\n name = "EvenHandler",\n system_message=f"""\n You will be given a number. \n If it is even, divide by 2 and say the result, nothing else.\n If it is odd, say {NO_ANSWER}\n """,\n single_round=True, # task done after 1 step() with valid response\n)\n\nodd_agent = ChatAgent(config)\nodd_task = Task(\n odd_agent,\n name = "OddHandler",\n system_message=f"""\n You will be given a number n. \n If it is odd, return (n*3+1), say nothing else. \n If it is even, say {NO_ANSWER}\n """,\n single_round=True, # task done after 1 step() with valid response\n)\n```\nThen add the `even_task` and `odd_task` as sub-tasks of `repeater_task`, \nand run the `repeater_task`, kicking it off with a number as input:\n```python\nrepeater_task.add_sub_task([even_task, odd_task])\nrepeater_task.run("3")\n```\n\n</details>\n\n<details>\n<summary><b> Simple Tool/Function-calling example </b></summary>\n\nLangroid leverages Pydantic to support OpenAI\'s\n[Function-calling API](https://platform.openai.com/docs/guides/gpt/function-calling)\nas well as its own native tools. The benefits are that you don\'t have to write\nany JSON to specify the schema, and also if the LLM hallucinates a malformed\ntool syntax, Langroid sends the Pydantic validation error (suitiably sanitized) \nto the LLM so it can fix it!\n\nSimple example: Say the agent has a secret list of numbers, \nand we want the LLM to find the smallest number in the list. \nWe want to give the LLM a `probe` tool/function which takes a\nsingle number `n` as argument. The tool handler method in the agent\nreturns how many numbers in its list are at most `n`.\n\nFirst define the tool using Langroid\'s `ToolMessage` class:\n\n\n```python\nfrom langroid.agent.tool_message import ToolMessage\nclass ProbeTool(ToolMessage):\n request: str = "probe" # specifies which agent method handles this tool\n purpose: str = """\n To find how many numbers in my list are less than or equal to \n the <number> you specify.\n """ # description used to instruct the LLM on when/how to use the tool\n number: int # required argument to the tool\n```\n\nThen define a `SpyGameAgent` as a subclass of `ChatAgent`, \nwith a method `probe` that handles this tool:\n\n```python\nfrom langroid.agent.chat_agent import ChatAgent, ChatAgentConfig\nclass SpyGameAgent(ChatAgent):\n def __init__(self, config: ChatAgentConfig):\n super().__init__(config)\n self.numbers = [3, 4, 8, 11, 15, 25, 40, 80, 90]\n\n def probe(self, msg: ProbeTool) -> str:\n # return how many numbers in self.numbers are less or equal to msg.number\n return str(len([n for n in self.numbers if n <= msg.number]))\n```\n\nWe then instantiate the agent and enable it to use and respond to the tool:\n\n```python\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\nspy_game_agent = SpyGameAgent(\n ChatAgentConfig(\n name="Spy",\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=None,\n use_tools=False, # don\'t use Langroid native tool\n use_functions_api=True, # use OpenAI function-call API\n )\n)\nspy_game_agent.enable_message(ProbeTool)\n```\n\nFor a full working example see the\n[chat-agent-tool.py](https://github.com/langroid/langroid-examples/blob/main/examples/quick-start/chat-agent-tool.py)\nscript in the `langroid-examples` repo.\n</details>\n\n<details>\n<summary> <b>Tool/Function-calling to extract structured information from text </b> </summary>\n\nSuppose you want an agent to extract \nthe key terms of a lease, from a lease document, as a nested JSON structure.\nFirst define the desired structure via Pydantic models:\n\n```python\nfrom pydantic import BaseModel\nclass LeasePeriod(BaseModel):\n start_date: str\n end_date: str\n\n\nclass LeaseFinancials(BaseModel):\n monthly_rent: str\n deposit: str\n\nclass Lease(BaseModel):\n period: LeasePeriod\n financials: LeaseFinancials\n address: str\n```\n\nThen define the `LeaseMessage` tool as a subclass of Langroid\'s `ToolMessage`.\nNote the tool has a required argument `terms` of type `Lease`:\n\n```python\nclass LeaseMessage(ToolMessage):\n request: str = "lease_info"\n purpose: str = """\n Collect information about a Commercial Lease.\n """\n terms: Lease\n```\n\nThen define a `LeaseExtractorAgent` with a method `lease_info` that handles this tool,\ninstantiate the agent, and enable it to use and respond to this tool:\n\n```python\nclass LeaseExtractorAgent(ChatAgent):\n def lease_info(self, message: LeaseMessage) -> str:\n print(\n f"""\n DONE! Successfully extracted Lease Info:\n {message.terms}\n """\n )\n return json.dumps(message.terms.dict())\n \nlease_extractor_agent = LeaseExtractorAgent(\n ChatAgentConfig(\n llm=OpenAIGPTConfig(),\n use_functions_api=False,\n use_tools=True,\n )\n)\nlease_extractor_agent.enable_message(LeaseMessage)\n```\n\nSee the [`chat_multi_extract.py`](https://github.com/langroid/langroid-examples/blob/main/examples/docqa/chat_multi_extract.py)\nscript in the `langroid-examples` repo for a full working example.\n</details>\n\n<details>\n<summary><b> Chat with documents (file paths, URLs, etc) </b></summary>\n\nLangroid provides a specialized agent class `DocChatAgent` for this purpose.\nIt incorporates document sharding, embedding, storage in a vector-DB, \nand retrieval-augmented query-answer generation.\nUsing this class to chat with a collection of documents is easy.\nFirst create a `DocChatAgentConfig` instance, with a \n`doc_paths` field that specifies the documents to chat with.\n\n```python\nfrom langroid.agent.doc_chat_agent import DocChatAgentConfig\nconfig = DocChatAgentConfig(\n doc_paths = [\n "https://en.wikipedia.org/wiki/Language_model",\n "https://en.wikipedia.org/wiki/N-gram_language_model",\n "/path/to/my/notes-on-language-models.txt",\n ]\n llm = OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n vecdb=VectorStoreConfig(\n type="qdrant",\n ),\n)\n```\n\nThen instantiate the `DocChatAgent`, ingest the docs into the vector-store:\n\n```python\nagent = DocChatAgent(config)\nagent.ingest()\n```\nThen we can either ask the agent one-off questions,\n```python\nagent.chat("What is a language model?")\n```\nor wrap it in a `Task` and run an interactive loop with the user:\n```python\nfrom langroid.task import Task\ntask = Task(agent)\ntask.run()\n```\n\nSee full working scripts in the \n[`docqa`](https://github.com/langroid/langroid-examples/tree/main/examples/docqa)\nfolder of the `langroid-examples` repo.\n</details>\n\n<details>\n<summary><b> :fire: Chat with tabular data (file paths, URLs, dataframes) </b></summary>\n\nUsing Langroid you can set up a `TableChatAgent` with a dataset (file path, URL or dataframe),\nand query it. The Agent\'s LLM generates Pandas code to answer the query, \nvia function-calling (or tool/plugin), and the Agent\'s function-handling method\nexecutes the code and returns the answer.\n\nHere is how you can do this:\n\n```python\nfrom langroid.agent.special.table_chat_agent import TableChatAgent, TableChatAgentConfig\nfrom langroid.agent.task import Task\nfrom langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig\n```\n\nSet up a `TableChatAgent` for a data file, URL or dataframe\n(Ensure the data table has a header row; the delimiter/separator is auto-detected):\n```python\ndataset = "https://archive.ics.uci.edu/ml/machine-learning-databases/wine-quality/winequality-red.csv"\n# or dataset = "/path/to/my/data.csv"\n# or dataset = pd.read_csv("/path/to/my/data.csv")\nagent = TableChatAgent(\n config=TableChatAgentConfig(\n data=dataset, \n llm=OpenAIGPTConfig(\n chat_model=OpenAIChatModel.GPT4,\n ),\n )\n)\n```\nSet up a task, and ask one-off questions like this: \n\n```python\ntask = Task(\n agent, \n name = "DataAssistant",\n default_human_response="", # to avoid waiting for user input\n)\nresult = task.run(\n "What is the average alcohol content of wines with a quality rating above 7?",\n turns=2 # return after user question, LLM fun-call/tool response, Agent code-exec result\n) \nprint(result.content)\n```\nOr alternatively, set up a task and run it in an interactive loop with the user:\n\n```python\ntask = Task(agent, name="DataAssistant")\ntask.run()\n``` \n\nFor a full working example see the \n[`table_chat.py`](https://github.com/langroid/langroid-examples/tree/main/examples/data-qa/table_chat.py)\nscript in the `langroid-examples` repo.\n\n\n</details>\n\n---\n\n# :heart: Thank you to our [supporters](https://github.com/langroid/langroid/stargazers)\n\nIf you like this repo, don\'t forget to leave a star :star: !\n\n# Contributors\n\n- Prasad Chalasani (IIT BTech/CS, CMU PhD/ML; Independent ML Consultant)\n- Somesh Jha (IIT BTech/CS, CMU PhD/CS; Professor of CS, U Wisc at Madison)\n- Mohannad Alhanahnah (Research Associate, U Wisc at Madison)\n- Ashish Hooda (IIT BTech/CS; PhD Candidate, U Wisc at Madison)\n\n',
|
75
|
-
'author': 'Prasad Chalasani',
|
76
|
-
'author_email': 'pchalasani@gmail.com',
|
77
|
-
'maintainer': 'None',
|
78
|
-
'maintainer_email': 'None',
|
79
|
-
'url': 'None',
|
80
|
-
'packages': packages,
|
81
|
-
'package_data': package_data,
|
82
|
-
'install_requires': install_requires,
|
83
|
-
'extras_require': extras_require,
|
84
|
-
'python_requires': '>=3.8.1,<3.12',
|
85
|
-
}
|
86
|
-
|
87
|
-
|
88
|
-
setup(**setup_kwargs)
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|