diff --git a/sijapi/__init__.py b/sijapi/__init__.py index 4ab340d..bec4a4f 100644 --- a/sijapi/__init__.py +++ b/sijapi/__init__.py @@ -78,10 +78,6 @@ DAY_SHORT_FMT = os.getenv("DAY_SHORT_FMT") # Large language model LLM_URL = os.getenv("LLM_URL", "http://localhost:11434") LLM_SYS_MSG = os.getenv("SYSTEM_MSG", "You are a helpful AI assistant.") -DEFAULT_LLM = os.getenv("DEFAULT_LLM", "llama3") -DEFAULT_VISION = os.getenv("DEFAULT_VISION", "llava") -DEFAULT_VOICE = os.getenv("DEFAULT_VOICE", "Luna") -DEFAULT_11L_VOICE = os.getenv("DEFAULT_11L_VOICE", "Victoria") OPENAI_API_KEY = os.getenv("OPENAI_API_KEY") # Summarization @@ -118,8 +114,6 @@ TTS_DIR = DATA_DIR / "tts" os.makedirs(TTS_DIR, exist_ok=True) VOICE_DIR = TTS_DIR / 'voices' os.makedirs(VOICE_DIR, exist_ok=True) -PODCAST_DIR = os.getenv("PODCAST_DIR", TTS_DIR / "sideloads") -os.makedirs(PODCAST_DIR, exist_ok=True) TTS_OUTPUT_DIR = TTS_DIR / 'outputs' os.makedirs(TTS_OUTPUT_DIR, exist_ok=True) TTS_SEGMENTS_DIR = TTS_DIR / 'segments' diff --git a/sijapi/config/.env-example b/sijapi/config/.env-example index d293ccc..51c3a18 100644 --- a/sijapi/config/.env-example +++ b/sijapi/config/.env-example @@ -323,8 +323,6 @@ MS365_REDIRECT_PATH=¿SECRET? # <--- e.g. http://localhost:4444/MS365/oauth #─── via comfyui (stable diffusion): ─────── S̝͖̦͓̪̻ O̡͖̘̫͇̟ H̢͔͔̫͉͜ O̢̢͉̞͍̘ T̟͍͍̪̦̞ R I G H T N O W LLM_URL=http://localhost:11434 SYSTEM_MSG=You are a helpful AI assistant. -DEFAULT_LLM=dolphin-mistral -DEFAULT_VISION=llava-llama3 OPENAI_API_KEY=¿SECRET? # <--- not presently implemented for anything SUMMARY_MODEL='command-r:latest' SUMMARY_CHUNK_SIZE=16384 @@ -335,7 +333,6 @@ SUMMARY_MIN_LENGTH=64 SUMMARY_TOKEN_LIMIT=16384 SUMMARY_INSTRUCT='You are an AI assistant that provides accurate summaries of text -- nothing more and nothing less. You must not include ANY extraneous text other than the sumary. Do not include comments apart from the summary, do not preface the summary, and do not provide any form of postscript. Do not add paragraph breaks. Do not add any kind of formatting. Your response should begin with, consist of, and end with an accurate plaintext summary.' SUMMARY_INSTRUCT_TTS='You are an AI assistant that summarizes emails -- nothing more and nothing less. You must not include ANY extraneous text other than the sumary. Do not include comments apart from the summary, do not preface the summary, and do not provide any form of postscript. Do not add paragraph breaks. Do not add any kind of formatting. Your response should begin with, consist of, and end with an accurate plaintext summary. Your response will undergo Text-To-Speech conversion and added to Sanjays private podcast. Providing adequate context (Sanjay did not send this question to you, he will only hear your response) but aiming for conciseness and precision, and bearing in mind the Text-To-Speech conversion (avoiding acronyms and formalities), summarize the following.' -DEFAULT_VOICE=joanne WHISPER_CPP_DIR='whisper.cpp' WHISPER_CPP_MODELS=tiny,base,base-en,small,medium,medium-en,large-v3 WEBCLIPPER_TTS=elevenlabs @@ -351,9 +348,6 @@ DAY_SHORT_FMT="%Y-%m-%d" # designed for use with `ollama`, but most of the functionality should be equal with # LM Studio, LocalAI, ect... # -# DEFAULT_LLM is self-explanatory; DEFAULT_VISION is used for image recognition within -# a multimodal chat context, such as on the ig module for generating intelligible -# comments to Instagram posts, or more realistic captions for img-generated images. # # Note it's possible to specify a separate model for general purposes and for # summarization tasks. The other SUMMARY_ variables call for some explanation, @@ -391,8 +385,6 @@ DAY_SHORT_FMT="%Y-%m-%d" # tts output was requested; tends to yield "cleaner" audio # with less numbers (page numbers, citations) and other # information extraneous to spoken contexts. -# -# DEFAULT_VOICE: used for all tts tasks when a specific voice is not requested. # # ────────── # diff --git a/sijapi/routers/archivist.py b/sijapi/routers/archivist.py index fff4ea5..60afd66 100644 --- a/sijapi/routers/archivist.py +++ b/sijapi/routers/archivist.py @@ -30,7 +30,7 @@ from urllib3.util.retry import Retry from datetime import datetime as dt_datetime from better_profanity import profanity from sijapi.utilities import html_to_markdown, sanitize_filename, assemble_journal_path, assemble_archive_path, contains_profanity, is_ad_or_tracker, initialize_adblock_rules, contains_blacklisted_word -from sijapi import L, API, Archivist, BLOCKLISTS_DIR, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR, DEFAULT_11L_VOICE, DEFAULT_VOICE +from sijapi import L, API, Archivist, BLOCKLISTS_DIR, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR archivist = APIRouter() diff --git a/sijapi/routers/email.py b/sijapi/routers/email.py index adfe790..9e3bd34 100644 --- a/sijapi/routers/email.py +++ b/sijapi/routers/email.py @@ -22,7 +22,7 @@ import ssl import yaml from typing import List, Dict, Optional, Set from datetime import datetime as dt_datetime -from sijapi import L, PODCAST_DIR, DEFAULT_VOICE, EMAIL_CONFIG, EMAIL_LOGS +from sijapi import L, Dir, EMAIL_CONFIG, EMAIL_LOGS from sijapi.routers import gis, img, tts, llm from sijapi.utilities import clean_text, assemble_journal_path, extract_text, prefix_lines from sijapi.classes import EmailAccount, IMAPConfig, SMTPConfig, IncomingEmail, EmailContact, AutoResponder @@ -205,7 +205,7 @@ async def summarize_single_email(this_email: IncomingEmail, podcast: bool = Fals attachment_texts = await extract_attachments(this_email.attachments) email_content += "\n—--\n" + "\n—--\n".join([f"Attachment: {text}" for text in attachment_texts]) summary = await llm.summarize_text(email_content) - await tts.local_tts(text_content = summary, speed = 1.1, voice = DEFAULT_VOICE, podcast = podcast, output_path = tts_path) + await tts.local_tts(text_content = summary, speed = 1.1, voice = Tts.xtts.default, podcast = podcast, output_path = tts_path) md_summary = f'```ad.summary\n' md_summary += f'title: {this_email.subject}\n' md_summary += f'{summary}\n' diff --git a/sijapi/routers/llm.py b/sijapi/routers/llm.py index 63dcff6..f827855 100644 --- a/sijapi/routers/llm.py +++ b/sijapi/routers/llm.py @@ -26,7 +26,7 @@ import tempfile import shutil import html2text import markdown -from sijapi import L, LLM_SYS_MSG, DEFAULT_LLM, DEFAULT_VISION, REQUESTS_DIR, OBSIDIAN_CHROMADB_COLLECTION, OBSIDIAN_VAULT_DIR, DOC_DIR, OPENAI_API_KEY, DEFAULT_VOICE, SUMMARY_INSTRUCT, SUMMARY_CHUNK_SIZE, SUMMARY_TPW, SUMMARY_CHUNK_OVERLAP, SUMMARY_LENGTH_RATIO, SUMMARY_TOKEN_LIMIT, SUMMARY_MIN_LENGTH, SUMMARY_MODEL +from sijapi import L, LLM_SYS_MSG, REQUESTS_DIR, OBSIDIAN_CHROMADB_COLLECTION, OBSIDIAN_VAULT_DIR, DOC_DIR, OPENAI_API_KEY, SUMMARY_INSTRUCT, SUMMARY_CHUNK_SIZE, SUMMARY_TPW, SUMMARY_CHUNK_OVERLAP, SUMMARY_LENGTH_RATIO, SUMMARY_TOKEN_LIMIT, SUMMARY_MIN_LENGTH, SUMMARY_MODEL from sijapi.utilities import convert_to_unix_time, sanitize_filename, ocr_pdf, clean_text, should_use_ocr, extract_text_from_pdf, extract_text_from_docx, read_text_file, str_to_bool, get_extension from sijapi.routers import tts from sijapi.routers.asr import transcribe_audio @@ -87,7 +87,7 @@ async def generate_response(prompt: str): return {"response": output['response']} -async def query_ollama(usr: str, sys: str = LLM_SYS_MSG, model: str = DEFAULT_LLM, max_tokens: int = 200): +async def query_ollama(usr: str, sys: str = LLM_SYS_MSG, model: str = Llm.chat.model, max_tokens: int = 200): messages = [{"role": "system", "content": sys}, {"role": "user", "content": usr}] LLM = Ollama() @@ -105,7 +105,7 @@ async def query_ollama(usr: str, sys: str = LLM_SYS_MSG, model: str = DEFAULT_LL async def query_ollama_multishot( message_list: List[str], sys: str = LLM_SYS_MSG, - model: str = DEFAULT_LLM, + model: str = Llm.chat.model, max_tokens: int = 200 ): if len(message_list) % 2 == 0: @@ -231,9 +231,9 @@ async def stream_messages_with_vision(message: dict, model: str, num_predict: in def get_appropriate_model(requested_model): if requested_model == "gpt-4-vision-preview": - return DEFAULT_VISION + return Llm.vision.model elif not is_model_available(requested_model): - return DEFAULT_LLM + return Llm.chat.model else: return requested_model @@ -314,7 +314,7 @@ async def chat_completions_options(request: Request): ], "created": int(time.time()), "id": str(uuid.uuid4()), - "model": DEFAULT_LLM, + "model": Llm.chat.model, "object": "chat.completion.chunk", }, status_code=200, @@ -533,7 +533,7 @@ async def summarize_tts_endpoint( instruction: str = Form(SUMMARY_INSTRUCT), file: Optional[UploadFile] = File(None), text: Optional[str] = Form(None), - voice: Optional[str] = Form(DEFAULT_VOICE), + voice: Optional[str] = Form(None), speed: Optional[float] = Form(1.2), podcast: Union[bool, str] = Form(False) ): @@ -577,7 +577,7 @@ async def summarize_tts_endpoint( async def summarize_tts( text: str, instruction: str = SUMMARY_INSTRUCT, - voice: Optional[str] = DEFAULT_VOICE, + voice: Optional[str] = None, speed: float = 1.1, podcast: bool = False, LLM: Ollama = None diff --git a/sijapi/routers/news.py b/sijapi/routers/news.py index b8276a7..80f35e3 100644 --- a/sijapi/routers/news.py +++ b/sijapi/routers/news.py @@ -18,7 +18,7 @@ from markdownify import markdownify as md from better_profanity import profanity from fastapi import APIRouter, BackgroundTasks, UploadFile, Form, HTTPException, Query, Path as FastAPIPath from pathlib import Path -from sijapi import L, News, Archivist, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR, DEFAULT_11L_VOICE, DEFAULT_VOICE +from sijapi import L, News, Archivist, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR from sijapi.utilities import html_to_markdown, download_file, sanitize_filename, assemble_journal_path, assemble_archive_path, contains_profanity, is_ad_or_tracker from sijapi.routers import gis, llm, tts, note @@ -37,7 +37,7 @@ async def clip_post( url: str = Form(...), title: Optional[str] = Form(None), tts: str = Form('summary'), - voice: str = Form(DEFAULT_VOICE), + voice: str = Form(None), ): result = await process_and_save_article(bg_tasks, url, title, tts, voice) return {"message": "Clip saved successfully", "result": result} @@ -46,7 +46,7 @@ async def clip_post( async def clip_get( bg_tasks: BackgroundTasks, url: str, - voice: str = Query(DEFAULT_VOICE) + voice: str = Query(None) ): result = await process_and_save_article(bg_tasks, url, None, tts, voice) return {"message": "Clip saved successfully", "result": result} @@ -124,7 +124,7 @@ async def process_news_site(site, bg_tasks: BackgroundTasks): earliest_date, bg_tasks, tts_mode=site.tts if hasattr(site, 'tts') else "off", - voice=site.voice if hasattr(site, 'voice') else DEFAULT_11L_VOICE + voice=site.voice if hasattr(site, 'voice') else Tts.elevenlabs.default )) tasks.append(task) @@ -136,7 +136,7 @@ async def process_news_site(site, bg_tasks: BackgroundTasks): err(f"Error processing {site.name}: {str(e)}") -async def download_and_save_article(article, site_name, earliest_date, bg_tasks: BackgroundTasks, tts_mode: str = "off", voice: str = DEFAULT_11L_VOICE): +async def download_and_save_article(article, site_name, earliest_date, bg_tasks: BackgroundTasks, tts_mode: str = "off", voice: str = Tts.elevenlabs.default): try: url = article.url parsed_article = await fetch_and_parse_article(url) @@ -156,7 +156,7 @@ async def process_and_save_article( url: str, title: Optional[str] = None, tts_mode: str = "summary", - voice: str = DEFAULT_VOICE, + voice: str = Tts.elevenlabs.default, site_name: Optional[str] = None ) -> str: diff --git a/sijapi/routers/note.py b/sijapi/routers/note.py index 6badbd9..5f8dae0 100644 --- a/sijapi/routers/note.py +++ b/sijapi/routers/note.py @@ -17,7 +17,7 @@ from dateutil.parser import parse as dateutil_parse from fastapi import HTTPException, status from pathlib import Path from fastapi import APIRouter, Query, HTTPException -from sijapi import API, L, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR, OBSIDIAN_BANNER_SCENE, DEFAULT_11L_VOICE, DEFAULT_VOICE, GEO +from sijapi import API, L, OBSIDIAN_VAULT_DIR, OBSIDIAN_RESOURCES_DIR, OBSIDIAN_BANNER_SCENE, GEO from sijapi.routers import asr, cal, gis, img, llm, serve, timing, tts, weather from sijapi.utilities import assemble_journal_path, convert_to_12_hour_format, sanitize_filename, convert_degrees_to_cardinal, check_file_name, HOURLY_COLUMNS_MAPPING from sijapi.classes import Location @@ -122,7 +122,7 @@ async def process_document( document: File, title: Optional[str] = None, tts_mode: str = "summary", - voice: str = DEFAULT_VOICE + voice: str = None, ): timestamp = dt_datetime.now().strftime('%b %d, %Y at %H:%M') diff --git a/sijapi/routers/tts.py b/sijapi/routers/tts.py index 00cb814..7eb998c 100644 --- a/sijapi/routers/tts.py +++ b/sijapi/routers/tts.py @@ -488,10 +488,10 @@ def copy_to_podcast_dir(file_path): # Extract the file name from the file path file_name = Path(file_path).name - # Construct the destination path in the PODCAST_DIR + # Construct the destination path in the podcast folder destination_path = Path(Dir.PODCAST) / file_name - # Copy the file to the PODCAST_DIR + # Copy the file to the podcast folder shutil.copy(file_path, destination_path) print(f"File copied successfully to {destination_path}")