linden 0.1.0__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.
linden-0.1.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) [2025] [matstech]
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
linden-0.1.0/PKG-INFO ADDED
@@ -0,0 +1,484 @@
1
+ Metadata-Version: 2.4
2
+ Name: linden
3
+ Version: 0.1.0
4
+ Summary: A Python framework for building AI agents with multi-provider LLM support, persistent memory, and function calling capabilities.
5
+ Author-email: Matteo Stabile <matteo.stabile2@gmail.com>
6
+ License-Expression: MIT
7
+ Project-URL: Homepage, https://github.com/matstech/linden
8
+ Project-URL: Bug Tracker, https://github.com/matstech/linden/issues
9
+ Classifier: Programming Language :: Python :: 3
10
+ Classifier: Operating System :: OS Independent
11
+ Requires-Python: >=3.10
12
+ Description-Content-Type: text/markdown
13
+ License-File: LICENSE
14
+ Requires-Dist: altair==5.5.0
15
+ Requires-Dist: annotated-types==0.7.0
16
+ Requires-Dist: anthropic==0.64.0
17
+ Requires-Dist: anyio==4.10.0
18
+ Requires-Dist: attrs==25.3.0
19
+ Requires-Dist: backoff==2.2.1
20
+ Requires-Dist: blinker==1.9.0
21
+ Requires-Dist: cachetools==6.1.0
22
+ Requires-Dist: certifi==2025.8.3
23
+ Requires-Dist: charset-normalizer==3.4.3
24
+ Requires-Dist: click==8.2.1
25
+ Requires-Dist: distro==1.9.0
26
+ Requires-Dist: docstring_parser==0.17.0
27
+ Requires-Dist: elastic-transport==9.1.0
28
+ Requires-Dist: elasticsearch==9.1.0
29
+ Requires-Dist: faiss-cpu==1.12.0
30
+ Requires-Dist: filelock==3.19.1
31
+ Requires-Dist: fsspec==2025.7.0
32
+ Requires-Dist: gitdb==4.0.12
33
+ Requires-Dist: GitPython==3.1.45
34
+ Requires-Dist: groq==0.31.0
35
+ Requires-Dist: grpcio==1.74.0
36
+ Requires-Dist: h11==0.16.0
37
+ Requires-Dist: h2==4.3.0
38
+ Requires-Dist: hf-xet==1.1.8
39
+ Requires-Dist: hpack==4.1.0
40
+ Requires-Dist: httpcore==1.0.9
41
+ Requires-Dist: httpx==0.28.1
42
+ Requires-Dist: huggingface-hub==0.34.4
43
+ Requires-Dist: hyperframe==6.1.0
44
+ Requires-Dist: idna==3.10
45
+ Requires-Dist: iniconfig==2.1.0
46
+ Requires-Dist: Jinja2==3.1.6
47
+ Requires-Dist: jiter==0.10.0
48
+ Requires-Dist: joblib==1.5.1
49
+ Requires-Dist: jsonschema==4.25.1
50
+ Requires-Dist: jsonschema-specifications==2025.4.1
51
+ Requires-Dist: MarkupSafe==3.0.2
52
+ Requires-Dist: mem0ai==0.1.116
53
+ Requires-Dist: mpmath==1.3.0
54
+ Requires-Dist: narwhals==2.1.2
55
+ Requires-Dist: networkx==3.5
56
+ Requires-Dist: numpy==2.3.2
57
+ Requires-Dist: ollama==0.5.3
58
+ Requires-Dist: openai==1.101.0
59
+ Requires-Dist: packaging==25.0
60
+ Requires-Dist: pandas==2.3.2
61
+ Requires-Dist: pillow==11.3.0
62
+ Requires-Dist: pluggy==1.6.0
63
+ Requires-Dist: portalocker==3.2.0
64
+ Requires-Dist: posthog==6.6.1
65
+ Requires-Dist: protobuf==5.29.5
66
+ Requires-Dist: pyarrow==21.0.0
67
+ Requires-Dist: pydantic==2.11.7
68
+ Requires-Dist: pydantic_core==2.33.2
69
+ Requires-Dist: pydeck==0.9.1
70
+ Requires-Dist: Pygments==2.19.2
71
+ Requires-Dist: pytest==8.4.1
72
+ Requires-Dist: python-dateutil==2.9.0.post0
73
+ Requires-Dist: python-dotenv==1.1.1
74
+ Requires-Dist: pytz==2025.2
75
+ Requires-Dist: PyYAML==6.0.2
76
+ Requires-Dist: qdrant-client==1.15.1
77
+ Requires-Dist: referencing==0.36.2
78
+ Requires-Dist: regex==2025.7.34
79
+ Requires-Dist: requests==2.32.5
80
+ Requires-Dist: rpds-py==0.27.0
81
+ Requires-Dist: safetensors==0.6.2
82
+ Requires-Dist: scikit-learn==1.7.1
83
+ Requires-Dist: scipy==1.16.1
84
+ Requires-Dist: sentence-transformers==4.0.2
85
+ Requires-Dist: setuptools==80.9.0
86
+ Requires-Dist: six==1.17.0
87
+ Requires-Dist: smmap==5.0.2
88
+ Requires-Dist: sniffio==1.3.1
89
+ Requires-Dist: SQLAlchemy==2.0.43
90
+ Requires-Dist: streamlit==1.48.1
91
+ Requires-Dist: sympy==1.14.0
92
+ Requires-Dist: tenacity==9.1.2
93
+ Requires-Dist: threadpoolctl==3.6.0
94
+ Requires-Dist: tokenizers==0.21.4
95
+ Requires-Dist: toml==0.10.2
96
+ Requires-Dist: torch==2.8.0
97
+ Requires-Dist: tornado==6.5.2
98
+ Requires-Dist: tqdm==4.67.1
99
+ Requires-Dist: transformers==4.55.4
100
+ Requires-Dist: typing-inspection==0.4.1
101
+ Requires-Dist: typing_extensions==4.14.1
102
+ Requires-Dist: tzdata==2025.2
103
+ Requires-Dist: urllib3==2.5.0
104
+ Dynamic: license-file
105
+
106
+ # Linden
107
+
108
+ <div align="center">
109
+ <img src="doc/logo.png" alt="Linden Logo" width="200"/>
110
+ </div>
111
+
112
+ <div align="center">
113
+ <p><em>A Python framework for building AI agents with multi-provider LLM support, persistent memory, and function calling capabilities.</em></p>
114
+ </div>
115
+
116
+ ## Table of Contents
117
+
118
+ - [Overview](#overview)
119
+ - [Features](#features)
120
+ - [Installation](#installation)
121
+ - [Requirements](#requirements)
122
+ - [Quick Start](#quick-start)
123
+ - [Basic Agent Setup](#basic-agent-setup)
124
+ - [Agent with Function Calling](#agent-with-function-calling)
125
+ - [Streaming Responses](#streaming-responses)
126
+ - [Structured Output with Pydantic](#structured-output-with-pydantic)
127
+ - [Configuration](#configuration)
128
+ - [Environment Variables](#environment-variables)
129
+ - [Architecture](#architecture)
130
+ - [Core Components](#core-components)
131
+ - [Memory Architecture](#memory-architecture)
132
+ - [Function Tool Definition](#function-tool-definition)
133
+ - [Advanced Usage](#advanced-usage)
134
+ - [Multi-Turn Conversations](#multi-turn-conversations)
135
+ - [Error Handling and Retries](#error-handling-and-retries)
136
+ - [Memory Management](#memory-management)
137
+ - [Provider-Specific Features](#provider-specific-features)
138
+ - [API Reference](#api-reference)
139
+ - [AgentRunner](#agentrunner)
140
+ - [Memory Classes](#memory-classes)
141
+ - [Configuration](#configuration-1)
142
+ - [Error Types](#error-types)
143
+ - [Contributing](#contributing)
144
+ - [License](#license)
145
+ - [Support](#support)
146
+
147
+ ## Overview
148
+
149
+ Linden is a comprehensive AI agent framework that provides a unified interface for interacting with multiple Large Language Model (LLM) providers including OpenAI, Groq, and Ollama. It features persistent conversation memory, automatic tool/function calling, and robust error handling for building production-ready AI applications.
150
+
151
+ ## Features
152
+
153
+ - **Multi-Provider LLM Support**: Seamless integration with OpenAI, Groq, and Ollama
154
+ - **Persistent Memory**: Long-term conversation memory using FAISS vector storage and embeddings
155
+ - **Function Calling**: Automatic parsing and execution of tools with Google-style docstring support
156
+ - **Streaming Support**: Real-time response streaming for interactive applications
157
+ - **Thread-Safe Memory**: Concurrent agent support with isolated memory per agent
158
+ - **Configuration Management**: Flexible TOML-based configuration with environment variable support
159
+ - **Type Safety**: Full Pydantic model support for structured outputs
160
+ - **Error Handling**: Comprehensive error handling with retry mechanisms
161
+
162
+ ## Installation
163
+
164
+ ```bash
165
+ pip install linden
166
+ ```
167
+
168
+ ## Requirements
169
+
170
+ - Python >= 3.9
171
+ - Dependencies automatically installed:
172
+ - `openai` - OpenAI API client
173
+ - `groq` - Groq API client
174
+ - `ollama` - Ollama local LLM client
175
+ - `pydantic` - Data validation and serialization
176
+ - `mem0` - Memory management
177
+ - `docstring_parser` - Function documentation parsing
178
+
179
+ ## Quick Start
180
+
181
+ ### Basic Agent Setup
182
+
183
+ ```python
184
+ from linden.core import AgentRunner, Provider
185
+
186
+ # Create a simple agent
187
+ agent = AgentRunner(
188
+ name="assistant",
189
+ model="gpt-4",
190
+ temperature=0.7,
191
+ system_prompt="You are a helpful AI assistant.",
192
+ client=Provider.OPENAI
193
+ )
194
+
195
+ # Ask a question
196
+ response = agent.run("What is the capital of France?")
197
+ print(response)
198
+ ```
199
+
200
+ ### Agent with Function Calling
201
+
202
+ ```python
203
+ def get_weather(location: str, units: str = "celsius") -> str:
204
+ """Get current weather for a location.
205
+
206
+ Args:
207
+ location (str): The city name or location
208
+ units (str, optional): Temperature units (celsius/fahrenheit). Defaults to celsius.
209
+
210
+ Returns:
211
+ str: Weather information
212
+ """
213
+ return f"The weather in {location} is 22°{units[0].upper()}"
214
+
215
+ # Create agent with tools
216
+ agent = AgentRunner(
217
+ name="weather_bot",
218
+ model="gpt-4",
219
+ temperature=0.7,
220
+ system_prompt="You are a weather assistant.",
221
+ tools=[get_weather],
222
+ client=Provider.OPENAI
223
+ )
224
+
225
+ response = agent.run("What's the weather in Paris?")
226
+ print(response)
227
+ ```
228
+
229
+ ### Streaming Responses
230
+
231
+ ```python
232
+ # Stream responses for real-time interaction
233
+ for chunk in agent.run("Tell me a story", stream=True):
234
+ print(chunk, end="", flush=True)
235
+ ```
236
+
237
+ ### Structured Output with Pydantic
238
+
239
+ ```python
240
+ from pydantic import BaseModel
241
+
242
+ class PersonInfo(BaseModel):
243
+ name: str
244
+ age: int
245
+ occupation: str
246
+
247
+ agent = AgentRunner(
248
+ name="extractor",
249
+ model="gpt-4",
250
+ temperature=0.1,
251
+ system_prompt="Extract person information from text.",
252
+ output_type=PersonInfo,
253
+ client=Provider.OPENAI
254
+ )
255
+
256
+ result = agent.run("John Smith is a 30-year-old software engineer.")
257
+ print(f"Name: {result.name}, Age: {result.age}")
258
+ ```
259
+
260
+ ## Configuration
261
+
262
+ Create a `config.toml` file in your project root:
263
+
264
+ ```toml
265
+ [models]
266
+ dec = "gpt-4"
267
+ tool = "gpt-4"
268
+ extractor = "gpt-3.5-turbo"
269
+ speaker = "gpt-4"
270
+
271
+ [openai]
272
+ api_key = "your-openai-api-key"
273
+ timeout = 30
274
+
275
+ [groq]
276
+ base_url = "https://api.groq.com/openai/v1"
277
+ api_key = "your-groq-api-key"
278
+ timeout = 30
279
+
280
+ [ollama]
281
+ timeout = 60
282
+
283
+ [memory]
284
+ path = "./memory_db"
285
+ ```
286
+
287
+ ### Environment Variables
288
+
289
+ Set your API keys as environment variables:
290
+
291
+ ```bash
292
+ export OPENAI_API_KEY="your-openai-api-key"
293
+ export GROQ_API_KEY="your-groq-api-key"
294
+ ```
295
+
296
+ ## Architecture
297
+
298
+ ### Core Components
299
+
300
+ #### AgentRunner
301
+ The main agent orchestrator that handles:
302
+ - LLM interaction and response processing
303
+ - Tool calling and execution
304
+ - Memory management
305
+ - Error handling and retries
306
+ - Streaming and non-streaming responses
307
+
308
+ #### Memory System
309
+ - **AgentMemory**: Per-agent conversation history and semantic search
310
+ - **MemoryManager**: Thread-safe singleton for shared vector storage
311
+ - **Persistent Storage**: FAISS-based vector database for long-term memory
312
+
313
+ #### AI Clients
314
+ Abstract interface with concrete implementations:
315
+ - **OpenAiClient**: OpenAI GPT models
316
+ - **GroqClient**: Groq inference API
317
+ - **Ollama**: Local LLM execution
318
+
319
+ #### Function Calling
320
+ - Automatic parsing of Google-style docstrings
321
+ - JSON Schema generation for tool descriptions
322
+ - Type-safe argument parsing and validation
323
+ - Error handling for tool execution
324
+
325
+ ### Memory Architecture
326
+
327
+ The memory system uses a shared FAISS vector store with agent isolation:
328
+
329
+ ```python
330
+ # Each agent has isolated memory
331
+ agent1 = AgentRunner(name="agent1", ...)
332
+ agent2 = AgentRunner(name="agent2", ...)
333
+
334
+ # Memories are automatically isolated by agent_id
335
+ agent1.run("Remember I like coffee")
336
+ agent2.run("Remember I like tea")
337
+
338
+ # Each agent only retrieves its own memories
339
+ ```
340
+
341
+ ### Function Tool Definition
342
+
343
+ Functions must use Google-style docstrings for automatic parsing:
344
+
345
+ ```python
346
+ def search_database(query: str, limit: int = 10, filters: dict = None) -> list:
347
+ """Search the knowledge database.
348
+
349
+ Args:
350
+ query (str): The search query string
351
+ limit (int, optional): Maximum results to return. Defaults to 10.
352
+ filters (dict, optional): Additional search filters:
353
+ category (str): Filter by category
354
+ date_range (str): Date range in ISO format
355
+
356
+ Returns:
357
+ list: List of search results with metadata
358
+ """
359
+ # Implementation here
360
+ pass
361
+ ```
362
+
363
+ ## Advanced Usage
364
+
365
+ ### Multi-Turn Conversations
366
+
367
+ ```python
368
+ agent = AgentRunner(name="chat_bot", model="gpt-4", temperature=0.7)
369
+
370
+ # Conversation maintains context automatically
371
+ agent.run("My name is Alice")
372
+ agent.run("What's my name?") # Will remember "Alice"
373
+ agent.run("Tell me about my previous question") # Has full context
374
+ ```
375
+
376
+ ### Error Handling and Retries
377
+
378
+ ```python
379
+ agent = AgentRunner(
380
+ name="robust_agent",
381
+ model="gpt-4",
382
+ temperature=0.7,
383
+ retries=3 # Retry failed calls up to 3 times
384
+ )
385
+
386
+ try:
387
+ response = agent.run("Complex query that might fail")
388
+ except ToolError as e:
389
+ print(f"Tool execution failed: {e.message}")
390
+ except ToolNotFound as e:
391
+ print(f"Tool not found: {e.message}")
392
+ ```
393
+
394
+ ### Memory Management
395
+
396
+ ```python
397
+ # Reset agent memory
398
+ agent.reset()
399
+
400
+ # Add context without user interaction
401
+ agent.add_to_context("Important context information", persist=True)
402
+
403
+ # Get conversation history
404
+ history = agent.memory.get_conversation("Current query")
405
+ ```
406
+
407
+ ### Provider-Specific Features
408
+
409
+ ```python
410
+ # Use local Ollama models
411
+ local_agent = AgentRunner(
412
+ name="local_agent",
413
+ model="llama2",
414
+ client=Provider.OLLAMA
415
+ )
416
+
417
+ # Use Groq for fast inference
418
+ fast_agent = AgentRunner(
419
+ name="fast_agent",
420
+ model="mixtral-8x7b-32768",
421
+ client=Provider.GROQ
422
+ )
423
+ ```
424
+
425
+ ## API Reference
426
+
427
+ ### AgentRunner
428
+
429
+ #### Constructor Parameters
430
+ - `name` (str): Unique agent identifier
431
+ - `model` (str): LLM model name
432
+ - `temperature` (int): Response randomness (0-1)
433
+ - `system_prompt` (str, optional): System instruction
434
+ - `tools` (list[Callable], optional): Available functions
435
+ - `output_type` (BaseModel, optional): Structured output schema
436
+ - `client` (Provider): LLM provider selection
437
+ - `retries` (int): Maximum retry attempts
438
+
439
+ #### Methods
440
+ - `run(user_question: str, stream: bool = False)`: Execute agent query
441
+ - `reset()`: Clear conversation history
442
+ - `add_to_context(content: str, persist: bool = False)`: Add contextual information
443
+
444
+ ### Memory Classes
445
+
446
+ #### AgentMemory
447
+ - `record(message: str, persist: bool = False)`: Store message
448
+ - `get_conversation(user_input: str)`: Retrieve relevant context
449
+ - `reset()`: Clear agent memory
450
+
451
+ #### MemoryManager (Singleton)
452
+ - `get_memory()`: Access shared memory instance
453
+ - `get_all_agent_memories(agent_id: str = None)`: Retrieve stored memories
454
+
455
+ ### Configuration
456
+
457
+ #### ConfigManager
458
+ - `initialize(config_path: str | Path)`: Load configuration file
459
+ - `get(config_path: Optional[str | Path] = None)`: Get configuration instance
460
+ - `reload()`: Refresh configuration from file
461
+
462
+ ## Error Types
463
+
464
+ - `ToolNotFound`: Requested function not available
465
+ - `ToolError`: Function execution failed
466
+ - `ValidationError`: Pydantic model validation failed
467
+ - `RequestException`: HTTP/API communication error
468
+
469
+ ## Contributing
470
+
471
+ 1. Fork the repository
472
+ 2. Create a feature branch (`git checkout -b feature/new-feature`)
473
+ 3. Commit your changes (`git commit -am 'Add new feature'`)
474
+ 4. Push to the branch (`git push origin feature/new-feature`)
475
+ 5. Create a Pull Request
476
+
477
+ ## License
478
+
479
+ This project is licensed under the MIT License - see the LICENSE file for details.
480
+
481
+ ## Support
482
+
483
+ - GitHub Issues: [https://github.com/matstech/linden/issues](https://github.com/matstech/linden/issues)
484
+ - Documentation: [https://github.com/matstech/linden](https://github.com/matstech/linden)