diff --git a/.gitignore b/.gitignore index 36b13f1..2e4956a 100644 --- a/.gitignore +++ b/.gitignore @@ -174,3 +174,5 @@ cython_debug/ # PyPI configuration file .pypirc +# Output from Agent +*.csv \ No newline at end of file diff --git a/src/CSV_Agent.py b/src/CSV_Agent.py index 93ab70a..164f9ee 100644 --- a/src/CSV_Agent.py +++ b/src/CSV_Agent.py @@ -8,6 +8,7 @@ from langchain_openai import ChatOpenAI from langchain_core.messages import HumanMessage, AIMessage, BaseMessage from langchain_core.tools import tool from langgraph.prebuilt import create_react_agent +from langchain.agents import create_agent from dotenv import load_dotenv load_dotenv() @@ -20,7 +21,7 @@ API_MODEL = os.getenv("OPENAI_MODEL") ################### @tool -def write_csv(filepath: str, data: List[any]) -> str: +def write_csv(filepath: str, data: List[str]) -> str: """Write a Python dictionary as CSV to a file.""" header = ['number', 'location', @@ -35,23 +36,33 @@ def write_csv(filepath: str, data: List[any]) -> str: ] try: with open(filepath, 'w', newline='') as csvfile: - writer = csv.DictWriter(csvfile, delimiter=',') + fieldnames = [ + 'number', + 'location', + 'state', + 'ci', + 'priority', + 'short_description', + 'description', + 'assignment_group', + 'assigned_to', + 'sys_created_on', + 'resolved_at', + ] + + writer = csv.DictWriter(csvfile, fieldnames=fieldnames) writer.writeheader() + for row in data: writer.writerow(row) + return f"Successfully wrote a CSV file to '{filepath}'." except Exception as e: return f"Error writing CSV file: {str(e)}" @tool -def generate_test_list( - location: List[str], - state: List[str], - ci: List[str], - priority: List[str], - assigned_to: List[str], -) -> List[dict]: +def generate_incidents() -> List[List[str]]: """ Generate sample ticket data. Count will be 100 total items. @@ -60,20 +71,70 @@ def generate_test_list( state: List of possible ticket states (Will use multiple times) ci: List of the possible configuration items (will use multiple times) priority: List of possible ticket priorities (Will use multiple times) - assigned_to: List of possible Support Engineers to lead tickets to resolution (Will cycle through) + assigned_to: List of possible Support Engineers to lead incidents to resolution (Will cycle through) Returns: - List with 'tickets' dictionary or 'error' message + List with 'incidents' List or 'error' message """ - pass -# number -# location -# state -# ci -# priority -# short_description -# description -# assignment_group -# assigned_to -# sys_created_on -# resolved_at \ No newline at end of file + # TODO: ADD DYNAMIC CSV LOGIC + return [["1", "Broadway", "Work In Progress", "Order Accuracy Issue", "P3 - Medium", "This is short", "This is much longer, see?", "Managed Support - L3", "2025-11-05 08:08:27 PM", ""]] + + +TOOLS = [write_csv, generate_incidents] + +llm = ChatOpenAI(model=API_MODEL, temperature=0, api_key=API_KEY) + +SYSTEM_MESSAGE = ( + "You are CVSBot, a cheerful assistant who generates sample data for applications. " + "To generate incidents, you need: location (list), state (list), ci (list), priority (list), assigned_to (list). " + "When asked to generate sample ticket data, first generate them with the tool, then immediately use write_csv with the result. " + "If the user refers to 'past incidents' from a previous request, ask them to specify the details again. " +) + +agent = create_agent(llm, TOOLS, system_prompt=SYSTEM_MESSAGE) + +def run_agent(user_input: str, history: List[BaseMessage]) -> AIMessage: + """Single-turn agent runner with automatic tool execution via LangGraph.""" + try: + result = agent.invoke( + {"messages": history + [HumanMessage(content=user_input)]}, + configs={"recursion_limit": 50} + ) + # Return the last AI message + return result["messages"][-1] + except Exception as e: + # Return error as an AI message so the conversation can continue + return AIMessage(content=f"Error: {str(e)}\n\nPlease try rephrasing your request or provide more specific details.") + + +if __name__ == "__main__": + print("-" * 50) + print("CSVBot Agent - Sample Incident Generator") + print("-" * 50) + print("Generate sample ticket data and save to a CSV file.") + print() + print("Examples:") + print(" - Generate incidents for locations called Main st, Broad way, Park Ave and save to incidents.csv") + print(" - Create incidents with the priority P1 - Critical, P3 - Medium") + print(" - Make incidents that created over the last 4 weeks") + print() + print("Commands: 'quit' or 'exit' to end") + print("-" * 50) + + history: List[BaseMessage] = [] + + while True: + user_input = input("You: ").strip() + + # Check for exit commands + if user_input.lower() in ['quit', 'exit']: + print("Goodbye!") + break + + print("Agent: ", end="", flush=True) + response = run_agent(user_input, history) + print(response.content) + print() + + # Update conversation history + history += [HumanMessage(content=user_input), response]