ragV98 commited on
Commit
c8b3b66
Β·
1 Parent(s): c8c2401

switching to tinyllama

Browse files
components/LLMs/Mistral.py ADDED
@@ -0,0 +1,39 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ import requests
3
+ from typing import Optional
4
+
5
+ # πŸ” Load HF credentials and endpoint URL from environment variables
6
+ HF_TOKEN = os.environ.get("HF_TOKEN")
7
+ MISTRAL_URL = os.environ.get("MISTRAL_URL")
8
+
9
+ # πŸ“œ Headers for HF Inference Endpoint
10
+ HEADERS = {
11
+ "Authorization": f"Bearer {HF_TOKEN}",
12
+ "Content-Type": "application/json"
13
+ }
14
+
15
+ # πŸ” Call Mistral using HF Inference Endpoint
16
+ def call_mistral(base_prompt: str, tail_prompt: str) -> Optional[str]:
17
+ full_prompt = f"<s>[INST]{base_prompt}\n\n{tail_prompt}[/INST]</s>"
18
+ payload = {
19
+ "inputs": full_prompt
20
+ }
21
+
22
+ try:
23
+ response = requests.post(MISTRAL_URL, headers=HEADERS, json=payload, timeout=20)
24
+ response.raise_for_status()
25
+ data = response.json()
26
+
27
+ raw_output = ""
28
+ if isinstance(data, list) and data:
29
+ raw_output = data[0].get("generated_text", "")
30
+ elif isinstance(data, dict):
31
+ raw_output = data.get("generated_text", "")
32
+
33
+ if "[/INST]</s>" in raw_output:
34
+ return raw_output.split("[/INST]</s>")[-1].strip()
35
+ return raw_output.strip()
36
+
37
+ except Exception as e:
38
+ print(f"⚠️ Mistral error: {e}")
39
+ return None
components/LLMs/TinyLLama.py ADDED
@@ -0,0 +1,34 @@
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
1
+ import os
2
+ from transformers import pipeline
3
+ from typing import Optional
4
+
5
+ # Load model just once when module is imported
6
+ _tinyllama_pipeline = pipeline(
7
+ "text-generation",
8
+ model="TinyLlama/TinyLlama-1.1B-Chat-v1.0",
9
+ torch_dtype="auto",
10
+ device_map="auto"
11
+ )
12
+
13
+ def call_tinyllama(base_prompt: str, tail_prompt: str, max_new_tokens: int = 256) -> Optional[str]:
14
+ """
15
+ Calls TinyLlama model with an instruction-tuned prompt.
16
+
17
+ Args:
18
+ base_prompt (str): Instruction or system prompt.
19
+ tail_prompt (str): User or content-specific prompt.
20
+ max_new_tokens (int): Max tokens to generate.
21
+
22
+ Returns:
23
+ str or None: The generated summary content.
24
+ """
25
+ prompt = f"<s>[INST]{base_prompt}\n\n{tail_prompt}[/INST]</s>"
26
+ try:
27
+ result = _tinyllama_pipeline(prompt, max_new_tokens=max_new_tokens)
28
+ output = result[0]["generated_text"]
29
+ if "[/INST]" in output:
30
+ return output.split("[/INST]")[-1].strip()
31
+ return output.strip()
32
+ except Exception as e:
33
+ print(f"⚠️ TinyLlama error: {e}")
34
+ return None
components/LLMs/__init__.py ADDED
File without changes
components/generators/daily_feed.py CHANGED
@@ -8,6 +8,8 @@ from llama_index.core import VectorStoreIndex
8
  from llama_index.core.query_engine import RetrieverQueryEngine
9
  from llama_index.core.schema import Document
10
  from llama_index.core.settings import Settings
 
 
11
 
12
  # βœ… Disable implicit LLM usage
13
  Settings.llm = None
@@ -15,8 +17,6 @@ Settings.llm = None
15
  # πŸ” Environment variables
16
  REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
