Spaces:
Sleeping
Sleeping
Upload 8 files
Browse files- .dockerignore +9 -0
- Dockerfile +18 -0
- agents.py +102 -0
- app.py +13 -0
- prompts/news_selector.yml +27 -0
- prompts/post_generator.yml +26 -0
- prompts/post_generator_without_source.yml +20 -0
- requirements.txt +16 -0
.dockerignore
ADDED
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
__pycache__/
|
2 |
+
*.pyc
|
3 |
+
*.pyo
|
4 |
+
*.pyd
|
5 |
+
.venv/
|
6 |
+
.env
|
7 |
+
.git
|
8 |
+
*.log
|
9 |
+
news_data.json
|
Dockerfile
ADDED
@@ -0,0 +1,18 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Dockerfile for deploying the FastAPI app on Hugging Face Spaces or any Docker environment
|
2 |
+
FROM python:3.10-slim
|
3 |
+
|
4 |
+
# Set working directory
|
5 |
+
WORKDIR /app
|
6 |
+
|
7 |
+
# Install Python dependencies
|
8 |
+
COPY requirements.txt ./
|
9 |
+
RUN pip install --no-cache-dir -r requirements.txt
|
10 |
+
|
11 |
+
# Copy application code
|
12 |
+
COPY . .
|
13 |
+
|
14 |
+
# Expose port (Hugging Face Spaces uses port 80)
|
15 |
+
EXPOSE 80
|
16 |
+
|
17 |
+
# Run the FastAPI app with Gunicorn and Uvicorn worker
|
18 |
+
CMD ["gunicorn", "app:app", "--workers", "1", "--bind", "0.0.0.0:80", "--worker-class", "uvicorn.workers.UvicornWorker"]
|
agents.py
ADDED
@@ -0,0 +1,102 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
import os
|
2 |
+
import json
|
3 |
+
import time
|
4 |
+
import traceback
|
5 |
+
|
6 |
+
from langchain_core.prompts import PromptTemplate
|
7 |
+
from langchain_core.output_parsers import JsonOutputParser
|
8 |
+
from pydantic import BaseModel, Field
|
9 |
+
|
10 |
+
from langchain_groq import ChatGroq
|
11 |
+
from dotenv import load_dotenv
|
12 |
+
|
13 |
+
load_dotenv()
|
14 |
+
|
15 |
+
analysis_llm = ChatGroq(
|
16 |
+
model="llama-3.1-8b-instant ",
|
17 |
+
temperature=0.8,
|
18 |
+
max_tokens=800,
|
19 |
+
timeout=None,
|
20 |
+
max_retries=2,
|
21 |
+
api_key=os.getenv("GROQ_ANALYSIS_API_KEY"),
|
22 |
+
)
|
23 |
+
post_content_llm = ChatGroq(
|
24 |
+
model="qwen-qwq-32b",
|
25 |
+
temperature=0.8,
|
26 |
+
timeout=None,
|
27 |
+
max_retries=2,
|
28 |
+
api_key=os.getenv("THREADS_POST_GENERATION_API_KEY"),
|
29 |
+
)
|
30 |
+
|
31 |
+
|
32 |
+
def basic_analysis(news):
|
33 |
+
global analysis_llm_indx
|
34 |
+
prompt = PromptTemplate.from_file(
|
35 |
+
template_file="prompts/news_selector.yml",
|
36 |
+
input_variables=["news_object"],
|
37 |
+
)
|
38 |
+
|
39 |
+
for _ in range(5):
|
40 |
+
try:
|
41 |
+
response = analysis_llm.invoke(
|
42 |
+
prompt.invoke({"news_object": news})
|
43 |
+
)
|
44 |
+
print("################ BASIC ANALYSIS AGENT RESPONSE ################")
|
45 |
+
print(response.content)
|
46 |
+
print("################ BASIC ANALYSIS END AGENT RESPONSE ################")
|
47 |
+
|
48 |
+
start_index = response.content.find("{")
|
49 |
+
end_index = response.content.rfind("}")
|
50 |
+
|
51 |
+
print("start index:", start_index)
|
52 |
+
print("end index:", end_index)
|
53 |
+
|
54 |
+
abstracted_string = ""
|
55 |
+
if start_index != -1 and end_index != -1 and start_index < end_index:
|
56 |
+
abstracted_string = response.content[start_index : end_index + 1]
|
57 |
+
|
58 |
+
try:
|
59 |
+
results = json.loads(abstracted_string)
|
60 |
+
print(results)
|
61 |
+
return results
|
62 |
+
except Exception as e:
|
63 |
+
print(e)
|
64 |
+
traceback.print_exc()
|
65 |
+
except Exception as e:
|
66 |
+
print(e)
|
67 |
+
traceback.print_exc()
|
68 |
+
time.sleep(30)
|
69 |
+
|
70 |
+
raise ValueError("LLM response is not in correct format.")
|
71 |
+
|
72 |
+
|
73 |
+
def get_text_post_content(details, reference):
|
74 |
+
try:
|
75 |
+
prompt = PromptTemplate.from_file(
|
76 |
+
template_file="prompts/post_generator_without_source.yml",
|
77 |
+
input_variables=["NEWS_CONTENT", "CHAR_LENGTH"],
|
78 |
+
)
|
79 |
+
|
80 |
+
user_query = prompt.invoke(
|
81 |
+
{"NEWS_CONTENT": details, "CHAR_LENGTH": 490- len(reference)}
|
82 |
+
)
|
83 |
+
response = post_content_llm.invoke(user_query)
|
84 |
+
|
85 |
+
print("POST CONTENT RESPONSE:", response)
|
86 |
+
|
87 |
+
content = response.content.replace('"', '')
|
88 |
+
|
89 |
+
if "</think>" in content:
|
90 |
+
content = content.split("</think>")[1]
|
91 |
+
|
92 |
+
start_indx = content.find("#")
|
93 |
+
content = f"""{content[:start_indx]}
|
94 |
+
{reference}
|
95 |
+
|
96 |
+
{content[start_indx:]}"""
|
97 |
+
|
98 |
+
return content, True
|
99 |
+
except Exception as e:
|
100 |
+
print(e)
|
101 |
+
traceback.print_exc()
|
102 |
+
return "", False
|
app.py
ADDED
@@ -0,0 +1,13 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
from fastapi import FastAPI
|
2 |
+
|
3 |
+
from agents import basic_analysis, get_text_post_content
|
4 |
+
|
5 |
+
app = FastAPI()
|
6 |
+
|
7 |
+
@app.post("/get_basic_analysis")
|
8 |
+
def handle_basic_analysis(news: dict):
|
9 |
+
return basic_analysis(news)
|
10 |
+
|
11 |
+
@app.post("/get_text_post_content")
|
12 |
+
def handle_text_post_content(details: str, reference: str):
|
13 |
+
return get_text_post_content(details, reference)
|
prompts/news_selector.yml
ADDED
@@ -0,0 +1,27 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
input_variables:
|
2 |
+
- news_object
|
3 |
+
|
4 |
+
template: >-
|
5 |
+
You are an expert news analyzer. Your task is to analyze news to determine how it will impact the Indian stock market with the help of a title and a small description of the news if given. You will be given a news object in which some fields will be empty. You have to fill in those fields and return the same filled object.
|
6 |
+
|
7 |
+
Formate of news object:
|
8 |
+
{{
|
9 |
+
"title": "",
|
10 |
+
"url": "",
|
11 |
+
"description": " ",
|
12 |
+
"time": "",
|
13 |
+
"source": "",
|
14 |
+
"will_it_directly_impact_any_stock": "" -> boolean: true/false,
|
15 |
+
"directly_mentioned_companies_in_news": [] -> name of companies which are directly mentioned in the news and listed in indian stockmarket.,
|
16 |
+
"how_will_it_impact": "" -> categorical: Very Positive, Positive, Nautural, Negative, Very Negative.
|
17 |
+
"reason": "" -> reason for the impact.
|
18 |
+
}}
|
19 |
+
|
20 |
+
Output instructions:
|
21 |
+
- You have to strictly return news object after filling empty fields.
|
22 |
+
- You have to fill the fields in the same news object and return it.
|
23 |
+
- Don't give any additional information apart from filled news object.
|
24 |
+
- You must always return valid JSON fenced by a markdown code block. Do not return any additional text.
|
25 |
+
|
26 |
+
NEWS objects to analyze:
|
27 |
+
{news_object}
|
prompts/post_generator.yml
ADDED
@@ -0,0 +1,26 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
# Not in use.
|
2 |
+
input_variables:
|
3 |
+
- NEWS_CONTENT
|
4 |
+
- REFERENCE_URL
|
5 |
+
- CHAR_LENGTH
|
6 |
+
|
7 |
+
template: >-
|
8 |
+
You are an AI assistant specializing in creating concise, impactful social media posts for Threads. Your task is to generate a post based on the provided news and its reference link, ensuring it meets the following criteria:
|
9 |
+
|
10 |
+
1. **Summary:** Provide a brief yet informative summary of the news, highlighting key details and numbers.
|
11 |
+
2. **Impacted Stocks:** Identify Indian stocks that may be affected by this news but don't directly mention this in post content by saing impacted stocks.
|
12 |
+
3. **Character Limit:** Ensure the entire post does not exceed {CHAR_LENGTH} characters.
|
13 |
+
4. **Format:** You can use any format to present the news but above guidelines must be followed.
|
14 |
+
5. **HashTags:** Add few tranding hashtags under 20 chars in the post content.
|
15 |
+
6. **Source URL:** You must Include the full provided Source URL with given route in the post.
|
16 |
+
|
17 |
+
Output instructions:
|
18 |
+
- Don't use emoji in the post content.
|
19 |
+
- You have to strictly return post content only not any other information or your thoughts.
|
20 |
+
|
21 |
+
Here is the news:
|
22 |
+
{NEWS_CONTENT}
|
23 |
+
|
24 |
+
Source URL: {REFERENCE_URL}
|
25 |
+
|
26 |
+
Generate the post following these guidelines without add any additional details or information.
|
prompts/post_generator_without_source.yml
ADDED
@@ -0,0 +1,20 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
input_variables:
|
2 |
+
- NEWS_CONTENT
|
3 |
+
- CHAR_LENGTH
|
4 |
+
|
5 |
+
template: >-
|
6 |
+
You are an AI assistant specializing in creating concise, impactful social media posts for Threads. Your task is to generate a post based on the provided news and its reference link, ensuring it meets the following criteria:
|
7 |
+
|
8 |
+
1. **Summary:** Provide a brief yet informative summary of the news, highlighting key details and numbers.
|
9 |
+
2. **Impacted Stocks:** Identify Indian stocks that may be affected by this news but don't directly mention this in post content by saing impacted stocks.
|
10 |
+
3. **Character Limit:** Ensure the entire post does not exceed {CHAR_LENGTH} characters.
|
11 |
+
4. **Format:** You can use any format to present the news but above guidelines must be followed.
|
12 |
+
5. **HashTags:** Add only one related tranding hashtags under 10 chars at the last.
|
13 |
+
|
14 |
+
Output instructions:
|
15 |
+
- You have to strictly return post content only not any other information or your thoughts. Don't include Link in the post content.
|
16 |
+
|
17 |
+
Here is the news:
|
18 |
+
{NEWS_CONTENT}
|
19 |
+
|
20 |
+
Generate the post following these guidelines without add any additional details or information.
|
requirements.txt
ADDED
@@ -0,0 +1,16 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
1 |
+
bs4==0.0.2
|
2 |
+
html2text==2024.2.26
|
3 |
+
pymongo[srv]==4.11
|
4 |
+
selenium==4.28.1
|
5 |
+
webdriver-manager==4.0.2
|
6 |
+
tiktoken==0.8.0
|
7 |
+
python-dotenv==1.0.1
|
8 |
+
langchain==0.3.17
|
9 |
+
langchain_core==0.3.33
|
10 |
+
langchain_groq==0.2.4
|
11 |
+
langchain_community==0.3.16
|
12 |
+
fastapi===0.115.8
|
13 |
+
gunicorn===23.0.0
|
14 |
+
uvicorn===0.34.0
|
15 |
+
pydantic==2.9.2
|
16 |
+
certifi
|