solana-agent 22.0.0__tar.gz → 22.0.5__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.
- {solana_agent-22.0.0 → solana_agent-22.0.5}/PKG-INFO +59 -9
- {solana_agent-22.0.0 → solana_agent-22.0.5}/README.md +58 -8
- {solana_agent-22.0.0 → solana_agent-22.0.5}/pyproject.toml +1 -1
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/llm_adapter.py +14 -16
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/client/solana_agent.py +2 -2
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/client/client.py +1 -1
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/llm.py +1 -1
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/agent.py +1 -1
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/query.py +1 -1
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/agent.py +48 -14
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/query.py +4 -3
- {solana_agent-22.0.0 → solana_agent-22.0.5}/LICENSE +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/mongodb_adapter.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/client/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/agent.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/routing.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/factories/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/factories/agent_factory.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/plugins/plugins.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/data_storage.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/memory.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/routing.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/manager.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/registry.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/tools/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/tools/auto_tool.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/repositories/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/repositories/memory.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/__init__.py +0 -0
- {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/routing.py +0 -0
@@ -1,6 +1,6 @@
|
|
1
1
|
Metadata-Version: 2.3
|
2
2
|
Name: solana-agent
|
3
|
-
Version: 22.0.
|
3
|
+
Version: 22.0.5
|
4
4
|
Summary: Agentic IQ
|
5
5
|
License: MIT
|
6
6
|
Keywords: ai,openai,ai agents,agi
|
@@ -49,7 +49,6 @@ Build your AI business in three lines of code!
|
|
49
49
|
* Extensible Tooling
|
50
50
|
* Simple Business Definition
|
51
51
|
* Tested & Secure
|
52
|
-
* Support for MCP Servers
|
53
52
|
* Built in Python
|
54
53
|
* Deployed by [CometHeart](https://cometheart.com) & [WalletBubbles](https://walletbubbles.com)
|
55
54
|
|
@@ -66,7 +65,6 @@ Build your AI business in three lines of code!
|
|
66
65
|
* Powerful tool integration using standard Python packages and/or inline tools
|
67
66
|
* Assigned tools are utilized by agents automatically and effectively
|
68
67
|
* Simple business definition using JSON
|
69
|
-
* Ability to access any MCP server via URL
|
70
68
|
|
71
69
|
## Stack
|
72
70
|
|
@@ -251,9 +249,57 @@ async for response in solana_agent.process("user123", "Write me a poem.", intern
|
|
251
249
|
print(response, end="")
|
252
250
|
```
|
253
251
|
|
254
|
-
|
252
|
+
### Customize Audio Voice
|
255
253
|
|
256
|
-
|
254
|
+
This is an audio to audio example using the `audio_instructions` parameter.
|
255
|
+
|
256
|
+
```python
|
257
|
+
async for response in solana_agent.process("user123", audio_content, output_format="audio", audio_voice="nova", audio_input_format="webm", audio_output_format="aac", audio_instructions="You speak with an American southern accent"):
|
258
|
+
print(response, end="")
|
259
|
+
```
|
260
|
+
|
261
|
+
## Tools
|
262
|
+
|
263
|
+
Tools can be used from plugins like Solana Agent Kit (sakit) or via custom inline tools. Tools available via plugins integrate automatically with Solana Agent.
|
264
|
+
|
265
|
+
### Plugin Usage Example
|
266
|
+
|
267
|
+
`pip install sakit`
|
268
|
+
|
269
|
+
```python
|
270
|
+
from solana_agent import SolanaAgent
|
271
|
+
|
272
|
+
config = {
|
273
|
+
"openai": {
|
274
|
+
"api_key": "your-openai-api-key",
|
275
|
+
},
|
276
|
+
"tools": {
|
277
|
+
"search_internet": {
|
278
|
+
"api_key": "your-perplexity-api-key",
|
279
|
+
},
|
280
|
+
},
|
281
|
+
"agents": [
|
282
|
+
{
|
283
|
+
"name": "research_specialist",
|
284
|
+
"instructions": "You are an expert researcher who synthesizes complex information clearly. You use your search_internet tool to get the latest information.",
|
285
|
+
"specialization": "Research and knowledge synthesis",
|
286
|
+
"tools": ["search_internet"],
|
287
|
+
},
|
288
|
+
{
|
289
|
+
"name": "customer_support",
|
290
|
+
"instructions": "You provide friendly, helpful customer support responses.",
|
291
|
+
"specialization": "Customer inquiries",
|
292
|
+
}
|
293
|
+
],
|
294
|
+
}
|
295
|
+
|
296
|
+
solana_agent = SolanaAgent(config=config)
|
297
|
+
|
298
|
+
async for response in solana_agent.process("user123", "What are the latest AI developments?", internet_search=False):
|
299
|
+
print(response, end="")
|
300
|
+
```
|
301
|
+
|
302
|
+
### Custom Inline Tool Example
|
257
303
|
|
258
304
|
```python
|
259
305
|
from solana_agent import SolanaAgent
|
@@ -333,9 +379,11 @@ async for response in solana_agent.process("user123", "What are the latest AI de
|
|
333
379
|
print(response, end="")
|
334
380
|
```
|
335
381
|
|
336
|
-
|
382
|
+
## Training your Agents
|
337
383
|
|
338
|
-
|
384
|
+
Many use-cases for Solana Agent require training your agents on your company data.
|
385
|
+
|
386
|
+
This can be accomplished via runtime prompt injection. Integrations that work well with this method are KBs like Pinecone and FAQs.
|
339
387
|
|
340
388
|
```python
|
341
389
|
from solana_agent import SolanaAgent
|
@@ -360,11 +408,13 @@ config = {
|
|
360
408
|
|
361
409
|
solana_agent = SolanaAgent(config=config)
|
362
410
|
|
363
|
-
async for response in solana_agent.process("user123", "What are the latest AI developments?", "
|
411
|
+
async for response in solana_agent.process("user123", "What are the latest AI developments?", "This is my FAQ"):
|
364
412
|
print(response, end="")
|
365
413
|
```
|
366
414
|
|
367
|
-
|
415
|
+
## Custom Routing
|
416
|
+
|
417
|
+
In advanced cases like implementing a ticketing system on-top of Solana Agent - you can use your own router.
|
368
418
|
|
369
419
|
```python
|
370
420
|
from solana_agent import SolanaAgent
|
@@ -25,7 +25,6 @@ Build your AI business in three lines of code!
|
|
25
25
|
* Extensible Tooling
|
26
26
|
* Simple Business Definition
|
27
27
|
* Tested & Secure
|
28
|
-
* Support for MCP Servers
|
29
28
|
* Built in Python
|
30
29
|
* Deployed by [CometHeart](https://cometheart.com) & [WalletBubbles](https://walletbubbles.com)
|
31
30
|
|
@@ -42,7 +41,6 @@ Build your AI business in three lines of code!
|
|
42
41
|
* Powerful tool integration using standard Python packages and/or inline tools
|
43
42
|
* Assigned tools are utilized by agents automatically and effectively
|
44
43
|
* Simple business definition using JSON
|
45
|
-
* Ability to access any MCP server via URL
|
46
44
|
|
47
45
|
## Stack
|
48
46
|
|
@@ -227,9 +225,57 @@ async for response in solana_agent.process("user123", "Write me a poem.", intern
|
|
227
225
|
print(response, end="")
|
228
226
|
```
|
229
227
|
|
230
|
-
|
228
|
+
### Customize Audio Voice
|
231
229
|
|
232
|
-
|
230
|
+
This is an audio to audio example using the `audio_instructions` parameter.
|
231
|
+
|
232
|
+
```python
|
233
|
+
async for response in solana_agent.process("user123", audio_content, output_format="audio", audio_voice="nova", audio_input_format="webm", audio_output_format="aac", audio_instructions="You speak with an American southern accent"):
|
234
|
+
print(response, end="")
|
235
|
+
```
|
236
|
+
|
237
|
+
## Tools
|
238
|
+
|
239
|
+
Tools can be used from plugins like Solana Agent Kit (sakit) or via custom inline tools. Tools available via plugins integrate automatically with Solana Agent.
|
240
|
+
|
241
|
+
### Plugin Usage Example
|
242
|
+
|
243
|
+
`pip install sakit`
|
244
|
+
|
245
|
+
```python
|
246
|
+
from solana_agent import SolanaAgent
|
247
|
+
|
248
|
+
config = {
|
249
|
+
"openai": {
|
250
|
+
"api_key": "your-openai-api-key",
|
251
|
+
},
|
252
|
+
"tools": {
|
253
|
+
"search_internet": {
|
254
|
+
"api_key": "your-perplexity-api-key",
|
255
|
+
},
|
256
|
+
},
|
257
|
+
"agents": [
|
258
|
+
{
|
259
|
+
"name": "research_specialist",
|
260
|
+
"instructions": "You are an expert researcher who synthesizes complex information clearly. You use your search_internet tool to get the latest information.",
|
261
|
+
"specialization": "Research and knowledge synthesis",
|
262
|
+
"tools": ["search_internet"],
|
263
|
+
},
|
264
|
+
{
|
265
|
+
"name": "customer_support",
|
266
|
+
"instructions": "You provide friendly, helpful customer support responses.",
|
267
|
+
"specialization": "Customer inquiries",
|
268
|
+
}
|
269
|
+
],
|
270
|
+
}
|
271
|
+
|
272
|
+
solana_agent = SolanaAgent(config=config)
|
273
|
+
|
274
|
+
async for response in solana_agent.process("user123", "What are the latest AI developments?", internet_search=False):
|
275
|
+
print(response, end="")
|
276
|
+
```
|
277
|
+
|
278
|
+
### Custom Inline Tool Example
|
233
279
|
|
234
280
|
```python
|
235
281
|
from solana_agent import SolanaAgent
|
@@ -309,9 +355,11 @@ async for response in solana_agent.process("user123", "What are the latest AI de
|
|
309
355
|
print(response, end="")
|
310
356
|
```
|
311
357
|
|
312
|
-
|
358
|
+
## Training your Agents
|
313
359
|
|
314
|
-
|
360
|
+
Many use-cases for Solana Agent require training your agents on your company data.
|
361
|
+
|
362
|
+
This can be accomplished via runtime prompt injection. Integrations that work well with this method are KBs like Pinecone and FAQs.
|
315
363
|
|
316
364
|
```python
|
317
365
|
from solana_agent import SolanaAgent
|
@@ -336,11 +384,13 @@ config = {
|
|
336
384
|
|
337
385
|
solana_agent = SolanaAgent(config=config)
|
338
386
|
|
339
|
-
async for response in solana_agent.process("user123", "What are the latest AI developments?", "
|
387
|
+
async for response in solana_agent.process("user123", "What are the latest AI developments?", "This is my FAQ"):
|
340
388
|
print(response, end="")
|
341
389
|
```
|
342
390
|
|
343
|
-
|
391
|
+
## Custom Routing
|
392
|
+
|
393
|
+
In advanced cases like implementing a ticketing system on-top of Solana Agent - you can use your own router.
|
344
394
|
|
345
395
|
```python
|
346
396
|
from solana_agent import SolanaAgent
|
@@ -22,12 +22,12 @@ class OpenAIAdapter(LLMProvider):
|
|
22
22
|
self.text_model = "gpt-4o-mini"
|
23
23
|
self.internet_search_model = "gpt-4o-mini-search-preview"
|
24
24
|
self.transcription_model = "gpt-4o-mini-transcribe"
|
25
|
-
self.tts_model = "tts
|
25
|
+
self.tts_model = "gpt-4o-mini-tts"
|
26
26
|
|
27
27
|
async def tts(
|
28
28
|
self,
|
29
29
|
text: str,
|
30
|
-
instructions: str = "",
|
30
|
+
instructions: str = "You speak in a friendly and helpful manner.",
|
31
31
|
voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
32
32
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
33
33
|
response_format: Literal['mp3', 'opus',
|
@@ -45,16 +45,16 @@ class OpenAIAdapter(LLMProvider):
|
|
45
45
|
Audio bytes as they become available
|
46
46
|
"""
|
47
47
|
try:
|
48
|
-
|
48
|
+
with self.client.audio.speech.with_streaming_response.create(
|
49
49
|
model=self.tts_model,
|
50
50
|
voice=voice,
|
51
|
+
instructions=instructions,
|
51
52
|
input=text,
|
52
53
|
response_format=response_format
|
53
|
-
)
|
54
|
-
|
55
|
-
|
56
|
-
|
57
|
-
yield chunk
|
54
|
+
) as stream:
|
55
|
+
# Stream the bytes in 16KB chunks
|
56
|
+
for chunk in stream.iter_bytes(chunk_size=1024 * 16):
|
57
|
+
yield chunk
|
58
58
|
|
59
59
|
except Exception as e:
|
60
60
|
print(f"Error in text_to_speech: {str(e)}")
|
@@ -66,7 +66,7 @@ class OpenAIAdapter(LLMProvider):
|
|
66
66
|
print(f"Error in text_to_speech: {str(e)}")
|
67
67
|
import traceback
|
68
68
|
print(traceback.format_exc())
|
69
|
-
yield
|
69
|
+
yield b"" # Return empty bytes on error
|
70
70
|
|
71
71
|
async def transcribe_audio(
|
72
72
|
self,
|
@@ -85,16 +85,14 @@ class OpenAIAdapter(LLMProvider):
|
|
85
85
|
Transcript text chunks as they become available
|
86
86
|
"""
|
87
87
|
try:
|
88
|
-
|
88
|
+
with self.client.audio.transcriptions.with_streaming_response.create(
|
89
89
|
model=self.transcription_model,
|
90
90
|
file=(f"file.{input_format}", audio_bytes),
|
91
91
|
response_format="text",
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
if hasattr(event, 'text') and event.text:
|
97
|
-
yield event.text
|
92
|
+
) as stream:
|
93
|
+
# Stream the text in 16KB chunks
|
94
|
+
for chunk in stream.iter_text(chunk_size=1024 * 16):
|
95
|
+
yield chunk
|
98
96
|
|
99
97
|
except Exception as e:
|
100
98
|
print(f"Error in transcribe_audio: {str(e)}")
|
@@ -49,7 +49,7 @@ class SolanaAgent(SolanaAgentInterface):
|
|
49
49
|
output_format: Literal["text", "audio"] = "text",
|
50
50
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
51
51
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
52
|
-
audio_instructions:
|
52
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
53
53
|
audio_output_format: Literal['mp3', 'opus',
|
54
54
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
55
55
|
audio_input_format: Literal[
|
@@ -66,7 +66,7 @@ class SolanaAgent(SolanaAgentInterface):
|
|
66
66
|
prompt: Optional prompt for the agent
|
67
67
|
output_format: Response format ("text" or "audio")
|
68
68
|
audio_voice: Voice to use for audio output
|
69
|
-
audio_instructions:
|
69
|
+
audio_instructions: Audio voice instructions
|
70
70
|
audio_output_format: Audio output format
|
71
71
|
audio_input_format: Audio input format
|
72
72
|
router: Optional routing service for processing
|
@@ -17,7 +17,7 @@ class SolanaAgent(ABC):
|
|
17
17
|
output_format: Literal["text", "audio"] = "text",
|
18
18
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
19
19
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
20
|
-
audio_instructions:
|
20
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
21
21
|
audio_output_format: Literal['mp3', 'opus',
|
22
22
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
23
23
|
audio_input_format: Literal[
|
@@ -31,7 +31,7 @@ class LLMProvider(ABC):
|
|
31
31
|
async def tts(
|
32
32
|
self,
|
33
33
|
text: str,
|
34
|
-
instructions: str = "",
|
34
|
+
instructions: str = "You speak in a friendly and helpful manner.",
|
35
35
|
voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
36
36
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
37
37
|
response_format: Literal['mp3', 'opus',
|
@@ -27,7 +27,7 @@ class AgentService(ABC):
|
|
27
27
|
output_format: Literal["text", "audio"] = "text",
|
28
28
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
29
29
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
30
|
-
audio_instructions:
|
30
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
31
31
|
audio_output_format: Literal['mp3', 'opus',
|
32
32
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
33
33
|
audio_input_format: Literal[
|
@@ -13,7 +13,7 @@ class QueryService(ABC):
|
|
13
13
|
output_format: Literal["text", "audio"] = "text",
|
14
14
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
15
15
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
16
|
-
audio_instructions:
|
16
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
17
17
|
audio_output_format: Literal['mp3', 'opus',
|
18
18
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
19
19
|
audio_input_format: Literal[
|
@@ -5,6 +5,7 @@ This service manages AI and human agents, their registration, tool assignments,
|
|
5
5
|
and response generation.
|
6
6
|
"""
|
7
7
|
import asyncio
|
8
|
+
from copy import deepcopy
|
8
9
|
import datetime as main_datetime
|
9
10
|
from datetime import datetime
|
10
11
|
import json
|
@@ -169,7 +170,7 @@ class AgentService(AgentServiceInterface):
|
|
169
170
|
output_format: Literal["text", "audio"] = "text",
|
170
171
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
171
172
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
172
|
-
audio_instructions:
|
173
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
173
174
|
audio_output_format: Literal['mp3', 'opus',
|
174
175
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
175
176
|
audio_input_format: Literal[
|
@@ -199,12 +200,8 @@ class AgentService(AgentServiceInterface):
|
|
199
200
|
else:
|
200
201
|
query_text = query
|
201
202
|
|
202
|
-
# Get system prompt
|
203
|
+
# Get system prompt
|
203
204
|
system_prompt = self.get_agent_system_prompt(agent_name)
|
204
|
-
if self.tool_registry:
|
205
|
-
tool_usage_prompt = self._get_tool_usage_prompt(agent_name)
|
206
|
-
if tool_usage_prompt:
|
207
|
-
system_prompt = f"{system_prompt}\n\n{tool_usage_prompt}"
|
208
205
|
|
209
206
|
# Add User ID and memory context
|
210
207
|
system_prompt += f"\n\nUser ID: {user_id}"
|
@@ -213,6 +210,13 @@ class AgentService(AgentServiceInterface):
|
|
213
210
|
if prompt:
|
214
211
|
system_prompt += f"\n\nADDITIONAL PROMPT: {prompt}"
|
215
212
|
|
213
|
+
# make tool calling prompt
|
214
|
+
tool_calling_system_prompt = deepcopy(system_prompt)
|
215
|
+
if self.tool_registry:
|
216
|
+
tool_usage_prompt = self._get_tool_usage_prompt(agent_name)
|
217
|
+
if tool_usage_prompt:
|
218
|
+
tool_calling_system_prompt += f"\n\nTOOL CALLING PROMPT: {tool_usage_prompt}"
|
219
|
+
|
216
220
|
# Variables for tracking the response
|
217
221
|
complete_text_response = ""
|
218
222
|
|
@@ -226,7 +230,7 @@ class AgentService(AgentServiceInterface):
|
|
226
230
|
# Generate and stream response
|
227
231
|
async for chunk in self.llm_provider.generate_text(
|
228
232
|
prompt=query_text,
|
229
|
-
system_prompt=
|
233
|
+
system_prompt=tool_calling_system_prompt,
|
230
234
|
internet_search=internet_search,
|
231
235
|
):
|
232
236
|
# Check if the chunk is JSON or a tool call
|
@@ -276,7 +280,7 @@ class AgentService(AgentServiceInterface):
|
|
276
280
|
tool_response += processed_chunk
|
277
281
|
|
278
282
|
# Add to our complete text record and full audio buffer
|
279
|
-
tool_response = self.
|
283
|
+
tool_response = self._clean_for_audio(
|
280
284
|
tool_response)
|
281
285
|
complete_text_response += tool_response
|
282
286
|
full_response_buffer += tool_response
|
@@ -318,8 +322,8 @@ class AgentService(AgentServiceInterface):
|
|
318
322
|
|
319
323
|
# For audio output, now process the complete response
|
320
324
|
if output_format == "audio" and full_response_buffer:
|
321
|
-
# Clean
|
322
|
-
full_response_buffer = self.
|
325
|
+
# Clean text before TTS
|
326
|
+
full_response_buffer = self._clean_for_audio(
|
323
327
|
full_response_buffer)
|
324
328
|
|
325
329
|
# Process the entire response with TTS
|
@@ -427,14 +431,14 @@ class AgentService(AgentServiceInterface):
|
|
427
431
|
- Use exact tool names as shown in AVAILABLE TOOLS
|
428
432
|
"""
|
429
433
|
|
430
|
-
def
|
431
|
-
"""Remove Markdown formatting and
|
434
|
+
def _clean_for_audio(self, text: str) -> str:
|
435
|
+
"""Remove Markdown formatting, emojis, and non-pronounceable characters from text.
|
432
436
|
|
433
437
|
Args:
|
434
|
-
text: Input text with potential Markdown formatting
|
438
|
+
text: Input text with potential Markdown formatting and special characters
|
435
439
|
|
436
440
|
Returns:
|
437
|
-
Clean text without Markdown
|
441
|
+
Clean text without Markdown, emojis, and special characters
|
438
442
|
"""
|
439
443
|
import re
|
440
444
|
|
@@ -469,4 +473,34 @@ class AgentService(AgentServiceInterface):
|
|
469
473
|
# Remove multiple consecutive newlines (keep just one)
|
470
474
|
text = re.sub(r'\n{3,}', '\n\n', text)
|
471
475
|
|
476
|
+
# Remove emojis and other non-pronounceable characters
|
477
|
+
# Common emoji Unicode ranges
|
478
|
+
emoji_pattern = re.compile(
|
479
|
+
"["
|
480
|
+
"\U0001F600-\U0001F64F" # emoticons
|
481
|
+
"\U0001F300-\U0001F5FF" # symbols & pictographs
|
482
|
+
"\U0001F680-\U0001F6FF" # transport & map symbols
|
483
|
+
"\U0001F700-\U0001F77F" # alchemical symbols
|
484
|
+
"\U0001F780-\U0001F7FF" # Geometric Shapes
|
485
|
+
"\U0001F800-\U0001F8FF" # Supplemental Arrows-C
|
486
|
+
"\U0001F900-\U0001F9FF" # Supplemental Symbols and Pictographs
|
487
|
+
"\U0001FA00-\U0001FA6F" # Chess Symbols
|
488
|
+
"\U0001FA70-\U0001FAFF" # Symbols and Pictographs Extended-A
|
489
|
+
"\U00002702-\U000027B0" # Dingbats
|
490
|
+
"\U000024C2-\U0000257F" # Enclosed characters
|
491
|
+
"\U00002600-\U000026FF" # Miscellaneous Symbols
|
492
|
+
"\U00002700-\U000027BF" # Dingbats
|
493
|
+
"\U0000FE00-\U0000FE0F" # Variation Selectors
|
494
|
+
"\U0001F1E0-\U0001F1FF" # Flags (iOS)
|
495
|
+
"]+",
|
496
|
+
flags=re.UNICODE
|
497
|
+
)
|
498
|
+
text = emoji_pattern.sub(r' ', text)
|
499
|
+
|
500
|
+
# Replace special characters that can cause issues with TTS
|
501
|
+
text = re.sub(r'[^\w\s\.\,\;\:\?\!\'\"\-\(\)]', ' ', text)
|
502
|
+
|
503
|
+
# Replace multiple spaces with a single space
|
504
|
+
text = re.sub(r'\s+', ' ', text)
|
505
|
+
|
472
506
|
return text.strip()
|
@@ -41,7 +41,7 @@ class QueryService(QueryServiceInterface):
|
|
41
41
|
output_format: Literal["text", "audio"] = "text",
|
42
42
|
audio_voice: Literal["alloy", "ash", "ballad", "coral", "echo",
|
43
43
|
"fable", "onyx", "nova", "sage", "shimmer"] = "nova",
|
44
|
-
audio_instructions:
|
44
|
+
audio_instructions: str = "You speak in a friendly and helpful manner.",
|
45
45
|
audio_output_format: Literal['mp3', 'opus',
|
46
46
|
'aac', 'flac', 'wav', 'pcm'] = "aac",
|
47
47
|
audio_input_format: Literal[
|
@@ -58,7 +58,7 @@ class QueryService(QueryServiceInterface):
|
|
58
58
|
query: Text query or audio bytes
|
59
59
|
output_format: Response format ("text" or "audio")
|
60
60
|
audio_voice: Voice for TTS (text-to-speech)
|
61
|
-
audio_instructions:
|
61
|
+
audio_instructions: Audio voice instructions
|
62
62
|
audio_output_format: Audio output format
|
63
63
|
audio_input_format: Audio input format
|
64
64
|
prompt: Optional prompt for the agent
|
@@ -84,7 +84,8 @@ class QueryService(QueryServiceInterface):
|
|
84
84
|
async for chunk in self.agent_service.llm_provider.tts(
|
85
85
|
text=response,
|
86
86
|
voice=audio_voice,
|
87
|
-
response_format=audio_output_format
|
87
|
+
response_format=audio_output_format,
|
88
|
+
instructions=audio_instructions,
|
88
89
|
):
|
89
90
|
yield chunk
|
90
91
|
else:
|
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
|
{solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/data_storage.py
RENAMED
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
|