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.
Files changed (35) hide show
  1. {solana_agent-22.0.0 → solana_agent-22.0.5}/PKG-INFO +59 -9
  2. {solana_agent-22.0.0 → solana_agent-22.0.5}/README.md +58 -8
  3. {solana_agent-22.0.0 → solana_agent-22.0.5}/pyproject.toml +1 -1
  4. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/llm_adapter.py +14 -16
  5. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/client/solana_agent.py +2 -2
  6. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/client/client.py +1 -1
  7. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/llm.py +1 -1
  8. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/agent.py +1 -1
  9. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/query.py +1 -1
  10. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/agent.py +48 -14
  11. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/query.py +4 -3
  12. {solana_agent-22.0.0 → solana_agent-22.0.5}/LICENSE +0 -0
  13. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/__init__.py +0 -0
  14. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/__init__.py +0 -0
  15. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/adapters/mongodb_adapter.py +0 -0
  16. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/client/__init__.py +0 -0
  17. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/__init__.py +0 -0
  18. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/agent.py +0 -0
  19. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/domains/routing.py +0 -0
  20. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/factories/__init__.py +0 -0
  21. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/factories/agent_factory.py +0 -0
  22. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/__init__.py +0 -0
  23. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/plugins/plugins.py +0 -0
  24. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/data_storage.py +0 -0
  25. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/providers/memory.py +0 -0
  26. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/interfaces/services/routing.py +0 -0
  27. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/__init__.py +0 -0
  28. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/manager.py +0 -0
  29. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/registry.py +0 -0
  30. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/tools/__init__.py +0 -0
  31. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/plugins/tools/auto_tool.py +0 -0
  32. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/repositories/__init__.py +0 -0
  33. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/repositories/memory.py +0 -0
  34. {solana_agent-22.0.0 → solana_agent-22.0.5}/solana_agent/services/__init__.py +0 -0
  35. {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.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
- ## Advanced
252
+ ### Customize Audio Voice
255
253
 
256
- ### Custom Inline Tools
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
- ### Custom Prompt Injection at Runtime
382
+ ## Training your Agents
337
383
 
338
- Useful for Knowledge Base answers and FAQs
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?", "Always end your sentences with eh?"):
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
- ### Custom Routing
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
- ## Advanced
228
+ ### Customize Audio Voice
231
229
 
232
- ### Custom Inline Tools
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
- ### Custom Prompt Injection at Runtime
358
+ ## Training your Agents
313
359
 
314
- Useful for Knowledge Base answers and FAQs
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?", "Always end your sentences with eh?"):
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
- ### Custom Routing
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
@@ -1,6 +1,6 @@
1
1
  [tool.poetry]
2
2
  name = "solana-agent"
3
- version = "22.0.0"
3
+ version = "22.0.5"
4
4
  description = "Agentic IQ"
5
5
  authors = ["Bevan Hunt <bevan@bevanhunt.com>"]
6
6
  license = "MIT"
@@ -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-1"
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
- stream = self.client.audio.speech.create(
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
- # Stream the bytes in chunks
56
- for chunk in stream.iter_bytes(chunk_size=1024 * 16): # 16KB chunks
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 f"I apologize, but I encountered an error converting text to speech: {str(e)}"
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
- stream = self.client.audio.transcriptions.create(
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
- stream=True
93
- )
94
-
95
- for event in stream:
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: Optional[str] = None,
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: Not used currently
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: Optional[str] = None,
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: Optional[str] = None,
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: Optional[str] = None,
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: Optional[str] = None,
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 and add tool instructions
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=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._remove_markdown(
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 markdown before TTS
322
- full_response_buffer = self._remove_markdown(
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 _remove_markdown(self, text: str) -> str:
431
- """Remove Markdown formatting and links from text.
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 formatting
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: Optional[str] = None,
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: Optional instructions for TTS
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