Spaces:
Runtime error
Runtime error
Refactored to suggest articles based on user insights
Browse files- Added callback functions to the task to capture required info.
- .gitignore +5 -1
- agents/learning_profiler.py +0 -1
- app.py +6 -0
- crew/article_suggestion.py +0 -8
- tasks/create_article_pitch.py +39 -14
- tasks/create_learning_profile.py +15 -9
- tasks/evaluate_articles.py +43 -10
- tasks/new_article_suggestion.py +35 -9
- utils/learning_profile.py +0 -12
- utils/recommended_article.py +0 -11
- utils/settings.py +3 -0
- utils/write_to_json.py +9 -0
.gitignore
CHANGED
|
@@ -1,5 +1,9 @@
|
|
| 1 |
__pycache__/
|
| 2 |
-
privacy_policy.pkl.tar.gz
|
| 3 |
.env
|
| 4 |
.DS_Store
|
| 5 |
venv
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
__pycache__/
|
|
|
|
| 2 |
.env
|
| 3 |
.DS_Store
|
| 4 |
venv
|
| 5 |
+
article_suggestions.json
|
| 6 |
+
evaluated_articles.json
|
| 7 |
+
final_articles.json
|
| 8 |
+
learning_profile.json
|
| 9 |
+
pitched_articles.json
|
agents/learning_profiler.py
CHANGED
|
@@ -6,7 +6,6 @@ learning_profiler = Agent(
|
|
| 6 |
role="Personal Learning Profiler",
|
| 7 |
goal="Make sure to create an excellent learning profile of the user based on his interests and previous reading history.",
|
| 8 |
verbose=True,
|
| 9 |
-
# tools=[scrape_tool],
|
| 10 |
backstory=(
|
| 11 |
"As a Personal Learning Profiler, you excel at building a learning profile of a user. "
|
| 12 |
"The profile you build gives a high level overview of what interests that the user has. "
|
|
|
|
| 6 |
role="Personal Learning Profiler",
|
| 7 |
goal="Make sure to create an excellent learning profile of the user based on his interests and previous reading history.",
|
| 8 |
verbose=True,
|
|
|
|
| 9 |
backstory=(
|
| 10 |
"As a Personal Learning Profiler, you excel at building a learning profile of a user. "
|
| 11 |
"The profile you build gives a high level overview of what interests that the user has. "
|
app.py
CHANGED
|
@@ -2,6 +2,10 @@ from dotenv import load_dotenv
|
|
| 2 |
load_dotenv()
|
| 3 |
|
| 4 |
from crew.article_suggestion import article_recommendation_crew
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
result = article_recommendation_crew.kickoff(inputs={
|
| 7 |
"interests": "Ruby On Rails, Architecture, Go Lang",
|
|
@@ -23,3 +27,5 @@ result = article_recommendation_crew.kickoff(inputs={
|
|
| 23 |
|
| 24 |
print(result)
|
| 25 |
print("Usage Metrics:\n", article_recommendation_crew.usage_metrics)
|
|
|
|
|
|
|
|
|
| 2 |
load_dotenv()
|
| 3 |
|
| 4 |
from crew.article_suggestion import article_recommendation_crew
|
| 5 |
+
import utils.settings as settings
|
| 6 |
+
from utils.write_to_json import write_dict_to_json as write_dict_to_json
|
| 7 |
+
|
| 8 |
+
settings.init()
|
| 9 |
|
| 10 |
result = article_recommendation_crew.kickoff(inputs={
|
| 11 |
"interests": "Ruby On Rails, Architecture, Go Lang",
|
|
|
|
| 27 |
|
| 28 |
print(result)
|
| 29 |
print("Usage Metrics:\n", article_recommendation_crew.usage_metrics)
|
| 30 |
+
|
| 31 |
+
write_dict_to_json(settings.articles, filename="final_articles.json")
|
crew/article_suggestion.py
CHANGED
|
@@ -23,12 +23,4 @@ article_recommendation_crew = Crew(
|
|
| 23 |
"model": 'text-embedding-3-small'
|
| 24 |
}
|
| 25 |
}
|
| 26 |
-
# embedder={
|
| 27 |
-
# "provider": "google",
|
| 28 |
-
# "config":{
|
| 29 |
-
# "model": 'models/embedding-001',
|
| 30 |
-
# "task_type": "retrieval_document",
|
| 31 |
-
# "title": "Embeddings for Embedchain"
|
| 32 |
-
# }
|
| 33 |
-
# }
|
| 34 |
)
|
|
|
|
| 23 |
"model": 'text-embedding-3-small'
|
| 24 |
}
|
| 25 |
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
)
|
tasks/create_article_pitch.py
CHANGED
|
@@ -1,20 +1,45 @@
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.curiosity_catalyst import curiosity_catalyst
|
| 3 |
from tools.scrape_website import scrape_tool
|
| 4 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 5 |
|
| 6 |
article_pitch_task = Task(
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
| 15 |
-
|
| 16 |
-
|
| 17 |
-
|
| 18 |
-
|
| 19 |
-
|
|
|
|
|
|
|
|
|
|
| 20 |
)
|
|
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.curiosity_catalyst import curiosity_catalyst
|
| 3 |
from tools.scrape_website import scrape_tool
|
| 4 |
+
from crewai.tasks.task_output import TaskOutput
|
| 5 |
+
import utils.settings as settings
|
| 6 |
+
from pydantic import BaseModel
|
| 7 |
+
from typing import List
|
| 8 |
+
import json
|
| 9 |
+
|
| 10 |
+
|
| 11 |
+
class PitchedArticle(BaseModel):
|
| 12 |
+
title: str
|
| 13 |
+
url: str
|
| 14 |
+
pitch: str
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class PitchedArticles(BaseModel):
|
| 18 |
+
articles: List[PitchedArticle]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def callback_function(output: TaskOutput):
|
| 22 |
+
evaluated_articles = json.loads(output.exported_output)['articles']
|
| 23 |
+
|
| 24 |
+
for article in evaluated_articles:
|
| 25 |
+
settings.articles[article['url']]['pitch'] = article['pitch']
|
| 26 |
+
|
| 27 |
|
| 28 |
article_pitch_task = Task(
|
| 29 |
+
description=(
|
| 30 |
+
"Create a pitch only for the articles that have passed evaluation and no other links. "
|
| 31 |
+
"Craft the pitch so to that it teases the article's most intriguing aspects, "
|
| 32 |
+
"by posing questions that the article might answer or "
|
| 33 |
+
"highlighting surprising facts to pique the user's curiosity "
|
| 34 |
+
" to read the article for incremental learning."
|
| 35 |
+
),
|
| 36 |
+
expected_output=(
|
| 37 |
+
"List of all the artilces that have passed evaluation phase along with their url and pitch statement."
|
| 38 |
+
),
|
| 39 |
+
output_json=PitchedArticles,
|
| 40 |
+
output_file="pitched_articles.json",
|
| 41 |
+
tools=[scrape_tool],
|
| 42 |
+
agent=curiosity_catalyst,
|
| 43 |
+
async_execution=False,
|
| 44 |
+
callback=callback_function,
|
| 45 |
)
|
tasks/create_learning_profile.py
CHANGED
|
@@ -1,25 +1,31 @@
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.learning_profiler import learning_profiler
|
| 3 |
-
from
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 4 |
|
| 5 |
learning_profile_task = Task(
|
| 6 |
description=(
|
| 7 |
-
# "Create a Learning profile of the user based on his following interests {interests} "
|
| 8 |
-
# "and based on the following articles and insights he has read in the past: \n"
|
| 9 |
-
# "{previous_article_insights}"
|
| 10 |
"Create a Learning profile of the user based on "
|
| 11 |
"the following articles and insights he has read in the past: \n"
|
| 12 |
"{previous_article_insights}"
|
| 13 |
),
|
| 14 |
expected_output=(
|
| 15 |
"A structured learning profile of the user with his interests, topics he has read about "
|
| 16 |
-
"and
|
| 17 |
-
# "A structured learning profile. "
|
| 18 |
-
# "The learning profile should only contain a section called 'Topics of interest' and 'Insights'. "
|
| 19 |
-
# "It should not have any other sections such as summary or conclusion. "
|
| 20 |
-
# "'Insights' section should contain the insights captured by the user and they should be grouped by topic."
|
| 21 |
),
|
| 22 |
agent=learning_profiler,
|
| 23 |
output_json=LearningProfile,
|
|
|
|
| 24 |
async_execution=False
|
| 25 |
)
|
|
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.learning_profiler import learning_profiler
|
| 3 |
+
from pydantic import BaseModel
|
| 4 |
+
from typing import List
|
| 5 |
+
|
| 6 |
+
|
| 7 |
+
class Topic(BaseModel):
|
| 8 |
+
name: str
|
| 9 |
+
insights: List[str]
|
| 10 |
+
|
| 11 |
+
|
| 12 |
+
class LearningProfile(BaseModel):
|
| 13 |
+
topics_of_interests: List[str]
|
| 14 |
+
learnings: List[Topic]
|
| 15 |
+
|
| 16 |
|
| 17 |
learning_profile_task = Task(
|
| 18 |
description=(
|
|
|
|
|
|
|
|
|
|
| 19 |
"Create a Learning profile of the user based on "
|
| 20 |
"the following articles and insights he has read in the past: \n"
|
| 21 |
"{previous_article_insights}"
|
| 22 |
),
|
| 23 |
expected_output=(
|
| 24 |
"A structured learning profile of the user with his interests, topics he has read about "
|
| 25 |
+
"and insights he has captured on the topics."
|
|
|
|
|
|
|
|
|
|
|
|
|
| 26 |
),
|
| 27 |
agent=learning_profiler,
|
| 28 |
output_json=LearningProfile,
|
| 29 |
+
output_file="learning_profile.json",
|
| 30 |
async_execution=False
|
| 31 |
)
|
tasks/evaluate_articles.py
CHANGED
|
@@ -1,15 +1,48 @@
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.article_evaluator import article_evaluator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
evaluation_task = Task(
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
| 14 |
-
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 15 |
)
|
|
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.article_evaluator import article_evaluator
|
| 3 |
+
from crewai.tasks.task_output import TaskOutput
|
| 4 |
+
import utils.settings as settings
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from typing import List
|
| 7 |
+
import json
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class EvaluatedArticle(BaseModel):
|
| 11 |
+
title: str
|
| 12 |
+
url: str
|
| 13 |
+
evaluation_score: int
|
| 14 |
+
evaluation_reason: str
|
| 15 |
+
|
| 16 |
+
|
| 17 |
+
class EvaluatedArticles(BaseModel):
|
| 18 |
+
articles: List[EvaluatedArticle]
|
| 19 |
+
|
| 20 |
+
|
| 21 |
+
def callback_function(output: TaskOutput):
|
| 22 |
+
evaluated_articles = json.loads(output.exported_output)['articles']
|
| 23 |
+
|
| 24 |
+
for article in evaluated_articles:
|
| 25 |
+
settings.articles[article['url']
|
| 26 |
+
]['evaluation_score'] = article['evaluation_score']
|
| 27 |
+
settings.articles[article['url']
|
| 28 |
+
]['evaluation_reason'] = article['evaluation_reason']
|
| 29 |
+
|
| 30 |
|
| 31 |
evaluation_task = Task(
|
| 32 |
+
description=(
|
| 33 |
+
"Evaluate artilces based on the metric does the articles provide incremenrtal "
|
| 34 |
+
"learning w.r.t the insights captured by the user. "
|
| 35 |
+
"Score the articles on the scale of 1 to 10, "
|
| 36 |
+
"1 being doesn't provide incremental learning and "
|
| 37 |
+
"10 being provides incremental learning to the user."
|
| 38 |
+
),
|
| 39 |
+
expected_output=(
|
| 40 |
+
"List of article titles along with their links, evaluation score and "
|
| 41 |
+
"evaluation reason w.r.t to insights captured by the user."
|
| 42 |
+
),
|
| 43 |
+
output_json=EvaluatedArticles,
|
| 44 |
+
output_file="evaluated_articles.json",
|
| 45 |
+
agent=article_evaluator,
|
| 46 |
+
async_execution=False,
|
| 47 |
+
callback=callback_function,
|
| 48 |
)
|
tasks/new_article_suggestion.py
CHANGED
|
@@ -1,14 +1,40 @@
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.learning_curator import learning_curator
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 3 |
|
| 4 |
article_suggestion_task = Task(
|
| 5 |
-
|
| 6 |
-
|
| 7 |
-
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
|
| 11 |
-
|
| 12 |
-
|
| 13 |
-
|
|
|
|
|
|
|
|
|
|
| 14 |
)
|
|
|
|
| 1 |
from crewai import Task
|
| 2 |
from agents.learning_curator import learning_curator
|
| 3 |
+
from crewai.tasks.task_output import TaskOutput
|
| 4 |
+
import utils.settings as settings
|
| 5 |
+
from pydantic import BaseModel
|
| 6 |
+
from typing import List
|
| 7 |
+
import json
|
| 8 |
+
|
| 9 |
+
|
| 10 |
+
class SuggestedArticle(BaseModel):
|
| 11 |
+
title: str
|
| 12 |
+
url: str
|
| 13 |
+
reason_for_recommendation: str
|
| 14 |
+
|
| 15 |
+
|
| 16 |
+
class SuggestedArticles(BaseModel):
|
| 17 |
+
articles: List[SuggestedArticle]
|
| 18 |
+
|
| 19 |
+
|
| 20 |
+
def callback_function(output: TaskOutput):
|
| 21 |
+
suggested_articles = json.loads(output.exported_output)['articles']
|
| 22 |
+
|
| 23 |
+
for article in suggested_articles:
|
| 24 |
+
settings.articles[article['url']] = article
|
| 25 |
+
|
| 26 |
|
| 27 |
article_suggestion_task = Task(
|
| 28 |
+
description=(
|
| 29 |
+
"Find 5 articles from the past 10 days that align with the user's learning interests. "
|
| 30 |
+
"The articles should provide incremental learning to the user based on their insights."
|
| 31 |
+
),
|
| 32 |
+
expected_output=(
|
| 33 |
+
"List of article titles along with their links. "
|
| 34 |
+
),
|
| 35 |
+
output_json=SuggestedArticles,
|
| 36 |
+
output_file="article_suggestions.json",
|
| 37 |
+
agent=learning_curator,
|
| 38 |
+
async_execution=False,
|
| 39 |
+
callback=callback_function,
|
| 40 |
)
|
utils/learning_profile.py
DELETED
|
@@ -1,12 +0,0 @@
|
|
| 1 |
-
from pydantic import BaseModel
|
| 2 |
-
from typing import List
|
| 3 |
-
|
| 4 |
-
|
| 5 |
-
class Topic(BaseModel):
|
| 6 |
-
name: str
|
| 7 |
-
insights: List[str]
|
| 8 |
-
|
| 9 |
-
|
| 10 |
-
class LearningProfile(BaseModel):
|
| 11 |
-
topics_of_interests: List[str]
|
| 12 |
-
learnings: List[Topic]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils/recommended_article.py
DELETED
|
@@ -1,11 +0,0 @@
|
|
| 1 |
-
from pydantic import BaseModel
|
| 2 |
-
from typing import List
|
| 3 |
-
|
| 4 |
-
class RecommendedArticle(BaseModel):
|
| 5 |
-
title: str
|
| 6 |
-
url: str
|
| 7 |
-
pitch: str
|
| 8 |
-
reason_for_recommendation: str
|
| 9 |
-
|
| 10 |
-
class RecommendedArticles(BaseModel):
|
| 11 |
-
articles: List[RecommendedArticle]
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
utils/settings.py
ADDED
|
@@ -0,0 +1,3 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
def init():
|
| 2 |
+
global articles
|
| 3 |
+
articles = {}
|
utils/write_to_json.py
ADDED
|
@@ -0,0 +1,9 @@
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
| 1 |
+
import json
|
| 2 |
+
|
| 3 |
+
def write_dict_to_json(data, filename="data.json", indent=4):
|
| 4 |
+
try:
|
| 5 |
+
with open(filename, 'w') as json_file:
|
| 6 |
+
json.dump(data, json_file, indent=indent)
|
| 7 |
+
print(f"Successfully wrote dictionary to {filename}")
|
| 8 |
+
except (IOError, json.JSONDecodeError) as e:
|
| 9 |
+
print(f"Error writing to JSON file: {e}")
|