diff --git a/.gitignore b/.gitignore index 00bba9b..91e9c48 100644 --- a/.gitignore +++ b/.gitignore @@ -35,3 +35,10 @@ yarn-error.log* # typescript *.tsbuildinfo next-env.d.ts + +# Python +venv/ +__pycache__/ + +# PyCharm +.idea/ diff --git a/package-lock.json b/package-lock.json index 90beab3..9145621 100644 --- a/package-lock.json +++ b/package-lock.json @@ -14,6 +14,7 @@ "@prisma/client": "^5.9.1", "graphql": "^16.8.1", "next": "14.1.0", + "node-calls-python": "^1.8.2", "react": "^18", "react-dom": "^18", "tw-elements": "^1.1.0", @@ -4932,6 +4933,12 @@ "resolved": "https://registry.npmjs.org/node-abort-controller/-/node-abort-controller-3.1.1.tgz", "integrity": "sha512-AGK2yQKIjRuqnc6VkX2Xj5d+QW8xZ87pa1UK6yA6ouUyuxfHuMP6umE5QK7UmTeOAymo+Zx1Fxiuw9rVx8taHQ==" }, + "node_modules/node-calls-python": { + "version": "1.8.2", + "resolved": "https://registry.npmjs.org/node-calls-python/-/node-calls-python-1.8.2.tgz", + "integrity": "sha512-KIvIm6eGzhigqSeBZ9TwWdS4ZHYeRusYnZ0g6juRbViV7mZZeXZSCzw/YbkPsginJlhCoA1a3j8Z1dP9OnUflg==", + "hasInstallScript": true + }, "node_modules/node-fetch": { "version": "2.7.0", "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.7.0.tgz", diff --git a/package.json b/package.json index 6158717..3d82833 100644 --- a/package.json +++ b/package.json @@ -2,6 +2,7 @@ "name": "crew-ai-visualizer", "version": "0.1.0", "private": true, + "type": "module", "scripts": { "dev": "next dev", "build": "next build", @@ -15,6 +16,7 @@ "@prisma/client": "^5.9.1", "graphql": "^16.8.1", "next": "14.1.0", + "node-calls-python": "^1.8.2", "react": "^18", "react-dom": "^18", "tw-elements": "^1.1.0", diff --git a/postcss.config.js b/postcss.config.cjs similarity index 100% rename from postcss.config.js rename to postcss.config.cjs diff --git a/src/app/api/graphql/crew_ai.js b/src/app/api/graphql/crew_ai.js new file mode 100644 index 0000000..469e654 --- /dev/null +++ b/src/app/api/graphql/crew_ai.js @@ -0,0 +1,33 @@ +import prisma from "@/utils/prisma"; + +const nodecallspython = require("node-calls-python"); + +const py = nodecallspython.interpreter; + +py.addImportPath( + "E:\\Crew AI\\TheProject\\crew-ai-visualizer\\src\\app\\api\\graphql\\venv\\Lib\\site-packages" +); + +export function runMission(id) { + const crewaiPath = + "E:\\Crew AI\\TheProject\\crew-ai-visualizer\\src\\app\\api\\graphql\\crew_ai.py"; + return py + .import(crewaiPath) + .then(async function (pymodule) { + const mission = await prisma.mission.findFirst({ + where: { id }, + include: { crew: true }, + }); + if (mission) { + const result = await py.call(pymodule, "run_mission", mission); + const missionWithResult = prisma.mission.update({ + where: { id }, + data: { result }, + }); + return missionWithResult; + } else { + throw Error("Mission doest not exist"); + } + }) + .catch((err) => console.log(err)); +} diff --git a/src/app/api/graphql/crew_ai.py b/src/app/api/graphql/crew_ai.py new file mode 100644 index 0000000..210cbf1 --- /dev/null +++ b/src/app/api/graphql/crew_ai.py @@ -0,0 +1,57 @@ +import os + +from textwrap import dedent +from crewai import Agent, Task, Crew, Process +from langchain_google_genai import ChatGoogleGenerativeAI +from dotenv import load_dotenv + +load_dotenv() + +process_type = { + "SEQUENTIAL": Process.sequential, + "HIERARTICAL": Process.hierarchical, +} + + +def run_mission(mission): + llm = ChatGoogleGenerativeAI( + model="gemini-pro", + verbose=True, + temperature=0.5, + google_api_key=os.getenv("GEMINI_API_KEY"), + ) + + agents = [ + Agent( + role=agent["role"], + goal=agent["goal"], + backstory=agent["backstory"], + allow_delegation=agent["allowDelegation"], + verbose=agent["verbose"], + llm=llm, + ) + for agent in mission["crew"] + ] + + tasks = [ + Task( + description=dedent(task["description"]), + agent=( + [agent for agent in agents if agent.role == task["agent"]["role"]][0] + if task["agent"] + else None + ), + ) + for task in mission["tasks"] + ] + + crew = Crew( + agents=agents, + tasks=tasks, + verbose=mission["verbose"], + process=process_type[mission["process"]], + manager_llm=llm, + ) + + result = crew.kickoff() + return result diff --git a/src/app/api/graphql/requirements.txt b/src/app/api/graphql/requirements.txt new file mode 100644 index 0000000..8df356e --- /dev/null +++ b/src/app/api/graphql/requirements.txt @@ -0,0 +1,77 @@ +aiohttp==3.9.3 +aiosignal==1.3.1 +annotated-types==0.6.0 +anyio==4.3.0 +attrs==23.2.0 +backoff==2.2.1 +cachetools==5.3.2 +certifi==2024.2.2 +charset-normalizer==3.3.2 +click==8.1.7 +colorama==0.4.6 +crewai==0.11.2 +dataclasses-json==0.6.4 +Deprecated==1.2.14 +distro==1.9.0 +docstring-parser==0.15 +frozenlist==1.4.1 +google-ai-generativelanguage==0.4.0 +google-api-core==2.17.1 +google-auth==2.28.0 +google-generativeai==0.3.2 +googleapis-common-protos==1.62.0 +greenlet==3.0.3 +grpcio==1.60.1 +grpcio-status==1.60.1 +h11==0.14.0 +httpcore==1.0.3 +httpx==0.26.0 +idna==3.6 +importlib-metadata==6.11.0 +instructor==0.5.2 +jsonpatch==1.33 +jsonpointer==2.4 +langchain==0.1.8 +langchain-community==0.0.21 +langchain-core==0.1.24 +langchain-google-genai==0.0.9 +langchain-openai==0.0.5 +langsmith==0.1.3 +markdown-it-py==3.0.0 +marshmallow==3.20.2 +mdurl==0.1.2 +multidict==6.0.5 +mypy-extensions==1.0.0 +numpy==1.26.4 +openai==1.12.0 +opentelemetry-api==1.22.0 +opentelemetry-exporter-otlp-proto-common==1.22.0 +opentelemetry-exporter-otlp-proto-http==1.22.0 +opentelemetry-proto==1.22.0 +opentelemetry-sdk==1.22.0 +opentelemetry-semantic-conventions==0.43b0 +packaging==23.2 +proto-plus==1.23.0 +protobuf==4.25.3 +pyasn1==0.5.1 +pyasn1-modules==0.3.0 +pydantic==2.6.1 +pydantic_core==2.16.2 +Pygments==2.17.2 +PyYAML==6.0.1 +regex==2023.12.25 +requests==2.31.0 +rich==13.7.0 +rsa==4.9 +sniffio==1.3.0 +SQLAlchemy==2.0.27 +tenacity==8.2.3 +tiktoken==0.5.2 +tqdm==4.66.2 +typer==0.9.0 +typing-inspect==0.9.0 +typing_extensions==4.9.0 +urllib3==2.2.1 +wrapt==1.16.0 +yarl==1.9.4 +zipp==3.17.0 diff --git a/src/app/api/graphql/resolvers.ts b/src/app/api/graphql/resolvers.js similarity index 60% rename from src/app/api/graphql/resolvers.ts rename to src/app/api/graphql/resolvers.js index e4830c6..8630d38 100644 --- a/src/app/api/graphql/resolvers.ts +++ b/src/app/api/graphql/resolvers.js @@ -1,17 +1,13 @@ import { Process } from "@/data/consts"; -import { Agent } from "@/types/agent"; -import { CreateMissionInput, Mission } from "@/types/mission"; -import { Task } from "@/types/task"; import prisma from "@/utils/prisma"; -import { GraphQLResolveInfo } from "graphql"; -import { NextRequest, NextResponse } from "next/server"; +import { runMission } from "./crew_ai"; const resolvers = { Query: { agents: () => { return prisma.agent.findMany(); }, - agent: (id: number) => { + agent: (id) => { return prisma.agent.findFirst({ where: { id: id, @@ -26,7 +22,7 @@ const resolvers = { }); return missions; }, - mission: (id: number) => { + mission: (id) => { return prisma.mission.findFirst({ where: { id: id, @@ -35,42 +31,22 @@ const resolvers = { }, }, Mutation: { - createAgent: async ( - parent: any, - body: Agent, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + createAgent: async (parent, body, context, info) => { const agent = await prisma.agent.create({ data: body }); return agent; }, - updateAgent: async ( - parent: any, - body: Agent, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + updateAgent: async (parent, body, context, info) => { const updatedAgent = await prisma.agent.update({ where: { id: body.id }, data: body, }); return updatedAgent; }, - deleteAgent: async ( - parent: any, - body: { id: number }, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + deleteAgent: async (parent, body, context, info) => { await prisma.agent.delete({ where: { id: body.id } }); return { deleted: true }; }, - createMission: async ( - parent: any, - body: CreateMissionInput, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + createMission: async (parent, body, context, info) => { const { name, verbose, process } = body; const crew = await prisma.agent.findMany({ where: { @@ -79,7 +55,7 @@ const resolvers = { }, }, }); - const tasks: Array = []; + const tasks = []; for (let task of body.tasks) { const agent = await prisma.agent.findFirst({ where: { id: task.agent }, @@ -102,12 +78,7 @@ const resolvers = { mission.id; return mission; }, - updateMission: async ( - parent: any, - body: CreateMissionInput, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + updateMission: async (parent, body, context, info) => { const { id, name, verbose, process } = body; const crew = await prisma.agent.findMany({ where: { @@ -116,7 +87,7 @@ const resolvers = { }, }, }); - const tasks: Array = []; + const tasks = []; if (body.tasks) { for (let task of body.tasks) { const agent = await prisma.agent.findFirst({ @@ -146,21 +117,14 @@ const resolvers = { }); return mission; }, - deleteMission: async ( - parent: any, - body: { id: number }, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => { + deleteMission: async (parent, body, context, info) => { await prisma.mission.delete({ where: { id: body.id } }); return { deleted: true }; }, - runMission: async ( - parent: any, - body: { id: number }, - context: { req: NextRequest; res: NextResponse; datasource: any }, - info: GraphQLResolveInfo - ) => {}, + runMission: async (parent, body, context, info) => { + const result = await runMission(body.id); + return result; + }, }, }; diff --git a/src/data/data.ts b/src/data/data.ts index 377c818..dbd5f25 100644 --- a/src/data/data.ts +++ b/src/data/data.ts @@ -25,7 +25,7 @@ export const agents: Array = [ You check for missing imports, variable declarations, mismatched brackets and syntax errors. You also check for security vulnerabilities, and logic errors. `, - tools: [], + tools: ["DUCK_DUCK_GO_SEARCH", "PYTHON_REPL", "STACK_EXCHANGE"], allowDelegation: false, verbose: true, image: @@ -38,7 +38,7 @@ export const agents: Array = [ You feel that programmers always do only half the job, so you are super dedicate to make high quality code. `, - tools: [], + tools: ["SEMANTIC_SCHOLER", "WIKIDATA", "YUOUTUBE_SEARCH"], allowDelegation: false, verbose: true, image: @@ -47,26 +47,73 @@ export const agents: Array = [ ]; export const tools = [ - { text: "tool1", value: "tool1" }, - { text: "tool2", value: "tool2" }, - { text: "tool3", value: "tool3" }, - { text: "tool4", value: "tool4" }, - { text: "tool5", value: "tool5" }, + { text: "DUCK_DUCK_GO_SEARCH", value: "DUCK_DUCK_GO_SEARCH" }, + { text: "PUBMED", value: "PUBMED" }, + { text: "PYTHON_REPL", value: "PYTHON_REPL" }, + { text: "SEMANTIC_SCHOLER", value: "SEMANTIC_SCHOLER" }, + { text: "STACK_EXCHANGE", value: "STACK_EXCHANGE" }, + { text: "WIKIDATA", value: "WIKIDATA" }, + { text: "WIKIPEDIA", value: "WIKIPEDIA" }, + { text: "YAHOO_FINANCE", value: "YAHOO_FINANCE" }, + { text: "YUOUTUBE_SEARCH", value: "YUOUTUBE_SEARCH" }, ]; +const game = ` +"Chrono Quest: Time Traveler" is a narrative-driven web game where players embark on a thrilling journey through different historical periods to save the fabric of time. As a time-traveling adventurer, players must navigate various eras, from ancient civilizations to futuristic worlds, solving puzzles, interacting with historical figures, and altering events to prevent a catastrophic temporal paradox. +Players will face diverse challenges, from deciphering ancient codes in the Egyptian pyramids to outsmarting futuristic robots in a dystopian metropolis. Each decision impacts the course of history and the outcome of the game, leading to multiple branching storylines and endings. +With stunning visuals, immersive storytelling, and dynamic gameplay mechanics, "Chrono Quest: Time Traveler" offers an unforgettable experience that combines elements of adventure, strategy, and puzzle-solving. Dive into the depths of time and rewrite history in this epic web-based adventure game. +`; + export const missions: Array = [ { - name: "Mission1", + name: "Game Building", crew: agents, tasks: [ { - name: "Task1", - description: "description description description description", + name: "Code Task", + description: ` + You will create a game using python, these are the instructions: + + Instructions + ------------ + ${game} + + Your Final answer must be the full python code, only the python code and nothing else. + `, agent: agents[0], }, { - name: "Task2", - description: "description description description description", + name: "Review Task", + description: ` + You are helping create a game using python, these are the instructions: + + Instructions + ------------ + ${game} + + Using the code you got, check for errors. Check for logic errors, + syntax errors, missing imports, variable declarations, mismatched brackets, + and security vulnerabilities. + + Your Final answer must be the full python code, only the python code and nothing else. + `, + agent: agents[1], + }, + { + name: "Evaluate Task", + description: ` + You are helping create a game using python, these are the instructions: + + Instructions + ------------ + ${game} + + You will look over the code to insure that it is complete and + does the job that it is supposed to do. + + Your Final answer must be the full python code, only the python code and nothing else. + `, + agent: agents[2], }, ], verbose: true, diff --git a/tsconfig.json b/tsconfig.json index 7b28589..068633b 100644 --- a/tsconfig.json +++ b/tsconfig.json @@ -21,6 +21,6 @@ "@/*": ["./src/*"] } }, - "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"], + "include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts", "**/*.js", "postcss.config.cjs"], "exclude": ["node_modules"] }