From d3efeac0b46645c00cf515db7521702811e606d4 Mon Sep 17 00:00:00 2001 From: WilliamMRS Date: Thu, 17 Oct 2024 19:15:56 +0200 Subject: [PATCH] feat: Create file management for user_data --- .gitignore | 4 ++ core/agent.py | 118 -------------------------------- core/ai_message.py | 2 +- core/graphAgent.py | 2 +- core/graphtools.py | 2 +- core/main.py | 17 +++-- core/modules/chat.py | 15 ++++ core/modules/user_data_setup.py | 18 +++++ docker-compose.yml | 5 +- 9 files changed, 54 insertions(+), 129 deletions(-) delete mode 100644 core/agent.py create mode 100644 core/modules/chat.py create mode 100644 core/modules/user_data_setup.py diff --git a/.gitignore b/.gitignore index 75b8591..19a4e35 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,7 @@ +# Custom Ignores +user_data + + # Byte-compiled / optimized / DLL files __pycache__/ *.py[cod] diff --git a/core/agent.py b/core/agent.py deleted file mode 100644 index 69e4bff..0000000 --- a/core/agent.py +++ /dev/null @@ -1,118 +0,0 @@ -from langchain_openai import ChatOpenAI -from graphstate import GraphState -from tools.tools import get_tools -from langgraph.graph import StateGraph, START, END -from langgraph.prebuilt import ToolNode, tools_condition -from langchain_core.messages import BaseMessage, AIMessageChunk, HumanMessage -from models import Model -import json -from config import OPENAI_API_KEY - - - -class Agent1: - llm = ChatOpenAI( - model = Model.gpt_4o, - temperature=0, - max_tokens=512, - ) - - -class Agent: - def __init__(self, model_type) -> None: - #Langsmith Tracing - LANGCHAIN_TRACING_V2: str = "true" - - self.llm = ChatOpenAI( - model=model_type, - temperature=0, - max_tokens=512, - streaming=True, - ) - - self.llm_with_tools = self.llm.bind_tools(get_tools()) - - self.workflow = StateGraph(GraphState) - - # Adding nodes to the workflow - self.workflow.add_node("chatbot", self.chatbot) - self.workflow.add_node("tools", ToolNode(get_tools())) - # TODO: Visualize these tools - - # Defining edges between nodes - self.workflow.add_edge(START, "chatbot") - self.workflow.add_edge("tools", "chatbot") - - # Defining conditional edges - self.workflow.add_conditional_edges( - "chatbot", - tools_condition - ) - - self.graph = self.workflow.compile() # Compiles the workflow in a graph. - - #Saving image of graph node comment in and out as needed - #with open("core/graph_node_network.png", 'wb') as f: - # f.write(self.graph.get_graph().draw_mermaid_png()) - - def chatbot(self, state: GraphState): - """ - Simple bot that invokes the list of previous messages - and returns the result which will be added to the list of messages. - """ - #state_of_chatbot = self.llm_with_tools.invoke(state["messages"]).tool_calls - #print("Tools called: " + state_of_chatbot["name"][-1].content) - - return {"messages": [self.llm_with_tools.invoke(state["messages"])]} - - -# UNFINISHED - def run_stream_only(self, user_prompt: str): - """ - Run the agent, returning a token stream. - """ - print('Running stream...') - print(user_prompt) - print(type(user_prompt)) - for chunk in self.llm.stream(user_prompt): - yield chunk.content - - #for running the agent comment out for testing in terminal - def run(self, user_prompt: str) -> tuple[str, int]: - """ - Run the agent with a user prompt and return a tuple containing the llm - response and the total amount of tokens used. - """ - first = True - for event in self.graph.stream("tell me about orcas?"): - for value in event.values(): - messages = value["messages"][-1] - gathered = "" - # if messages.content and not isinstance(messages, HumanMessage): - # print(messages.content, end="|", flush=True) - - gathered += messages - - if isinstance(messages, BaseMessage): - if hasattr(messages, 'usage_metadata'): - total_tokens = messages.usage_metadata.get('total_tokens', 0) - gathered += messages.content - else: - print(f"Warning: Message of type {type(messages)} does not have usage_metadata") - - return gathered, total_tokens - - #for testing in terminal - """ def run(self, user_prompt: str): - for event in self.graph.stream({"messages": [("user", user_prompt)]}): - for value in event.values(): - if isinstance(value["messages"][-1], BaseMessage): - print("Assistant:", value["messages"][-1].content) - -if __name__ == "__main__": - agent = Agent("gpt-4o-mini") - while True: - user_prompt = input("User: ") - agent.run(user_prompt) """ - -# Counting tokens: https://python.langchain.com/docs/how_to/llm_token_usage_tracking/ \ No newline at end of file diff --git a/core/ai_message.py b/core/ai_message.py index aabaf40..19e0934 100644 --- a/core/ai_message.py +++ b/core/ai_message.py @@ -1,4 +1,4 @@ class Ai_message: def __init__(self, message:str, token_count:int) -> None: self.message = message - self.token_count = token_count + self.token_count = token_count \ No newline at end of file diff --git a/core/graphAgent.py b/core/graphAgent.py index 3468958..53326ea 100644 --- a/core/graphAgent.py +++ b/core/graphAgent.py @@ -8,7 +8,7 @@ import json from config import OPENAI_API_KEY from Agents.simpleagent import SimpleAgent -from agent import Agent, Agent1 +#from agent import Agent, Agent1 import asyncio from time import sleep diff --git a/core/graphtools.py b/core/graphtools.py index 446eb4e..1d3e4df 100644 --- a/core/graphtools.py +++ b/core/graphtools.py @@ -16,7 +16,7 @@ class AgentState(TypedDict): messages: Annotated[Sequence[BaseMessage], operator.add] sender: str -class gaphtool: +class graphtool: def __init__(self, graph): self.graph = graph self.nodes = graph.nodes() diff --git a/core/main.py b/core/main.py index 41e5552..3fbb7c7 100644 --- a/core/main.py +++ b/core/main.py @@ -7,6 +7,15 @@ from flask_cors import CORS from config import PORT import asyncio +from modules.user_data_setup import check_folders +from modules.chat import read_chat +import logging +log = logging.getLogger('werkzeug') +log.setLevel(logging.ERROR) + +print("J is booting up....") +check_folders() # Check directories are made for user data +read_chat("1") # # Server config @@ -42,8 +51,6 @@ def summarize_store(): return {"status": "success", "summary": summary} - - # # # Socket.IO events below @@ -68,10 +75,12 @@ def handle_prompt(data): socketio.emit("start_message") asyncio.run(jarvis.run(data['prompt'], socketio), debug=True) # prompts Jarvis and hands off emitting to the graphAgent. - return jsonify({"status": response}) + return jsonify({"status": "success"}) except Exception as e: print(f'Something very bad happened: {e}') return jsonify({"status": "error"}) if __name__ == '__main__': - socketio.run(app, debug=True, host='0.0.0.0', port=PORT, allow_unsafe_werkzeug=True) \ No newline at end of file + socketio.run(app, debug=True, host='0.0.0.0', port=PORT, allow_unsafe_werkzeug=True) + +# hello \ No newline at end of file diff --git a/core/modules/chat.py b/core/modules/chat.py new file mode 100644 index 0000000..6e39e37 --- /dev/null +++ b/core/modules/chat.py @@ -0,0 +1,15 @@ +import os +import json + +def read_chat(id): + ''' + Uses chat_id to get the entire chat JSON file + ''' + dirname = os.path.dirname(os.path.dirname(__file__)) # Creates folder in core named user_data + filepath = os.path.join(dirname, f'user_data/chats/{id}.json') + # Open and read the JSON file + with open(filepath, 'r') as file: + data = json.load(file) + + # Print the data + print(data) \ No newline at end of file diff --git a/core/modules/user_data_setup.py b/core/modules/user_data_setup.py new file mode 100644 index 0000000..98773f7 --- /dev/null +++ b/core/modules/user_data_setup.py @@ -0,0 +1,18 @@ +import os + +def check_folders(): + main_folder = "user_data/" + pathsToCheck = ["chats", "images", "pdfs", "fbx"] + for directory in pathsToCheck: + path = main_folder + directory # creates path user_data/chats for example. Everything should be under user_data as its gitignored. + check_and_create_folder(path) # Does a relative folder check, and builds the directory if it doesn't exist + +def check_and_create_folder(path): + dirname = os.path.dirname(os.path.dirname(__file__)) # Creates folder in core named user_data + relativedir = os.path.join(dirname, path) + if not os.path.exists(relativedir): + try: + print("Created user_data director under core folder. This is first-time setup.") + os.makedirs(path) + except Exception as e: + print(e) \ No newline at end of file diff --git a/docker-compose.yml b/docker-compose.yml index fdaff1c..9a52a41 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -2,11 +2,9 @@ services: llm-service: build: ./core restart: unless-stopped + env_file: .env environment: - FLASK_ENV=development # Autorestarts flask when code changes are detected - - OPENAI_API_KEY=${OPENAI_API_KEY} - - LANGSMITH_API_KEY=&{LANGSMITH_API_KEY} - - PORT=&{PORT} volumes: - ./core:/app # Mount the application code to detect live changes networks: @@ -15,7 +13,6 @@ services: ports: - "3000:3000" - networks: backend: driver: bridge \ No newline at end of file