solana-agent 1.2.0__tar.gz → 1.3.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.
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.3
2
2
  Name: solana-agent
3
- Version: 1.2.0
3
+ Version: 1.3.0
4
4
  Summary: Build self-learning AI Agents
5
5
  License: MIT
6
6
  Keywords: ai,openai,ai agents
@@ -17,7 +17,7 @@ Classifier: Programming Language :: Python :: 3.13
17
17
  Classifier: Programming Language :: Python :: 3 :: Only
18
18
  Classifier: Topic :: Scientific/Engineering :: Artificial Intelligence
19
19
  Requires-Dist: cohere (>=5.13.12,<6.0.0)
20
- Requires-Dist: openai (>=1.61.1,<2.0.0)
20
+ Requires-Dist: openai (>=1.63.2,<2.0.0)
21
21
  Requires-Dist: pinecone (>=6.0.1,<7.0.0)
22
22
  Requires-Dist: pydantic (>=2.10.6,<3.0.0)
23
23
  Requires-Dist: pymongo (>=4.11.1,<5.0.0)
@@ -45,7 +45,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
45
45
  - 🎯 **Context-Aware**: Recalls past interactions for more relevant responses
46
46
  - 🔄 **Self-Improving**: Builds knowledge and improves reasoning automatically
47
47
  - 🧠 **Knowledge Base**: Add domain-specific knowledge for better reasoning
48
- - 🏢 **Enterprise-Ready**: Scales from personal to organization-wide deployment
48
+ - 🏢 **File Context**: Upload propriety files to be part of the conversation
49
49
  - 🛡️ **Secure**: Secure and private memory and data storage
50
50
 
51
51
  **Experience Agentic IQ!**
@@ -57,7 +57,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
57
57
  - Real-time voice-to-voice conversations
58
58
 
59
59
  🧠 **Memory System and Extensibility**
60
- - Advanced AI memory combining conversational context, conversational facts, and parallel tool calling
60
+ - Advanced AI memory combining conversational context, conversational facts, knowledge base, file search, and parallel tool calling
61
61
  - Create custom tools for extending the Agent's capabilities like further API integrations
62
62
 
63
63
  🔍 **Multi-Source Search and Reasoning**
@@ -66,6 +66,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
66
66
  - Conversational fact search powered by Zep
67
67
  - Conversational message history using MongoDB (on-prem or hosted)
68
68
  - Knowledge Base using Pinecone with reranking by Cohere - available globally or user-specific
69
+ - File search using OpenAI
69
70
  - Comprehensive reasoning combining multiple data sources
70
71
 
71
72
  ## Why Choose Solana Agent Over LangChain?
@@ -77,6 +78,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
77
78
  - Persistent cross-session knowledge retention
78
79
  - Automatic self-learning from conversations
79
80
  - Knowledge Base to add domain specific knowledge
81
+ - File uploads to perform document context search
80
82
 
81
83
  🏢 **Enterprise Focus**
82
84
  - Production-ready out of the box in a few lines of code
@@ -17,7 +17,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
17
17
  - 🎯 **Context-Aware**: Recalls past interactions for more relevant responses
18
18
  - 🔄 **Self-Improving**: Builds knowledge and improves reasoning automatically
19
19
  - 🧠 **Knowledge Base**: Add domain-specific knowledge for better reasoning
20
- - 🏢 **Enterprise-Ready**: Scales from personal to organization-wide deployment
20
+ - 🏢 **File Context**: Upload propriety files to be part of the conversation
21
21
  - 🛡️ **Secure**: Secure and private memory and data storage
22
22
 
23
23
  **Experience Agentic IQ!**
@@ -29,7 +29,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
29
29
  - Real-time voice-to-voice conversations
30
30
 
31
31
  🧠 **Memory System and Extensibility**
32
- - Advanced AI memory combining conversational context, conversational facts, and parallel tool calling
32
+ - Advanced AI memory combining conversational context, conversational facts, knowledge base, file search, and parallel tool calling
33
33
  - Create custom tools for extending the Agent's capabilities like further API integrations
34
34
 
35
35
  🔍 **Multi-Source Search and Reasoning**
@@ -38,6 +38,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
38
38
  - Conversational fact search powered by Zep
39
39
  - Conversational message history using MongoDB (on-prem or hosted)
40
40
  - Knowledge Base using Pinecone with reranking by Cohere - available globally or user-specific
41
+ - File search using OpenAI
41
42
  - Comprehensive reasoning combining multiple data sources
42
43
 
43
44
  ## Why Choose Solana Agent Over LangChain?
@@ -49,6 +50,7 @@ Unlike traditional AI assistants that forget conversations after each session, S
49
50
  - Persistent cross-session knowledge retention
50
51
  - Automatic self-learning from conversations
51
52
  - Knowledge Base to add domain specific knowledge
53
+ - File uploads to perform document context search
52
54
 
