langroid 0.1.22__py3-none-any.whl → 0.1.23__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.
@@ -324,7 +324,7 @@ class DocChatAgent(ChatAgent):
324
324
 
325
325
  passages = self.original_docs
326
326
 
327
- # if original docs not too long, no need to look for relevant parts.
327
+ # if original docs too long, no need to look for relevant parts.
328
328
  if (
329
329
  passages is None
330
330
  or self.original_docs_length > self.config.max_context_tokens
@@ -380,8 +380,13 @@ class DocChatAgent(ChatAgent):
380
380
  if self.parser is None:
381
381
  raise ValueError("No parser defined")
382
382
  tot_tokens = self.parser.num_tokens(full_text)
383
+ model = (
384
+ self.config.llm.chat_model
385
+ if self.config.llm.use_chat_for_completion
386
+ else self.config.llm.completion_model
387
+ )
383
388
  MAX_INPUT_TOKENS = (
384
- self.config.llm.context_length[self.config.llm.completion_model]
389
+ self.config.llm.context_length[model]
385
390
  - self.config.llm.max_output_tokens
386
391
  - 100
387
392
  )
langroid/agent/task.py CHANGED
@@ -1,8 +1,3 @@
1
- """
2
- Class that runs the Task loop of an agent;
3
- maintains state while various responders (agent's own methods, or external sub-tasks)
4
- take turns attempting to respond to the `self.pending_message`.
5
- """
6
1
  from __future__ import annotations
7
2
 
8
3
  import logging
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: langroid
3
- Version: 0.1.22
3
+ Version: 0.1.23
4
4
  Summary: Harness LLMs with Multi-Agent Programming
5
5
  License: MIT
6
6
  Author: Prasad Chalasani
@@ -61,61 +61,51 @@ Description-Content-Type: text/markdown
61
61
  <h1>Langroid: Harness LLMs with Multi-Agent Programming</h1>
62
62
  </div>
63
63
 
64
+ <div align="center">
65
+
64
66
  [![Pytest](https://github.com/langroid/langroid/actions/workflows/pytest.yml/badge.svg)](https://github.com/langroid/langroid/actions/workflows/pytest.yml)
65
67
  [![Lint](https://github.com/langroid/langroid/actions/workflows/validate.yml/badge.svg)](https://github.com/langroid/langroid/actions/workflows/validate.yml)
66
68
  [![Docs](https://github.com/langroid/langroid/actions/workflows/mkdocs-deploy.yml/badge.svg)](https://github.com/langroid/langroid/actions/workflows/mkdocs-deploy.yml)
69
+ [![Static Badge](https://img.shields.io/badge/Documentation-blue?link=https%3A%2F%2Flangroid.github.io%2Flangroid%2F&link=https%3A%2F%2Flangroid.github.io%2Flangroid%2F)](https://langroid.github.io/langroid)
70
+ [![Static Badge](https://img.shields.io/badge/Discord-Orange?link=https%3A%2F%2Fdiscord.gg%2Fg3nAXCbZ&link=https%3A%2F%2Fdiscord.gg%2Fg3nAXCbZ)](https://discord.gg/g3nAXCbZ)
71
+
72
+ </div>
67
73
 
68
74
  Langroid is an intuitive, lightweight, transparent, flexible, extensible and principled
69
- Python framework to harness LLMs using Multi-Agent Programming (MAP).
75
+ Python framework to build LLM-powered applications using Multi-Agent Programming.
70
76
  We welcome [contributions](CONTRIBUTING.md)!
71
77
 
78
+ Langroid is the first Python LLM-application framework that was explicitly
79
+ designed with Agents as first-class citizens, and Multi-Agent Programming
80
+ as the core design principle. The framework is inspired by ideas from the
81
+ [Actor Framework](https://en.wikipedia.org/wiki/Actor_model).
82
+ For more details see [here](https://langroid.github.io/langroid/).
83
+
72
84
  Documentation: https://langroid.github.io/langroid/
73
85
 
74
86
  Usage examples: https://github.com/langroid/langroid-examples
75
87
 
76
- ## Overview
77
-
78
- ### The LLM Opportunity
79
-
80
- Given the remarkable abilities of recent Large Language Models (LLMs), there
81
- is an unprecedented opportunity to build intelligent applications powered by
82
- this transformative technology. The top question for any enterprise is: how
83
- best to harness the power of LLMs for complex applications? For technical and
84
- practical reasons, building LLM-powered applications is not as simple as
85
- throwing a task at an LLM-system and expecting it to do it.
88
+ Community: Join us on [Discord!](https://discord.gg/g3nAXCbZ)
86
89
 
87
- ### Langroid's Multi-Agent Programming Framework
90
+ ## :rocket: Demo
88
91
 
89
- Effectively leveraging LLMs at scale requires a *principled programming
90
- framework*. In particular, there is often a need to maintain multiple LLM
91
- conversations, each instructed in different ways, and "responsible" for
92
- different aspects of a task.
92
+ A `LeaseExtractor` agent is tasked with extracting structured information
93
+ from a commercial lease document. It generates questions that are
94
+ answerred by a `DocAgent` using Retrieval from a vector-database
95
+ (into which the lease has been sharded + embedded).
96
+ When it has all the information it needs, the `LeaseExtractor` agent
97
+ presents the information in a structured format using a Tool/Function-calling.
93
98
 
94
- An *agent* is a convenient abstraction that encapsulates LLM conversation
95
- state, along with access to long-term memory (vector-stores) and tools (a.k.a functions
96
- or plugins). Thus a **Multi-Agent Programming** framework is a natural fit
97
- for complex LLM-based applications.
99
+ ![Demo](lease-extractor-demo.gif)
98
100
 
99
- > Langroid is the first Python LLM-application framework that was explicitly
100
- designed with Agents as first-class citizens, and Multi-Agent Programming
101
- as the core design principle. The framework is inspired by ideas from the
102
- [Actor Framework](https://en.wikipedia.org/wiki/Actor_model).
103
101
 
104
- Langroid allows an intuitive definition of agents, tasks and task-delegation
105
- among agents. There is a principled mechanism to orchestrate multi-agent
106
- collaboration. Agents act as message-transformers, and take turns responding to (and
107
- transforming) the current message. The architecture is lightweight, transparent,
108
- flexible, and allows other types of orchestration to be implemented.
109
- Besides Agents, Langroid also provides simple ways to directly interact with
110
- LLMs and vector-stores.
102
+ ## :zap: Highlights
111
103
 
112
- ### Highlights
113
104
  Highlights of Langroid's features as of July 2023:
114
105
 
115
106
  - **Agents as first-class citizens:** The `Agent` class encapsulates LLM conversation state,
116
107
  and optionally a vector-store and tools. Agents are a core abstraction in Langroid;
117
- Agents act as _message transformers_, and by default provide 3 _responder_ methods,
118
- one corresponding to each entity: LLM, Agent, User.
108
+ Agents act as _message transformers_, and by default provide 3 _responder_ methods, one corresponding to each entity: LLM, Agent, User.
119
109
  - **Tasks:** A Task class wraps an Agent, and gives the agent instructions (or roles, or goals),
120
110
  manages iteration over an Agent's responder methods,
121
111
  and orchestrates multi-agent interactions via hierarchical, recursive
@@ -130,7 +120,7 @@ Highlights of Langroid's features as of July 2023:
130
120
  GPT-4-0613
131
121
  - **Caching of LLM prompts, responses:** Langroid uses [Redis](https://redis.com/try-free/) for caching.
132
122
  - **Vector-stores**: [Qdrant](https://qdrant.tech/) and [Chroma](https://www.trychroma.com/) are currently supported.
133
- Vector stores allow for Retrieval-Augmented-Generaation (RAG).
123
+ Vector stores allow for Retrieval-Augmented-Generation (RAG).
134
124
  - **Grounding and source-citation:** Access to external documents via vector-stores
135
125
  allows for grounding and source-citation.
136
126
  - **Observability, Logging, Lineage:** Langroid generates detailed logs of multi-agent interactions and
@@ -148,11 +138,9 @@ Highlights of Langroid's features as of July 2023:
148
138
  hallucinates malformed JSON, the Pydantic error message is sent back to
149
139
  the LLM so it can fix it!
150
140
 
151
- # Usage/quick-start
152
- These are quick teasers to give a glimpse of what you can do with Langroid
153
- and how your code would look. See the
154
- [`Getting Started Guide`](https://langroid.github.io/langroid/getting_started/)
155
- for a detailed tutorial.
141
+ ---
142
+
143
+ # :gear: Installation and Setup
156
144
 
157
145
  ## Install `langroid`
158
146
  Use `pip` to install `langroid` (from PyPi) to your virtual environment:
@@ -173,7 +161,7 @@ Copy the `.env-template` file to a new file `.env` and
173
161
  insert these secrets:
174
162
  - **OpenAI API** key (required): If you don't have one, see [this OpenAI Page](https://help.openai.com/en/collections/3675940-getting-started-with-openai-api).
175
163
  - **Qdrant** Vector Store API Key (required for apps that need retrieval from
176
- documents): Sign up for a free 1GB account at [Qdrant cloud](https://cloud.qdrant.io)
164
+ documents): Sign up for a free 1GB account at [Qdrant cloud](https://cloud.qdrant.io).
177
165
  Alternatively [Chroma](https://docs.trychroma.com/) is also currently supported.
178
166
  We use the local-storage version of Chroma, so there is no need for an API key.
179
167
  - **GitHub** Personal Access Token (required for apps that need to analyze git
@@ -198,7 +186,32 @@ QDRANT_API_KEY=<your key>
198
186
  Currently only OpenAI models are supported. Others will be added later
199
187
  (Pull Requests welcome!).
200
188
 
201
- ## Direct interaction with OpenAI LLM
189
+ ---
190
+
191
+ # :tada: Usage Examples
192
+
193
+ These are quick teasers to give a glimpse of what you can do with Langroid
194
+ and how your code would look.
195
+
196
+ :warning: The code snippets below are intended to give a flavor of the code
197
+ and they are **not** complete runnable examples! For that we encourage you to
198
+ consult the [`langroid-examples`](https://github.com/langroid/langroid-examples)
199
+ repository.
200
+
201
+ Also see the
202
+ [`Getting Started Guide`](https://langroid.github.io/langroid/quick-start/)
203
+ for a detailed tutorial.
204
+
205
+ - [Direct chat with LLM](#direct-llm)
206
+ - [Simple Agent and Task](#agent-task)
207
+ - [Three Communicating Agents](#three-agents)
208
+ - [Agent with Tool/Function-calling](#agent-tool)
209
+ - [Extract Structured Info with Tool/Function-calling](#agent-tool-structured)
210
+ - [Retrieval-Augmented-Generation: Chat with Docs](#agent-rag)
211
+
212
+ ---
213
+
214
+ ## Direct interaction with OpenAI LLM <a name="direct-llm"></a>
202
215
 
203
216
  ```python
204
217
  from langroid.language_models.openai_gpt import (
@@ -213,11 +226,14 @@ mdl = OpenAIGPT(cfg)
213
226
  messages = [
214
227
  LLMMessage(content="You are a helpful assistant", role=Role.SYSTEM),
215
228
  LLMMessage(content="What is the capital of Ontario?", role=Role.USER),
216
- ],
229
+ ]
217
230
  response = mdl.chat(messages, max_tokens=200)
231
+ print(response.message)
218
232
  ```
219
233
 
220
- ## Define an agent, set up a task, and run it
234
+ ---
235
+
236
+ ## Define an agent, set up a task, and run it <a name="agent-task"></a>
221
237
 
222
238
  ```python
223
239
  from langroid.agent.chat_agent import ChatAgent, ChatAgentConfig
@@ -232,13 +248,15 @@ config = ChatAgentConfig(
232
248
  )
233
249
  agent = ChatAgent(config)
234
250
  # get response from agent's LLM, and put this in an interactive loop...
235
- answer = agent.llm_response("What is the capital of Ontario?")
236
- # ... or set up a task (which has a built-in loop) and run it
251
+ # answer = agent.llm_response("What is the capital of Ontario?")
252
+ # ... OR instead, set up a task (which has a built-in loop) and run it
237
253
  task = Task(agent, name="Bot")
238
- task.run() # ... a loop seeking response from Agent, LLM or User at each turn
254
+ task.run() # ... a loop seeking response from LLM or User at each turn
239
255
  ```
240
256
 
241
- ## Three communicating agents
257
+ ---
258
+
259
+ ## Three communicating agents <a name="three-agents"></a>
242
260
 
243
261
  A toy numbers game, where when given a number `n`:
244
262
  - `repeater_agent`'s LLM simply returns `n`,
@@ -248,57 +266,66 @@ A toy numbers game, where when given a number `n`:
248
266
  First define the 3 agents, and set up their tasks with instructions:
249
267
 
250
268
  ```python
251
- config = ChatAgentConfig(
252
- llm = OpenAIGPTConfig(
253
- chat_model=OpenAIChatModel.GPT4,
254
- ),
255
- vecdb = None,
256
- )
257
- repeater_agent = ChatAgent(config)
258
- repeater_task = Task(
259
- repeater_agent,
260
- name = "Repeater",
261
- system_message="""
262
- Your job is to repeat whatever number you receive.
263
- """,
264
- llm_delegate=True, # LLM takes charge of task
265
- single_round=False,
266
- )
267
- even_agent = ChatAgent(config)
268
- even_task = Task(
269
- even_agent,
270
- name = "EvenHandler",
271
- system_message=f"""
272
- You will be given a number.
273
- If it is even, divide by 2 and say the result, nothing else.
274
- If it is odd, say {NO_ANSWER}
275
- """,
276
- single_round=True, # task done after 1 step() with valid response
277
- )
269
+ from langroid.utils.constants import NO_ANSWER
270
+ from langroid.agent.chat_agent import ChatAgent, ChatAgentConfig
271
+ from langroid.agent.task import Task
272
+ from langroid.language_models.openai_gpt import OpenAIChatModel, OpenAIGPTConfig
273
+ config = ChatAgentConfig(
274
+ llm = OpenAIGPTConfig(
275
+ chat_model=OpenAIChatModel.GPT4,
276
+ ),
277
+ vecdb = None,
278
+ )
279
+ repeater_agent = ChatAgent(config)
280
+ repeater_task = Task(
281
+ repeater_agent,
282
+ name = "Repeater",
283
+ system_message="""
284
+ Your job is to repeat whatever number you receive.
285
+ """,
286
+ llm_delegate=True, # LLM takes charge of task
287
+ single_round=False,
288
+ )
289
+ even_agent = ChatAgent(config)
290
+ even_task = Task(
291
+ even_agent,
292
+ name = "EvenHandler",
293
+ system_message=f"""
294
+ You will be given a number.
295
+ If it is even, divide by 2 and say the result, nothing else.
296
+ If it is odd, say {NO_ANSWER}
297
+ """,
298
+ single_round=True, # task done after 1 step() with valid response
299
+ )
278
300
 
279
- odd_agent = ChatAgent(config)
280
- odd_task = Task(
281
- odd_agent,
282
- name = "OddHandler",
283
- system_message=f"""
284
- You will be given a number n.
285
- If it is odd, return (n*3+1), say nothing else.
286
- If it is even, say {NO_ANSWER}
287
- """,
288
- single_round=True, # task done after 1 step() with valid response
289
- )
301
+ odd_agent = ChatAgent(config)
302
+ odd_task = Task(
303
+ odd_agent,
304
+ name = "OddHandler",
305
+ system_message=f"""
306
+ You will be given a number n.
307
+ If it is odd, return (n*3+1), say nothing else.
308
+ If it is even, say {NO_ANSWER}
309
+ """,
310
+ single_round=True, # task done after 1 step() with valid response
311
+ )
290
312
  ```
291
313
  Then add the `even_task` and `odd_task` as sub-tasks of `repeater_task`,
292
314
  and run the `repeater_task`, kicking it off with a number as input:
293
315
  ```python
294
- repeater_task.add_sub_task([even_task, odd_task])
295
- repeater_task.run("3")
316
+ repeater_task.add_sub_task([even_task, odd_task])
317
+ repeater_task.run("3")
296
318
  ```
319
+ ---
320
+
321
+ ## Simple Tool/Function-calling example <a name="agent-tool"></a>
297
322
 
298
- ### Simple Tool/Function-calling example
299
323
  Langroid leverages Pydantic to support OpenAI's
300
324
  [Function-calling API](https://platform.openai.com/docs/guides/gpt/function-calling)
301
- as well as its own native tools.
325
+ as well as its own native tools. The benefits are that you don't have to write
326
+ any JSON to specify the schema, and also if the LLM hallucinates a malformed
327
+ tool syntax, Langroid sends the Pydantic validation error (suitiably sanitized)
328
+ to the LLM so it can fix it!
302
329
 
303
330
  Simple example: Say the agent has a secret list of numbers,
304
331
  and we want the LLM to find the smallest number in the list.
@@ -357,7 +384,9 @@ For a full working example see the
357
384
  [chat-agent-tool.py](https://github.com/langroid/langroid-examples/blob/main/examples/quick-start/chat-agent-tool.py)
358
385
  script in the `langroid-examples` repo.
359
386
 
360
- ### Tool/Function-calling to extract structured information from text
387
+ ---
388
+
389
+ ## Tool/Function-calling to extract structured information from text <a name="agent-tool-structured"></a>
361
390
 
362
391
  Suppose you want an agent to extract
363
392
  the key terms of a lease, from a lease document, as a nested JSON structure.
@@ -381,7 +410,7 @@ class Lease(BaseModel):
381
410
  ```
382
411
 
383
412
  Then define the `LeaseMessage` tool as a subclass of Langroid's `ToolMessage`.
384
- Note the tool as a required argument `terms` of type `Lease`:
413
+ Note the tool has a required argument `terms` of type `Lease`:
385
414
 
386
415
  ```python
387
416
  class LeaseMessage(ToolMessage):
@@ -419,8 +448,9 @@ lease_extractor_agent.enable_message(LeaseMessage)
419
448
  See the [`chat_multi_extract.py`](https://github.com/langroid/langroid-examples/blob/main/examples/docqa/chat_multi_extract.py)
420
449
  script in the `langroid-examples` repo for a full working example.
421
450
 
451
+ ---
422
452
 
423
- ### Chat with documents (file paths, URLs, etc)
453
+ ## Chat with documents (file paths, URLs, etc) <a name="agent-docs"></a>
424
454
 
425
455
  Langroid provides a specialized agent class `DocChatAgent` for this purpose.
426
456
  It incorporates document sharding, embedding, storage in a vector-DB,
@@ -467,8 +497,9 @@ See full working scripts in the
467
497
  [`docqa`](https://github.com/langroid/langroid-examples/tree/main/examples/docqa)
468
498
  folder of the `langroid-examples` repo.
469
499
 
500
+ ---
470
501
 
471
- ## Contributors
502
+ # Contributors
472
503
 
473
504
  - Prasad Chalasani (IIT BTech/CS, CMU PhD/ML; Independent ML Consultant)
474
505
  - Somesh Jha (IIT BTech/CS, CMU PhD/CS; Professor of CS, U Wisc at Madison)
@@ -6,10 +6,10 @@ langroid/agent/chat_document.py,sha256=Rj7Hfp_FrNjuKsTMA3KyZhno5zKpmvnPPk7WgAuAF
6
6
  langroid/agent/helpers.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
7
7
  langroid/agent/junk,sha256=LxfuuW7Cijsg0szAzT81OjWWv1PMNI-6w_-DspVIO2s,339
8
8
  langroid/agent/special/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
9
- langroid/agent/special/doc_chat_agent.py,sha256=hcGbB9Vb0qdnPI9qHdQj1EIR8qPIluId7VlSP4cHfco,15600
9
+ langroid/agent/special/doc_chat_agent.py,sha256=NhoS02rlLr3nAfRvLB1YNcmfsWZJH24K8O-m-uYnb-I,15741
10
10
  langroid/agent/special/recipient_validator_agent.py,sha256=x2UprcGlh-fyxQCZbb_fkKrruU5Om0mgOnNzk_PYBNM,4527
11
11
  langroid/agent/special/retriever_agent.py,sha256=AiGKIJdndV4u5kr3woINw-vLKhwWnsINlvXtXxHcJgQ,6995
12
- langroid/agent/task.py,sha256=n-kqSVirxUHiFYwuchmY7tBSsX5FBk2gVa9tURnpw6M,25294
12
+ langroid/agent/task.py,sha256=5P3S7thuYBvdaowOk1KMyDLukDtc-LLJactJcSgEJqA,25093
13
13
  langroid/agent/tool_message.py,sha256=7OdVcV7UyOZD2ihYgV1C_1fIwiWM-2pR8FFxoA1IgOo,5379
14
14
  langroid/agent_config.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
15
15
  langroid/cachedb/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
@@ -60,7 +60,7 @@ langroid/vector_store/base.py,sha256=QZx3NUNwf2I0r3A7iuoUHIRGbqt_pFGD0hq1R-Yg8iM
60
60
  langroid/vector_store/chromadb.py,sha256=GPaXNPgPGIVUwYx2eO_-kreQoJ_33IFo13oigH5BP1c,5200
61
61
  langroid/vector_store/qdrant_cloud.py,sha256=3im4Mip0QXLkR6wiqVsjV1QvhSElfxdFSuDKddBDQ-4,188
62
62
  langroid/vector_store/qdrantdb.py,sha256=y7-fMxOqMJoYbdSfIr_HKcTIWTRpnb9j3Yg5EcOyFd4,8522
63
- langroid-0.1.22.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
64
- langroid-0.1.22.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
65
- langroid-0.1.22.dist-info/METADATA,sha256=i-QctcArTIqjyBGW_A8kUVLMQkI_788C0tpcv-l0U0U,18591
66
- langroid-0.1.22.dist-info/RECORD,,
63
+ langroid-0.1.23.dist-info/LICENSE,sha256=EgVbvA6VSYgUlvC3RvPKehSg7MFaxWDsFuzLOsPPfJg,1065
64
+ langroid-0.1.23.dist-info/WHEEL,sha256=vVCvjcmxuUltf8cYhJ0sJMRDLr1XsPuxEId8YDzbyCY,88
65
+ langroid-0.1.23.dist-info/METADATA,sha256=xuEtaXD4fPlxFI9r1ieWlDbj8VUZ-moCd2WFtOdeX5E,19215
66
+ langroid-0.1.23.dist-info/RECORD,,