17
  REDIS_KEY = os.environ.get("UPSTASH_REDIS_TOKEN")
18
- MISTRAL_URL = os.environ.get("MISTRAL_URL")
19
- HF_TOKEN = os.environ.get("HF_TOKEN")
20
 
21
  # βœ… Redis client
22
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
@@ -24,67 +24,32 @@ redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
24
  # πŸ“° Topics
25
  TOPICS = ["India news", "World news", "Tech news", "Finance news", "Sports news"]
26
 
27
- # πŸ“œ Headers for HF endpoint
28
- HEADERS = {
29
- "Authorization": f"Bearer {HF_TOKEN}",
30
- "Content-Type": "application/json"
31
- }
32
-
33
- # 🧠 Build Mistral-style instruction prompt
34
- def build_prompt(content: str, topic: str) -> str:
35
- base_instruction = (
36
- "You are Nuse’s official news summarizer β€” insightful, punchy, and always on point.\n"
37
- "Your job is to scan the content below and extract the key news items. For each item, craft a crisp summary (15–20 words). Avoid using any emojis.\n"
38
- "List each summary on a new line starting with a dash (-) and no numbers. This is how Nuse keeps it clean and scannable.\n"
39
- "\n"
40
- "Example format:\n"
41
- "- India stuns Australia in a last-ball thriller at the World Cup finals\n"
42
- "- U.S. imposes sweeping tariffs on Chinese tech giants, rattling global markets\n"
43
- "- Ceasefire breakthrough: Netanyahu (Prime minister of Isreal) bows to pressure after week-long escalation\n"
44
- "\n"
45
- "If you are mentioning a person, include their designation in brackets. For example: Jeff Bezos (Amazon CEO), Narendra Modi (Prime minister of India).\n"
46
- "If you're referencing a post like 'NATO Chief', also include the name of the person who holds the post.\n"
47
- "If you don't find anything useful, don't return anything for that news item.\n"
48
- "Skim through the content and write summaries that are compelling, include essential facts, and feel like strong hook lines.\n"
49
- "Be sharp. Be brief. No fluff. No preambles. Avoid source citations like (U.S. Security Council) or (The New York Times).\n"
50
- "Return only the summary block β€” no extra commentary, no prompt repetition."
51
- )
52
- tail = f"Topic: {topic}\n\n{content.strip()}"
53
- return f"<s>[INST]{base_instruction}\n\n{tail}[/INST]</s>"
54
-
55
- # πŸ” Call Mistral using HF Inference Endpoint
56
- def call_mistral(prompt: str) -> Optional[str]:
57
- payload = {
58
- "inputs": prompt
59
- }
60
-
61
- try:
62
- response = requests.post(MISTRAL_URL, headers=HEADERS, json=payload, timeout=20)
63
- response.raise_for_status()
64
- data = response.json()
65
-
66
- # Get the generated text
67
- raw_output = ""
68
- if isinstance(data, list) and data:
69
- raw_output = data[0].get("generated_text", "")
70
- elif isinstance(data, dict):
71
- raw_output = data.get("generated_text", "")
72
-
73
- if "[/INST]</s>" in raw_output:
74
- return raw_output.split("[/INST]</s>")[-1].strip()
75
- return raw_output.strip()
76
-
77
- except Exception as e:
78
- print(f"⚠️ Mistral error: {e}")
79
- return None
80
 
81
  # βœ‚οΈ Summarize top N documents
82
  def summarize_topic(docs: List[str], topic: str) -> List[Dict]:
83
  feed = []
84
  for doc in docs[:5]:
85
- prompt = build_prompt(doc, topic)
86
- print("\nπŸ“€ Prompt sent to Mistral:\n", prompt[:300], "...\n")
87
- summary_block = call_mistral(prompt)
88
 
89
  if summary_block:
90
  for line in summary_block.splitlines():
@@ -123,4 +88,4 @@ def generate_and_cache_daily_feed(documents: List[Document]):
123
  # πŸ“¦ For testing or API access