53
55
  🏢 **Enterprise Focus**
54
56
  - Production-ready out of the box in a few lines of code
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "solana-agent"
3
- version = "1.2.0"
3
+ version = "1.3.0"
4
4
  description = "Build self-learning AI Agents"
5
5
  authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
6
6
  license = "MIT"
@@ -18,7 +18,7 @@ python_paths = [".", "tests"]
18
18
 
19
19
  [tool.poetry.dependencies]
20
20
  python = ">=3.9,<4.0"
21
- openai = "^1.61.1"
21
+ openai = "^1.63.2"
22
22
  pydantic = "^2.10.6"
23
23
  pymongo = "^4.11.1"
24
24
  zep-cloud = "^2.4.0"
@@ -49,6 +49,8 @@ class MongoDatabase:
49
49
  self._threads = self.db["threads"]
50
50
  self.messages = self.db["messages"]
51
51
  self.kb = self.db["kb"]
52
+ self.vector_stores = self.db["vector_stores"]
53
+ self.files = self.db["files"]
52
54
 
53
55
  def save_thread_id(self, user_id: str, thread_id: str):
54
56
  self._threads.insert_one({"thread_id": thread_id, "user_id": user_id})
@@ -76,6 +78,22 @@ class MongoDatabase:
76
78
  storage["timestamp"] = datetime.datetime.now(datetime.timezone.utc)
77
79
  self.kb.insert_one(storage)
78
80
 
81
+ def get_vector_store_id(self) -> str | None:
82
+ document = self.vector_stores.find_one()
83
+ return document["vector_store_id"] if document else None
84
+
85
+ def save_vector_store_id(self, vector_store_id: str):
86
+ self.vector_stores.insert_one({"vector_store_id": vector_store_id})
87
+
88
+ def delete_vector_store_id(self, vector_store_id: str):
89
+ self.vector_stores.delete_one({"vector_store_id": vector_store_id})
90
+
91
+ def add_file(self, file_id: str):
92
+ self.files.insert_one({"file_id": file_id})
93
+
94
+ def delete_file(self, file_id: str):
95
+ self.files.delete_one({"file_id": file_id})
96
+
79
97
 
80
98
  class AI:
81
99
  def __init__(
@@ -92,6 +110,7 @@ class AI:
92
110
  cohere_api_key: str = None,
93
111
  cohere_model: Literal["rerank-v3.5"] = "rerank-v3.5",
94
112
  code_interpreter: bool = True,
113
+ file_search: bool = True,
95
114
  openai_assistant_model: Literal["gpt-4o-mini",
96
115
  "gpt-4o"] = "gpt-4o-mini",
97
116
  openai_embedding_model: Literal[
@@ -113,6 +132,7 @@ class AI:
113
132
  cohere_api_key (str, optional): API key for Cohere search. Defaults to None
114
133
  cohere_model (Literal["rerank-v3.5"], optional): Cohere model for reranking. Defaults to "rerank-v3.5"
115
134
  code_interpreter (bool, optional): Enable code interpretation. Defaults to True
135
+ file_search (bool, optional): Enable file search tool. Defaults to True
116
136
  openai_assistant_model (Literal["gpt-4o-mini", "gpt-4o"], optional): OpenAI model for assistant. Defaults to "gpt-4o-mini"
117
137
  openai_embedding_model (Literal["text-embedding-3-small", "text-embedding-3-large"], optional): OpenAI model for text embedding. Defaults to "text-embedding-3-small"
118
138
 
@@ -137,8 +157,20 @@ class AI:
137
157
  self._instructions = instructions
138
158
  self._openai_assistant_model = openai_assistant_model
139
159
  self._openai_embedding_model = openai_embedding_model
140
- self._tools = [{"type": "code_interpreter"}
141
- ] if code_interpreter else []
160
+ self._file_search = file_search
161
+ if file_search:
162
+ self._tools = (
163
+ [
164
+ {"type": "code_interpreter"},
165
+ {"type": "file_search"},
166
+ ]
167
+ if code_interpreter
168
+ else [{"type": "file_search"}]
169
+ )
170
+ else:
171
+ self._tools = [{"type": "code_interpreter"}
172
+ ] if code_interpreter else []
173
+
142
174
  self._tool_handlers = {}
143
175
  self._assistant_id = None
144
176
  self._database: MongoDatabase = database
@@ -174,7 +206,24 @@ class AI:
174
206
  model=self._openai_assistant_model,
175
207
  ).id
176
208
  self._database.delete_all_threads()
177
-
209
+ if self._file_search:
210
+ vectore_store_id = self._database.get_vector_store_id()
211
+ if vectore_store_id:
212
+ self._vector_store = self._client.beta.vector_stores.retrieve(
213
+ vector_store_id=vectore_store_id
214
+ )
215
+ else:
216
+ uid = uuid.uuid4().hex
217
+ self._vector_store = self._client.beta.vector_stores.create(
218
+ name=uid
219
+ )
220
+ self._database.save_vector_store_id(self._vector_store.id)
221
+ self._client.beta.assistants.update(
222
+ assistant_id=self._assistant_id,
223
+ tool_resources={
224
+ "file_search": {"vector_store_ids": [self._vector_store.id]}
225
+ },
226
+ )
178
227
  return self
179
228
 
180
229
  async def __aexit__(self, exc_type, exc_val, exc_tb):
@@ -223,6 +272,116 @@ class AI:
223
272
  )
