Skip to content

Commit

Permalink
add refactoring for pylint standards
Browse files Browse the repository at this point in the history
  • Loading branch information
VinciGit00 committed Feb 14, 2024
1 parent a2dd566 commit 8e5201e
Show file tree
Hide file tree
Showing 16 changed files with 157 additions and 103 deletions.
19 changes: 12 additions & 7 deletions examples/graph_example.py
Original file line number Diff line number Diff line change
@@ -1,17 +1,22 @@
"""
Basic example for creating the node
"""
import os
from dotenv import load_dotenv
from yosoai.graphs import SmartScraper

OPENAI_API_KEY = ''
load_dotenv()

openai_key = os.getenv("API_KEY")
if not openai_key:
print("Error: OpenAI API key not found in environment variables.")
llm_config = {
"api_key": OPENAI_API_KEY,
"api_key": openai_key,
"model_name": "gpt-3.5-turbo",
}

url = "https://perinim.github.io/projects/"
prompt = "List me all the titles and project descriptions"

smart_scraper = SmartScraper(prompt, url, llm_config)
smart_scraper = SmartScraper("List me all the titles and project descriptions",
"https://perinim.github.io/projects/", llm_config)

answer = smart_scraper.run()
print(answer)

15 changes: 8 additions & 7 deletions examples/html_scraping.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
"""
Exmaple of scraper using just the HTML code
"""
import os
from dotenv import load_dotenv
from yosoai import send_request
Expand Down Expand Up @@ -41,14 +44,13 @@
</article>
'''


def main():
# Get OpenAI API key from environment variables
openai_key = os.getenv("API_KEY")
if not openai_key:
print("Error: OpenAI API key not found in environment variables.")
return

# Example values for the request
request_settings = [
{
"title": "title",
Expand All @@ -57,15 +59,14 @@ def main():
}
]

# Choose the desired model and other parameters
selected_model = "gpt-3.5-turbo"
temperature_value = 0.7

# Invoke send_request function
result = send_request(openai_key, query_info, request_settings, selected_model, temperature_value, 'cl100k_base')
result = send_request(openai_key, query_info, request_settings,
selected_model, temperature_value, 'cl100k_base')

# Print or process the result as needed
print("Result:", result)


if __name__ == "__main__":
main()
main()
22 changes: 12 additions & 10 deletions examples/value_scraping.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,15 @@
"""
Example of scraping using just a link
"""
import os
from dotenv import load_dotenv
from yosoai import _get_function, send_request

load_dotenv()


def main():
# Get OpenAI API key from environment variables
""" """
openai_key = os.getenv("API_KEY")
if not openai_key:
print("Error: OpenAI API key not found in environment variables.")
Expand All @@ -14,24 +18,22 @@ def main():
# Example values for the request
request_settings = [
{
"title": "title_news",
"type": "str",
"description": "Give me the name of the news"
"title": "title_news",
"type": "str",
"description": "Give me the name of the news"
}
]

# Choose the desired model and other parameters
selected_model = "gpt-3.5-turbo"
temperature_value = 0.7

# Mockup World URL
mockup_world_url = "https://sport.sky.it/nba?gr=www"

# Invoke send_request function
result = send_request(openai_key, _get_function(mockup_world_url), request_settings, selected_model, temperature_value, 'cl100k_base')
result = send_request(openai_key, _get_function(
mockup_world_url), request_settings, selected_model, temperature_value, 'cl100k_base')

# Print or process the result as needed
print("Result:", result)


if __name__ == "__main__":
main()
main()
2 changes: 1 addition & 1 deletion yosoai/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
init file
__init__.py file for yosoai folder
"""
from .class_creator import create_class
from .class_generator import Generator
Expand Down
1 change: 1 addition & 0 deletions yosoai/class_generator.py
Original file line number Diff line number Diff line change
Expand Up @@ -58,3 +58,4 @@ def invocation(self, query_info):
return result_dict
except Exception as e:
print(f"Error: {e}")
return None
1 change: 1 addition & 0 deletions yosoai/getter.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,7 @@
"""
from langchain_community.document_loaders import AsyncHtmlLoader


def _get_function(link: str) -> str:
"""
It sends a GET request to the specified link with optional headers.
Expand Down
5 changes: 4 additions & 1 deletion yosoai/graphs/__init__.py
Original file line number Diff line number Diff line change
@@ -1,2 +1,5 @@
"""
__init__.py file for graphs folder
"""
from .base_graph import BaseGraph
from .smart_scraper_graph import SmartScraper
from .smart_scraper_graph import SmartScraper
14 changes: 8 additions & 6 deletions yosoai/graphs/base_graph.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,8 @@
"""
Module for creating the base graphs
"""


class BaseGraph:
"""
BaseGraph manages the execution flow of a graph composed of interconnected nodes.
Expand All @@ -19,15 +24,15 @@ class BaseGraph:
entry_point (BaseNode): The node instance that represents the entry point of the graph.
"""

def __init__(self, nodes, edges, entry_point):
def __init__(self, nodes: dict, edges: dict, entry_point: str):
"""
Initializes the graph with nodes, edges, and the entry point.
"""
self.nodes = {node.node_name: node for node in nodes}
self.edges = self._create_edges(edges)
self.entry_point = entry_point.node_name

def _create_edges(self, edges):
def _create_edges(self, edges: dict) -> dict:
"""
Helper method to create a dictionary of edges from the given iterable of tuples.
Expand All @@ -42,7 +47,7 @@ def _create_edges(self, edges):
edge_dict[from_node.node_name] = to_node.node_name
return edge_dict

def execute(self, initial_state):
def execute(self, initial_state: dict) -> dict:
"""
Executes the graph by traversing nodes starting from the entry point. The execution
follows the edges based on the result of each node's execution and continues until
Expand All @@ -62,13 +67,10 @@ def execute(self, initial_state):
result = current_node.execute(state)

if current_node.node_type == "conditional_node":
# For ConditionalNode, result is the next node based on the condition
current_node_name = result
elif current_node_name in self.edges:
# For regular nodes, move to the next node based on the defined edges
current_node_name = self.edges[current_node_name]
else:
# No further edges, end the execution
current_node_name = None

return state
27 changes: 18 additions & 9 deletions yosoai/graphs/smart_scraper_graph.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,11 @@
"""
Module for creating the smart scaper
"""
from langchain_openai import ChatOpenAI
from .base_graph import BaseGraph
from ..nodes import FetchHTMLNode,ConditionalNode, GetProbableTagsNode, GenerateAnswerNode, ParseHTMLNode
from ..nodes import FetchHTMLNode, ConditionalNode, GetProbableTagsNode
from ..nodes import GenerateAnswerNode, ParseHTMLNode


class SmartScraper:
"""
Expand All @@ -10,21 +15,23 @@ class SmartScraper:
Attributes:
prompt (str): The user's natural language prompt for the information to be extracted.
url (str): The URL of the web page to scrape.
llm_config (dict): Configuration parameters for the language model, with 'api_key' being mandatory.
llm_config (dict): Configuration parameters for the language model, with
'api_key' being mandatory.
llm (ChatOpenAI): An instance of the ChatOpenAI class configured with llm_config.
graph (BaseGraph): An instance of the BaseGraph class representing the scraping workflow.
Methods:
run(): Executes the web scraping process and returns the answer to the prompt.
Args:
prompt (str): The user's natural language prompt for the information to be extracted.
url (str): The URL of the web page to scrape.
llm_config (dict): A dictionary containing configuration options for the language model.
Must include 'api_key', may also specify 'model_name', 'temperature', and 'streaming'.
Must include 'api_key', may also specify 'model_name',
'temperature', and 'streaming'.
"""

def __init__(self, prompt, url, llm_config):
def __init__(self, prompt: str, url: str, llm_config: dict):
"""
Initializes the SmartScraper with a prompt, URL, and language model configuration.
"""
Expand Down Expand Up @@ -56,7 +63,7 @@ def _create_llm(self):
raise ValueError("LLM configuration must include an 'api_key'.")
# Create the ChatOpenAI instance with the provided and default parameters
return ChatOpenAI(**llm_params)

def _create_graph(self):
"""
Creates the graph of nodes representing the workflow for web scraping.
Expand All @@ -65,10 +72,12 @@ def _create_graph(self):
BaseGraph: An instance of the BaseGraph class.
"""
fetch_html_node = FetchHTMLNode("fetch_html")
get_probable_tags_node = GetProbableTagsNode(self.llm, "get_probable_tags")
get_probable_tags_node = GetProbableTagsNode(
self.llm, "get_probable_tags")
parse_document_node = ParseHTMLNode("parse_document")
generate_answer_node = GenerateAnswerNode(self.llm, "generate_answer")
conditional_node = ConditionalNode("conditional", [parse_document_node, generate_answer_node])
conditional_node = ConditionalNode(
"conditional", [parse_document_node, generate_answer_node])

return BaseGraph(
nodes={
Expand All @@ -86,7 +95,7 @@ def _create_graph(self):
entry_point=fetch_html_node
)

def run(self):
def run(self) -> str:
"""
Executes the scraping process by running the graph and returns the extracted information.
Expand Down
5 changes: 4 additions & 1 deletion yosoai/nodes/__init__.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,8 @@
"""
__init__.py file for node folder
"""
from .fetch_html_node import FetchHTMLNode
from .conditional_node import ConditionalNode
from .get_probable_tags_node import GetProbableTagsNode
from .generate_answer_node import GenerateAnswerNode
from .parse_html_node import ParseHTMLNode
from .parse_html_node import ParseHTMLNode
19 changes: 12 additions & 7 deletions yosoai/nodes/base_node.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""
Module for creating the basic node
"""
from abc import ABC, abstractmethod


class BaseNode(ABC):
"""
An abstract base class for nodes in a graph-based workflow. Each node is
Expand Down Expand Up @@ -33,7 +37,7 @@ class BaseNode(ABC):
values ("node" or "conditional_node"), a ValueError is
raised to indicate the incorrect usage.
"""

def __init__(self, node_name: str, node_type: str):
"""
Initialize the node with a unique identifier and a specified node type.
Expand All @@ -47,15 +51,16 @@ def __init__(self, node_name: str, node_type: str):
"""
self.node_name = node_name
if node_type not in ["node", "conditional_node"]:
raise ValueError(f"node_type must be 'node' or 'conditional_node', got '{node_type}'")
raise ValueError(
f"node_type must be 'node' or 'conditional_node', got '{node_type}'")
self.node_type = node_type

@abstractmethod
def execute(self, state):
def execute(self, state: dict):
"""
Execute the node's logic and return the updated state.
:param state: The current state of the graph.
Args:
state (dict): The current state of the graph.
:return: The updated state after executing this node.
"""
pass
pass
15 changes: 9 additions & 6 deletions yosoai/nodes/conditional_node.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,9 @@
"""
Module for implementing the conditional node
"""
from .base_node import BaseNode


class ConditionalNode(BaseNode):
"""
A node that determines the next step in the graph's execution flow based on
Expand Down Expand Up @@ -28,8 +32,8 @@ class ConditionalNode(BaseNode):
ValueError: If next_nodes does not contain exactly two elements, indicating
a misconfiguration in specifying the conditional paths.
"""
def __init__(self, key_name, next_nodes, node_name="ConditionalNode"):

def __init__(self, key_name: str, next_nodes: list, node_name="ConditionalNode"):
"""
Initializes the node with the key to check and the next node names based on the condition.
Expand All @@ -41,14 +45,14 @@ def __init__(self, key_name, next_nodes, node_name="ConditionalNode"):
Raises:
ValueError: If next_nodes does not contain exactly two elements.
"""

super().__init__(node_name, "conditional_node")
self.key_name = key_name
if len(next_nodes) != 2:
raise ValueError("next_nodes must contain exactly two elements.")
self.next_nodes = next_nodes

def execute(self, state):
def execute(self, state: dict) -> str:
"""
Checks if the specified key is present in the state and decides the next node accordingly.
Expand All @@ -61,5 +65,4 @@ def execute(self, state):

if self.key_name in state.get("keys", {}) and len(state["keys"][self.key_name]) > 0:
return self.next_nodes[0].node_name
else:
return self.next_nodes[1].node_name
return self.next_nodes[1].node_name
Loading

0 comments on commit 8e5201e

Please sign in to comment.