124
  def get_cached_daily_feed():
125
  cached = redis_client.get(REDIS_KEY)
126
- return json.loads(cached) if cached else []
 
8
  from llama_index.core.query_engine import RetrieverQueryEngine
9
  from llama_index.core.schema import Document
10
  from llama_index.core.settings import Settings
11
+ from components.LLMs.Mistral import call_mistral
12
+ from components.LLMs.TinyLLama import call_tinyllama
13
 
14
  # βœ… Disable implicit LLM usage
15
  Settings.llm = None
 
17
  # πŸ” Environment variables
18
  REDIS_URL = os.environ.get("UPSTASH_REDIS_URL", "redis://localhost:6379")
19
  REDIS_KEY = os.environ.get("UPSTASH_REDIS_TOKEN")
 
 
20
 
21
  # βœ… Redis client
22
  redis_client = redis.Redis.from_url(REDIS_URL, decode_responses=True)
 
24
  # πŸ“° Topics
25
  TOPICS = ["India news", "World news", "Tech news", "Finance news", "Sports news"]
26
 
27
+ # 🧠 Base summarization prompt (used for all topics)
28
+ BASE_PROMPT = (
29
+ "You are Nuse’s official news summarizer β€” insightful, punchy, and always on point.\n"
30
+ "Your job is to scan the content below and extract the key news items. For each item, craft a crisp summary (15–20 words). Avoid using any emojis.\n"
31
+ "List each summary on a new line starting with a dash (-) and no numbers. This is how Nuse keeps it clean and scannable.\n"
32
+ "\n"
33
+ "Example format:\n"
34
+ "- India stuns Australia in a last-ball thriller at the World Cup finals\n"
35
+ "- U.S. imposes sweeping tariffs on Chinese tech giants, rattling global markets\n"
36
+ "- Ceasefire breakthrough: Netanyahu (Prime minister of Isreal) bows to pressure after week-long escalation\n"
37
+ "\n"
38
+ "If you are mentioning a person, include their designation in brackets. For example: Jeff Bezos (Amazon CEO), Narendra Modi (Prime minister of India).\n"
39
+ "If you're referencing a post like 'NATO Chief', also include the name of the person who holds the post.\n"
40
+ "If you don't find anything useful, don't return anything for that news item.\n"
41
+ "Skim through the content and write summaries that are compelling, include essential facts, and feel like strong hook lines.\n"
42
+ "Be sharp. Be brief. No fluff. No preambles. Avoid source citations like (U.S. Security Council) or (The New York Times).\n"
43
+ "Return only the summary block β€” no extra commentary, no prompt repetition."
44
+ )
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
45
 
46
  # βœ‚οΈ Summarize top N documents
47
  def summarize_topic(docs: List[str], topic: str) -> List[Dict]:
48
  feed = []
49
  for doc in docs[:5]:
50
+ tail_prompt = f"Topic: {topic}\n\n{doc.strip()}"
51
+ print(f"\nπŸ“€ Prompt tail for Mistral:\n{tail_prompt[:300]}...\n")
52
+ summary_block = call_tinyllama(base_prompt=BASE_PROMPT, tail_prompt=tail_prompt)
53
 
54
  if summary_block:
55
  for line in summary_block.splitlines():
 
88
  # πŸ“¦ For testing or API access
89
  def get_cached_daily_feed():
90
  cached = redis_client.get(REDIS_KEY)
91
+ return json.loads(cached) if cached else []
requirements.txt CHANGED
@@ -6,6 +6,7 @@ llama-index
6
  llama-index-embeddings-huggingface
7
  llama_index.llms.huggingface
8
  sentence-transformers
 
9
  llama-index-vector-stores-upstash
10
  trafilatura
11
  newspaper3k
 
6
  llama-index-embeddings-huggingface
7
  llama_index.llms.huggingface
8
  sentence-transformers
9
+ transformers
10
  llama-index-vector-stores-upstash
11
  trafilatura
12
  newspaper3k