224
273
  return run.status
225
274
 
275
+ def delete_vector_store_and_files(self):
276
+ """Delete the OpenAI vector store and files.
277
+
278
+ Example:
279
+ ```python
280
+ ai.delete_vector_store()
281
+ ```
282
+
283
+ Note:
284
+ - Requires file_search=True in AI initialization
285
+ - Deletes the vector store and all associated files
286
+ """
287
+ vector_store_id = self._database.get_vector_store_id()
288
+ if vector_store_id:
289
+ self._client.beta.vector_stores.delete(vector_store_id)
290
+ self._database.delete_vector_store_id(vector_store_id)
291
+ for file in self._database.files.find().to_list():
292
+ self._client.files.delete(file["file_id"])
293
+ self._database.delete_file(file["file_id"])
294
+
295
+ def max_files(self) -> bool:
296
+ """Check if the OpenAI vector store has reached its maximum file capacity.
297
+
298
+ Returns:
299
+ bool: True if file count is at maximum (10,000), False otherwise
300
+
301
+ Example:
302
+ ```python
303
+ if ai.max_files():
304
+ print("Vector store is full")
305
+ else:
306
+ print("Can still add more files")
307
+ ```
308
+
309
+ Note:
310
+ - Requires file_search=True in AI initialization
311
+ - OpenAI vector stores have a 10,000 file limit
312
+ - Returns False if vector store is not configured
313
+ """
314
+ self._vector_store.file_counts.completed == 10000
315
+
316
+ def file_count(self) -> int:
317
+ """Get the total number of files processed in the OpenAI vector store.
318
+
319
+ Returns:
320
+ int: Number of successfully processed files in the vector store
321
+
322
+ Example:
323
+ ```python
324
+ count = ai.file_count()
325
+ print(f"Processed {count} files")
326
+ # Returns: "Processed 5 files"
327
+ ```
328
+
329
+ Note:
330
+ - Requires file_search=True in AI initialization
331
+ - Only counts successfully processed files
332
+ - Returns 0 if vector store is not configured
333
+ """
334
+ self._vector_store.file_counts.completed
335
+
336
+ def add_file(
337
+ self,
338
+ file_stream: bytes,
339
+ file_extension: Literal[
340
+ "doc", "docx", "json", "md", "pdf", "pptx", "tex", "txt"
341
+ ] = "pdf",
342
+ ) -> Literal["in_progress", "completed", "cancelled", "failed"]:
343
+ """Upload and process a file in the OpenAI vector store.
344
+
345
+ Args:
346
+ file_stream (bytes): Raw bytes of the file to upload
347
+ file_extension (Literal, optional): File type extension. Defaults to "pdf"
348
+ Supported formats:
349
+ - doc, docx: Word documents
350
+ - json: JSON files
351
+ - md: Markdown files
352
+ - pdf: PDF documents
353
+ - pptx: PowerPoint presentations
354
+ - tex: LaTeX files
355
+ - txt: Plain text files
356
+
357
+ Returns:
358
+ Literal["in_progress", "completed", "cancelled", "failed"]: Status of file processing
359
+
360
+ Example:
361
+ ```python
362
+ with open('document.pdf', 'rb') as f:
363
+ status = ai.add_file(f.read(), file_extension="pdf")
364
+ if status == "completed":
365
+ print("File processed successfully")
366
+ ```
367
+
368
+ Note:
369
+ - Requires file_search=True in AI initialization
370
+ - Files are vectorized for semantic search
371
+ - Maximum file size: 512MB
372
+ - Maximum 10,000 files per vector store
373
+ - Processing may take a few seconds to minutes
374
+ """
375
+ vector_store_id = self._database.get_vector_store_id()
376
+ file = self._client.files.create(
377
+ file=(f"file.{file_extension}", file_stream), purpose="assistants"
378
+ )
379
+ file_batch = self._client.beta.vector_stores.files.create_and_poll(
380
+ vector_store_id=vector_store_id, file_id=file.id
381
+ )
382
+ self._database.add_file(file.id)
383
+ return file_batch.status
384
+
226
385
  def search_kb(self, query: str, namespace: str = "global", limit: int = 3) -> str:
227
386
  """Search Pinecone knowledge base using OpenAI embeddings.
228
387
 
File without changes