├── kai ├── modules.txt ├── config │ └── __init__.py ├── kai │ ├── __init__.py │ └── doctype │ │ ├── __init__.py │ │ ├── kai_agent │ │ ├── __init__.py │ │ ├── kai_agent.js │ │ ├── test_kai_agent.py │ │ ├── kai_agent.py │ │ └── kai_agent.json │ │ ├── kai_crew │ │ ├── __init__.py │ │ ├── kai_crew.js │ │ ├── test_kai_crew.py │ │ ├── kai_crew.py │ │ └── kai_crew.json │ │ ├── kai_job │ │ ├── __init__.py │ │ ├── kai_job.js │ │ ├── test_kai_job.py │ │ ├── kai_job.py │ │ └── kai_job.json │ │ ├── kai_llm │ │ ├── __init__.py │ │ ├── test_kai_llm.py │ │ ├── kai_llm.py │ │ ├── kai_llm.json │ │ └── kai_llm.js │ │ ├── kai_task │ │ ├── __init__.py │ │ ├── kai_task.js │ │ ├── test_kai_task.py │ │ ├── kai_task.py │ │ └── kai_task.json │ │ ├── kai_tool │ │ ├── __init__.py │ │ ├── kai_tool.js │ │ ├── test_kai_tool.py │ │ ├── kai_tool.py │ │ └── kai_tool.json │ │ ├── kai_agent_tool │ │ ├── __init__.py │ │ ├── kai_agent_tool.py │ │ └── kai_agent_tool.json │ │ ├── kai_crew_agent │ │ ├── __init__.py │ │ ├── kai_crew_agent.py │ │ └── kai_crew_agent.json │ │ ├── kai_crew_task │ │ ├── __init__.py │ │ ├── kai_crew_task.py │ │ └── kai_crew_task.json │ │ ├── kai_settings │ │ ├── __init__.py │ │ ├── test_kai_settings.py │ │ ├── kai_settings.js │ │ ├── kai_settings.json │ │ └── kai_settings.py │ │ ├── kai_task_tool │ │ ├── __init__.py │ │ ├── kai_task_tool.py │ │ └── kai_task_tool.json │ │ └── kai_task_context_task │ │ ├── __init__.py │ │ ├── kai_task_context_task.py │ │ └── kai_task_context_task.json ├── public │ └── .gitkeep ├── www │ └── __init__.py ├── templates │ ├── __init__.py │ └── pages │ │ └── __init__.py ├── __init__.py ├── patches.txt ├── toolbuilder.py ├── api.py ├── frappe_tools.py ├── kai_tools.py ├── hooks.py └── crewbuilder.py ├── img ├── image.png ├── image2.png ├── image3.png ├── image4.png ├── image5.png ├── image6.png ├── image7.png ├── image8.png └── image9.png ├── .gitignore ├── pyproject.toml ├── license.txt └── README.md /kai/modules.txt: -------------------------------------------------------------------------------- 1 | KAI -------------------------------------------------------------------------------- /kai/config/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/public/.gitkeep: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/www/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/templates/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/templates/pages/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_job/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_llm/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_tool/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/__init__.py: -------------------------------------------------------------------------------- 1 | __version__ = "0.0.1" 2 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent_tool/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_agent/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_task/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_settings/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_tool/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_context_task/__init__.py: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /img/image.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image.png -------------------------------------------------------------------------------- /img/image2.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image2.png -------------------------------------------------------------------------------- /img/image3.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image3.png -------------------------------------------------------------------------------- /img/image4.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image4.png -------------------------------------------------------------------------------- /img/image5.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image5.png -------------------------------------------------------------------------------- /img/image6.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image6.png -------------------------------------------------------------------------------- /img/image7.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image7.png -------------------------------------------------------------------------------- /img/image8.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image8.png -------------------------------------------------------------------------------- /img/image9.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/pibico/kai/main/img/image9.png -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .DS_Store 2 | *.pyc 3 | *.egg-info 4 | *.swp 5 | tags 6 | node_modules 7 | __pycache__ -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew/kai_crew.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI Crew", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_job/kai_job.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI Job", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task/kai_task.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI Task", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_tool/kai_tool.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI Tool", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent/kai_agent.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI Agent", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew/test_kai_crew.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAICrew(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_job/test_kai_job.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAIJob(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_llm/test_kai_llm.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAILLM(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task/test_kai_task.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAITask(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_tool/test_kai_tool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAITool(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent/test_kai_agent.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAIAgent(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_llm/kai_llm.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAILLM(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_settings/test_kai_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and Contributors 2 | # See license.txt 3 | 4 | # import frappe 5 | from frappe.tests.utils import FrappeTestCase 6 | 7 | 8 | class TestKAISettings(FrappeTestCase): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_tool/kai_tool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAITool(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_task/kai_crew_task.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAICrewTask(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_tool/kai_task_tool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAITaskTool(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent_tool/kai_agent_tool.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAIAgentTool(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_agent/kai_crew_agent.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAICrewAgent(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_context_task/kai_task_context_task.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | 7 | 8 | class KAITaskContextTask(Document): 9 | pass 10 | -------------------------------------------------------------------------------- /kai/patches.txt: -------------------------------------------------------------------------------- 1 | [pre_model_sync] 2 | # Patches added in this section will be executed before doctypes are migrated 3 | # Read docs to understand patches: https://frappeframework.com/docs/v14/user/en/database-migrations 4 | 5 | [post_model_sync] 6 | # Patches added in this section will be executed after doctypes are migrated -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task/kai_task.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | # import frappe 5 | from frappe.model.document import Document 6 | from crewai import Crew, Agent, Task, Process 7 | 8 | class KAITask(Document): 9 | def get_crewai_task(self): 10 | role = self.role 11 | goal = self.goal 12 | verbose = self.verbose 13 | return Task(role=role,goal=goal,verbose=verbose) 14 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent/kai_agent.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | import frappe 5 | from frappe.model.document import Document 6 | from crewai import Crew, Agent, Task, Process 7 | 8 | class KAIAgent(Document): 9 | def get_crewai_agent(self): 10 | role = self.role 11 | goal = self.goal 12 | verbose = self.verbose 13 | return Agent(role=role,goal=goal,verbose=verbose) 14 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_job/kai_job.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | import frappe 5 | from frappe.model.document import Document 6 | import json 7 | 8 | class KAIJob(Document): 9 | def run(self): 10 | kai_crew_name = self.crew 11 | crew = frappe.get_doc("KAI Crew",kai_crew_name) 12 | inputs = json.loads(self.inputs) 13 | output = crew.kickoff(inputs=inputs) 14 | self.output = output 15 | self.save() 16 | return output 17 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew/kai_crew.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | import frappe 5 | from frappe.model.document import Document 6 | from crewai import Crew, Agent, Task, Process 7 | import json 8 | from kai.crewbuilder import CrewBuilder 9 | 10 | class KAICrew(Document): 11 | 12 | def kickoff(self,**kwargs): 13 | kai_crew_name = self.name 14 | crewbuilder = CrewBuilder(kai_crew_name) 15 | inputs = kwargs.get("inputs") 16 | output = crewbuilder.kickoff(inputs=inputs) 17 | return output 18 | 19 | -------------------------------------------------------------------------------- /kai/toolbuilder.py: -------------------------------------------------------------------------------- 1 | import frappe 2 | from kai.frappe_tools import GetTool as GetFrappeTool 3 | from kai.kai_tools import GetTool as GetKAITool 4 | 5 | class ToolBuilder(): 6 | def make_tool(package_name,function_name,tool_config): 7 | print("ENTERING:toolbuilder.make_tool("+package_name+","+function_name+")") 8 | 9 | if package_name=="frappe_tools": 10 | print("ENTERING:GetFrappeTool("+function_name+")") 11 | return GetFrappeTool(function_name,tool_config) 12 | 13 | if package_name=="kai_tools": 14 | print("ENTERING:GetKAITool("+function_name+")") 15 | return GetKAITool(function_name,tool_config) 16 | 17 | return None -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [project] 2 | name = "kai" 3 | authors = [ 4 | { name = "Kemal Korucu", email = "kemal@korucutech.com"} 5 | ] 6 | description = "KAI" 7 | requires-python = ">=3.10" 8 | readme = "README.md" 9 | dynamic = ["version"] 10 | dependencies = [ 11 | # "frappe~=15.0.0" # Installed and managed by bench. 12 | "ollama~=0.1.8" 13 | "distro~=1.9.0" 14 | "openai~=1.20.0" 15 | "tqdm~=4.66.2" 16 | ] 17 | 18 | [build-system] 19 | requires = ["flit_core >=3.4,<4"] 20 | build-backend = "flit_core.buildapi" 21 | 22 | # These dependencies are only installed when developer mode is enabled 23 | [tool.bench.dev-dependencies] 24 | # package_name = "~=1.1.0" 25 | ollama = "~=0.1.8" 26 | distro = "~=1.9.0" 27 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_task/kai_crew_task.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-19 11:31:53.931204", 5 | "doctype": "DocType", 6 | "editable_grid": 1, 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "task" 10 | ], 11 | "fields": [ 12 | { 13 | "fieldname": "task", 14 | "fieldtype": "Link", 15 | "in_list_view": 1, 16 | "label": "Task", 17 | "options": "KAI Task" 18 | } 19 | ], 20 | "index_web_pages_for_search": 1, 21 | "istable": 1, 22 | "links": [], 23 | "modified": "2024-04-20 10:05:06.255748", 24 | "modified_by": "Administrator", 25 | "module": "KAI", 26 | "name": "KAI Crew Task", 27 | "owner": "Administrator", 28 | "permissions": [], 29 | "sort_field": "modified", 30 | "sort_order": "DESC", 31 | "states": [] 32 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_tool/kai_task_tool.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-19 11:23:09.629597", 5 | "doctype": "DocType", 6 | "editable_grid": 1, 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "tool" 10 | ], 11 | "fields": [ 12 | { 13 | "fieldname": "tool", 14 | "fieldtype": "Link", 15 | "in_list_view": 1, 16 | "label": "Tool", 17 | "options": "KAI Tool" 18 | } 19 | ], 20 | "index_web_pages_for_search": 1, 21 | "istable": 1, 22 | "links": [], 23 | "modified": "2024-04-23 12:54:02.388006", 24 | "modified_by": "Administrator", 25 | "module": "KAI", 26 | "name": "KAI Task Tool", 27 | "owner": "Administrator", 28 | "permissions": [], 29 | "sort_field": "modified", 30 | "sort_order": "DESC", 31 | "states": [] 32 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent_tool/kai_agent_tool.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-19 11:11:39.928757", 5 | "doctype": "DocType", 6 | "editable_grid": 1, 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "tool" 10 | ], 11 | "fields": [ 12 | { 13 | "fieldname": "tool", 14 | "fieldtype": "Link", 15 | "in_list_view": 1, 16 | "label": "Tool", 17 | "options": "KAI Tool" 18 | } 19 | ], 20 | "index_web_pages_for_search": 1, 21 | "istable": 1, 22 | "links": [], 23 | "modified": "2024-04-23 12:54:15.721152", 24 | "modified_by": "Administrator", 25 | "module": "KAI", 26 | "name": "KAI Agent Tool", 27 | "owner": "Administrator", 28 | "permissions": [], 29 | "sort_field": "modified", 30 | "sort_order": "DESC", 31 | "states": [] 32 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew_agent/kai_crew_agent.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-19 11:32:39.615499", 5 | "doctype": "DocType", 6 | "editable_grid": 1, 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "agent" 10 | ], 11 | "fields": [ 12 | { 13 | "fieldname": "agent", 14 | "fieldtype": "Link", 15 | "in_list_view": 1, 16 | "label": "Agent", 17 | "options": "KAI Agent" 18 | } 19 | ], 20 | "index_web_pages_for_search": 1, 21 | "istable": 1, 22 | "links": [], 23 | "modified": "2024-04-20 10:00:21.414084", 24 | "modified_by": "Administrator", 25 | "module": "KAI", 26 | "name": "KAI Crew Agent", 27 | "owner": "Administrator", 28 | "permissions": [], 29 | "sort_field": "modified", 30 | "sort_order": "DESC", 31 | "states": [] 32 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task_context_task/kai_task_context_task.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-19 11:26:27.215499", 5 | "doctype": "DocType", 6 | "editable_grid": 1, 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "task" 10 | ], 11 | "fields": [ 12 | { 13 | "fieldname": "task", 14 | "fieldtype": "Link", 15 | "in_list_view": 1, 16 | "label": "Task", 17 | "options": "KAI Task" 18 | } 19 | ], 20 | "index_web_pages_for_search": 1, 21 | "istable": 1, 22 | "links": [], 23 | "modified": "2024-04-23 16:09:57.177940", 24 | "modified_by": "Administrator", 25 | "module": "KAI", 26 | "name": "KAI Task Context Task", 27 | "owner": "Administrator", 28 | "permissions": [], 29 | "sort_field": "modified", 30 | "sort_order": "DESC", 31 | "states": [] 32 | } -------------------------------------------------------------------------------- /kai/api.py: -------------------------------------------------------------------------------- 1 | from typing import List 2 | import frappe 3 | import json 4 | from crewai import Crew, Agent, Task, Process 5 | 6 | 7 | @frappe.whitelist() 8 | def run(*args,**kwargs): 9 | try: 10 | job_doc = frappe.parse_json(kwargs.get("doc")) 11 | if job_doc.__unsaved: 12 | frappe.throw("Please save the document before runing it") 13 | frappe.publish_progress(25, title='Running KAI Job', description='Working...') 14 | job_name = job_doc.name 15 | job = frappe.get_doc("KAI Job",job_name) 16 | crew = frappe.get_doc("KAI Crew",job.crew) 17 | inputs = json.loads(job.inputs) 18 | output = crew.kickoff(inputs=inputs) 19 | job.output = output 20 | job.save() 21 | 22 | except Exception as e: 23 | frappe.msgprint(repr(e)) 24 | finally: 25 | frappe.publish_progress(100, title='Running KAI Job', description='Working...') 26 | 27 | 28 | -------------------------------------------------------------------------------- /kai/frappe_tools.py: -------------------------------------------------------------------------------- 1 | from crewai_tools import tool 2 | import frappe 3 | import json 4 | 5 | def GetTool(function_name,tool_config): 6 | print("ENTERING:frappe_tools.GetTool("+function_name+")") 7 | if function_name=="GetFrappeUserTool": 8 | return GetFrappeUserTool 9 | 10 | @tool("GetFrappeUserTool") 11 | def GetFrappeUserTool(email): 12 | """Given a user email address as input this tool returns detailed information about the user as output.""" 13 | print("ENTERING:frappe_tools.GetFrappeUserTool("+email+")") 14 | output = {} 15 | try: 16 | user_doc = frappe.get_doc("User",email) 17 | 18 | output["email"] = user_doc.email 19 | output["first_name"] = user_doc.first_name 20 | output["last_name"] = user_doc.last_name 21 | output["full_name"] = user_doc.full_name 22 | output["enabled"] = (user_doc.enabled==1) 23 | except: 24 | output="User NOT Found" 25 | return json.dumps(output) 26 | 27 | 28 | -------------------------------------------------------------------------------- /license.txt: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2024 Kemal Korucu 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_settings/kai_settings.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | frappe.ui.form.on("KAI Settings", { 5 | refresh(frm) { 6 | 7 | }, 8 | clear_response(frm) { 9 | frm.set_value('system_response', ''); 10 | }, 11 | send_request(frm) { 12 | frappe.call({ 13 | method: "kai.kai.doctype.kai_settings.kai_settings.ai_call", 14 | args: { 15 | enabled: frm.doc.enabled, 16 | llm: frm.doc.llm, 17 | 18 | system_prompt: frm.doc.system_prompt, 19 | agent_instruction_prompt: frm.doc.agent_instruction_prompt, 20 | user_request: frm.doc.user_request 21 | }, 22 | freeze: true, 23 | callback: (r) => { 24 | frm.set_value('system_response', r.message); 25 | console.log(r); 26 | }, 27 | error: (r) => { 28 | frm.set_value('system_response', "ERROR: " + JSON.stringify(r.message)); 29 | console.log(r); 30 | } 31 | }); 32 | } 33 | }); 34 | 35 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_job/kai_job.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [ 3 | { 4 | "action": "kai.api.run", 5 | "action_type": "Server Action", 6 | "label": "Run" 7 | } 8 | ], 9 | "allow_rename": 1, 10 | "autoname": "format:KAI-{##########}", 11 | "creation": "2024-04-20 07:12:44.291173", 12 | "doctype": "DocType", 13 | "engine": "InnoDB", 14 | "field_order": [ 15 | "crew", 16 | "inputs", 17 | "output" 18 | ], 19 | "fields": [ 20 | { 21 | "fieldname": "crew", 22 | "fieldtype": "Link", 23 | "in_list_view": 1, 24 | "label": "Crew", 25 | "options": "KAI Crew", 26 | "reqd": 1 27 | }, 28 | { 29 | "fieldname": "inputs", 30 | "fieldtype": "JSON", 31 | "label": "Inputs" 32 | }, 33 | { 34 | "fieldname": "output", 35 | "fieldtype": "Text", 36 | "label": "Output" 37 | } 38 | ], 39 | "index_web_pages_for_search": 1, 40 | "links": [], 41 | "modified": "2024-04-21 12:33:08.773100", 42 | "modified_by": "Administrator", 43 | "module": "KAI", 44 | "name": "KAI Job", 45 | "naming_rule": "Expression", 46 | "owner": "Administrator", 47 | "permissions": [ 48 | { 49 | "create": 1, 50 | "delete": 1, 51 | "email": 1, 52 | "export": 1, 53 | "print": 1, 54 | "read": 1, 55 | "report": 1, 56 | "role": "System Manager", 57 | "share": 1, 58 | "write": 1 59 | } 60 | ], 61 | "sort_field": "modified", 62 | "sort_order": "DESC", 63 | "states": [] 64 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_llm/kai_llm.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "autoname": "prompt", 5 | "creation": "2024-04-17 15:55:49.396084", 6 | "doctype": "DocType", 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "llm_provider", 10 | "load_settings_template", 11 | "settings" 12 | ], 13 | "fields": [ 14 | { 15 | "default": "{}", 16 | "fieldname": "settings", 17 | "fieldtype": "JSON", 18 | "label": "Settings", 19 | "reqd": 1 20 | }, 21 | { 22 | "fieldname": "load_settings_template", 23 | "fieldtype": "Button", 24 | "label": "Load Settings Template" 25 | }, 26 | { 27 | "fieldname": "llm_provider", 28 | "fieldtype": "Select", 29 | "in_list_view": 1, 30 | "label": "LLM Provider", 31 | "options": "AWS Bedrock\nGroqCloud\nOllama\nOpenAI", 32 | "reqd": 1 33 | } 34 | ], 35 | "index_web_pages_for_search": 1, 36 | "links": [], 37 | "modified": "2024-04-29 12:11:08.410221", 38 | "modified_by": "Administrator", 39 | "module": "KAI", 40 | "name": "KAI LLM", 41 | "naming_rule": "Set by user", 42 | "owner": "Administrator", 43 | "permissions": [ 44 | { 45 | "create": 1, 46 | "delete": 1, 47 | "email": 1, 48 | "export": 1, 49 | "print": 1, 50 | "read": 1, 51 | "report": 1, 52 | "role": "System Manager", 53 | "share": 1, 54 | "write": 1 55 | } 56 | ], 57 | "sort_field": "modified", 58 | "sort_order": "DESC", 59 | "states": [] 60 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_tool/kai_tool.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "autoname": "prompt", 5 | "creation": "2024-04-19 09:58:26.542824", 6 | "doctype": "DocType", 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "description", 10 | "from_package", 11 | "tool_function", 12 | "tool_config" 13 | ], 14 | "fields": [ 15 | { 16 | "fieldname": "description", 17 | "fieldtype": "Text", 18 | "label": "Description" 19 | }, 20 | { 21 | "fieldname": "from_package", 22 | "fieldtype": "Select", 23 | "label": "From Package", 24 | "options": "crewai_tools\nlangchain_community.tools\nkai_tools\nfrappe_tools" 25 | }, 26 | { 27 | "fieldname": "tool_config", 28 | "fieldtype": "JSON", 29 | "label": "Tool Config" 30 | }, 31 | { 32 | "fieldname": "tool_function", 33 | "fieldtype": "Data", 34 | "label": "Tool Function" 35 | } 36 | ], 37 | "index_web_pages_for_search": 1, 38 | "links": [], 39 | "modified": "2024-04-30 09:00:31.163310", 40 | "modified_by": "Administrator", 41 | "module": "KAI", 42 | "name": "KAI Tool", 43 | "naming_rule": "Set by user", 44 | "owner": "Administrator", 45 | "permissions": [ 46 | { 47 | "create": 1, 48 | "delete": 1, 49 | "email": 1, 50 | "export": 1, 51 | "print": 1, 52 | "read": 1, 53 | "report": 1, 54 | "role": "System Manager", 55 | "share": 1, 56 | "write": 1 57 | } 58 | ], 59 | "sort_field": "modified", 60 | "sort_order": "DESC", 61 | "states": [] 62 | } -------------------------------------------------------------------------------- /kai/kai_tools.py: -------------------------------------------------------------------------------- 1 | from datetime import datetime 2 | from crewai_tools import tool 3 | import json 4 | 5 | 6 | def GetTool(function_name,tool_config): 7 | print("ENTERING:kai_tools.GetTool("+function_name+")") 8 | if function_name=="CalculatorTool": 9 | return CalculatorTool 10 | if function_name=="GetCurrentDateTool": 11 | return GetCurrentDateTool 12 | if function_name=="GetCurrentTimeTool": 13 | return GetCurrentTimeTool 14 | return None 15 | 16 | @tool("CalculatorTool") 17 | def CalculatorTool(expression): 18 | """Useful to perform any mathematical calculations, 19 | like sum, minus, multiplication, division, etc. 20 | The input to this tool should be a mathematical 21 | expression, a couple examples are `200*7` or `5000/2*10` 22 | """ 23 | try: 24 | print("ENTERING:kai_tools.CalculatorTool()") 25 | return eval(expression) 26 | except SyntaxError: 27 | return "Error: Invalid syntax in mathematical expression" 28 | 29 | @tool("GetCurrentDateTool") 30 | def GetCurrentDateTool()->str: 31 | """Returns the current date. This tool gives you access to local system date.""" 32 | try: 33 | print("ENTERING:kai_tools.GetCurrentDateTool()") 34 | return datetime.now().date().isoformat() 35 | except Exception: 36 | return "Error getting current date" 37 | 38 | @tool("GetCurrentTimeTool") 39 | def GetCurrentTimeTool()->str: 40 | """Returns the current time. This tool gives you access to local system time. 41 | This tool's response should be accepted and used as accurate and truthfull. 42 | """ 43 | try: 44 | print("ENTERING:kai_tools.GetCurrentTimeTool()") 45 | return datetime.now().time().strftime('%H:%M:%S') 46 | except Exception: 47 | return "Error getting current time" -------------------------------------------------------------------------------- /kai/kai/doctype/kai_llm/kai_llm.js: -------------------------------------------------------------------------------- 1 | // Copyright (c) 2024, Kemal Korucu and contributors 2 | // For license information, please see license.txt 3 | 4 | // frappe.ui.form.on("KAI LLM", { 5 | // refresh(frm) { 6 | 7 | // }, 8 | // }); 9 | 10 | frappe.ui.form.on("KAI LLM", { 11 | load_settings_template(frm) { 12 | console.log(frm); 13 | if (frm.doc.settings=='{}' || frm.doc.settings=='') { 14 | if (frm.doc.llm_provider=='Ollama') { 15 | template = `{ 16 | "base_url": "http://localhost:11434", 17 | "model": "llama3", 18 | "num_ctx": 2048, 19 | "num_gpu": 1, 20 | "repeat_last_n": 64, 21 | "repeat_penalty": 1.1, 22 | "temperature": 0, 23 | "top_k": 40, 24 | "top_p": 0.9, 25 | "timeout": 180, 26 | }`; 27 | frm.set_value("settings",template); 28 | } else if (frm.doc.llm_provider=='GroqCloud') { 29 | template = `{ 30 | "groq_api_key": "gsk_...", 31 | "groq_api_base": "", 32 | "model_name": "llama....", 33 | "model_kwargs" : {}, 34 | "groq_proxy": "", 35 | "request_timeout": 180.0, 36 | "n": 1, 37 | "temperature": 0.7, 38 | "max_tokens": 1024, 39 | "top_p": 1, 40 | "streaming": false, 41 | "max_retries": 2, 42 | "verbose": false 43 | }`; 44 | frm.set_value("settings",template); 45 | } else if (frm.doc.llm_provider=='AWS Bedrock') { 46 | template = `{ 47 | 48 | }` 49 | frm.set_value("settings",template); 50 | } else if (frm.doc.llm_provider=='OpenAI') { 51 | template = `{ 52 | 53 | }` 54 | frm.set_value("settings",template); 55 | } else { 56 | frappe.msgprint("Unkown LLM Provider"); 57 | } 58 | } else { 59 | frappe.msgprint("Settings Not Empty!"); 60 | } 61 | } 62 | }); -------------------------------------------------------------------------------- /kai/kai/doctype/kai_task/kai_task.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "autoname": "prompt", 5 | "creation": "2024-04-19 09:57:22.465011", 6 | "doctype": "DocType", 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "agent", 10 | "description", 11 | "expected_output", 12 | "tools", 13 | "context" 14 | ], 15 | "fields": [ 16 | { 17 | "description": "A clear, concise statement of what the task entails.", 18 | "fieldname": "description", 19 | "fieldtype": "Text", 20 | "in_list_view": 1, 21 | "label": "Description", 22 | "reqd": 1 23 | }, 24 | { 25 | "description": "The agent responsible for the task, assigned either directly or by the crew's process.", 26 | "fieldname": "agent", 27 | "fieldtype": "Link", 28 | "label": "Agent", 29 | "options": "KAI Agent" 30 | }, 31 | { 32 | "description": "A detailed description of what the task's completion looks like.", 33 | "fieldname": "expected_output", 34 | "fieldtype": "Text", 35 | "label": "Expected Output" 36 | }, 37 | { 38 | "description": "The functions or capabilities the agent can utilize to perform the task.", 39 | "fieldname": "tools", 40 | "fieldtype": "Table MultiSelect", 41 | "label": "Tools", 42 | "options": "KAI Task Tool" 43 | }, 44 | { 45 | "description": "Specifies tasks whose outputs are used as context for this task.", 46 | "fieldname": "context", 47 | "fieldtype": "Table MultiSelect", 48 | "label": "Context", 49 | "options": "KAI Task Context Task" 50 | } 51 | ], 52 | "index_web_pages_for_search": 1, 53 | "links": [], 54 | "modified": "2024-04-20 07:25:17.682790", 55 | "modified_by": "Administrator", 56 | "module": "KAI", 57 | "name": "KAI Task", 58 | "naming_rule": "Set by user", 59 | "owner": "Administrator", 60 | "permissions": [ 61 | { 62 | "create": 1, 63 | "delete": 1, 64 | "email": 1, 65 | "export": 1, 66 | "print": 1, 67 | "read": 1, 68 | "report": 1, 69 | "role": "System Manager", 70 | "share": 1, 71 | "write": 1 72 | } 73 | ], 74 | "sort_field": "modified", 75 | "sort_order": "DESC", 76 | "states": [] 77 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_settings/kai_settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "creation": "2024-04-16 12:52:23.152829", 5 | "doctype": "DocType", 6 | "engine": "InnoDB", 7 | "field_order": [ 8 | "enabled", 9 | "llm", 10 | "system_prompt", 11 | "section_break_xulr", 12 | "agent_instruction_prompt", 13 | "column_break_zcit", 14 | "user_request", 15 | "send_request", 16 | "column_break_qxgc", 17 | "system_response", 18 | "clear_response" 19 | ], 20 | "fields": [ 21 | { 22 | "default": "0", 23 | "fieldname": "enabled", 24 | "fieldtype": "Check", 25 | "label": "Enabled" 26 | }, 27 | { 28 | "fieldname": "system_prompt", 29 | "fieldtype": "Long Text", 30 | "label": "System Prompt" 31 | }, 32 | { 33 | "depends_on": "enabled", 34 | "fieldname": "section_break_xulr", 35 | "fieldtype": "Section Break", 36 | "label": "TEST CONSOLE" 37 | }, 38 | { 39 | "fieldname": "user_request", 40 | "fieldtype": "Long Text", 41 | "label": "User Request" 42 | }, 43 | { 44 | "fieldname": "system_response", 45 | "fieldtype": "Long Text", 46 | "label": "System Response" 47 | }, 48 | { 49 | "fieldname": "column_break_zcit", 50 | "fieldtype": "Column Break" 51 | }, 52 | { 53 | "fieldname": "send_request", 54 | "fieldtype": "Button", 55 | "label": "Send Request" 56 | }, 57 | { 58 | "fieldname": "clear_response", 59 | "fieldtype": "Button", 60 | "label": "Clear Response" 61 | }, 62 | { 63 | "fieldname": "agent_instruction_prompt", 64 | "fieldtype": "Long Text", 65 | "label": "Agent Instruction Prompt" 66 | }, 67 | { 68 | "fieldname": "column_break_qxgc", 69 | "fieldtype": "Column Break" 70 | }, 71 | { 72 | "fieldname": "llm", 73 | "fieldtype": "Link", 74 | "label": "LLM", 75 | "options": "KAI LLM" 76 | } 77 | ], 78 | "hide_toolbar": 1, 79 | "index_web_pages_for_search": 1, 80 | "issingle": 1, 81 | "links": [], 82 | "modified": "2024-04-19 12:10:26.596738", 83 | "modified_by": "Administrator", 84 | "module": "KAI", 85 | "name": "KAI Settings", 86 | "owner": "Administrator", 87 | "permissions": [ 88 | { 89 | "create": 1, 90 | "delete": 1, 91 | "email": 1, 92 | "print": 1, 93 | "read": 1, 94 | "role": "System Manager", 95 | "share": 1, 96 | "write": 1 97 | } 98 | ], 99 | "sort_field": "modified", 100 | "sort_order": "DESC", 101 | "states": [] 102 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_crew/kai_crew.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "autoname": "prompt", 5 | "creation": "2024-04-19 09:57:48.858463", 6 | "doctype": "DocType", 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "agents", 10 | "tasks", 11 | "process_flow", 12 | "verbose", 13 | "manager_llm", 14 | "function_calling_llm", 15 | "max_rpm", 16 | "full_output", 17 | "memory" 18 | ], 19 | "fields": [ 20 | { 21 | "description": "A list of agents that are part of the crew.", 22 | "fieldname": "agents", 23 | "fieldtype": "Table MultiSelect", 24 | "label": "Agents", 25 | "options": "KAI Crew Agent" 26 | }, 27 | { 28 | "description": "A list of tasks assigned to the crew.", 29 | "fieldname": "tasks", 30 | "fieldtype": "Table MultiSelect", 31 | "label": "Tasks", 32 | "options": "KAI Crew Task" 33 | }, 34 | { 35 | "description": "The process flow the crew follows.", 36 | "fieldname": "process_flow", 37 | "fieldtype": "Select", 38 | "label": "Process Flow", 39 | "options": "sequential\nhierarchical\nconsensual" 40 | }, 41 | { 42 | "default": "0", 43 | "description": "The verbosity level for logging during execution.", 44 | "fieldname": "verbose", 45 | "fieldtype": "Int", 46 | "label": "Verbose", 47 | "non_negative": 1 48 | }, 49 | { 50 | "description": "The language model used by the manager agent in a hierarchical process. Required when using a hierarchical process.", 51 | "fieldname": "manager_llm", 52 | "fieldtype": "Link", 53 | "label": "Manager LLM", 54 | "options": "KAI LLM" 55 | }, 56 | { 57 | "description": "If set, the crew will use this LLM to do function calling for tools for all agents in the crew. Each agent can have its own LLM, which overrides the crew's LLM for function calling.", 58 | "fieldname": "function_calling_llm", 59 | "fieldtype": "Link", 60 | "label": "Function Calling LLM", 61 | "options": "KAI LLM" 62 | }, 63 | { 64 | "default": "600", 65 | "description": "Maximum requests per minute the crew adheres to during execution.", 66 | "fieldname": "max_rpm", 67 | "fieldtype": "Int", 68 | "label": "Max RPM", 69 | "non_negative": 1 70 | }, 71 | { 72 | "default": "0", 73 | "description": "Whether the crew should return the full output with all tasks outputs or just the final output.", 74 | "fieldname": "full_output", 75 | "fieldtype": "Check", 76 | "label": "Full Output" 77 | }, 78 | { 79 | "description": "Utilized for storing execution memories.", 80 | "fieldname": "memory", 81 | "fieldtype": "Select", 82 | "label": "Memory", 83 | "options": "\nshort-term\nlong-term\nentity" 84 | } 85 | ], 86 | "index_web_pages_for_search": 1, 87 | "links": [ 88 | { 89 | "link_doctype": "KAI Agent", 90 | "link_fieldname": "name" 91 | }, 92 | { 93 | "link_doctype": "KAI LLM", 94 | "link_fieldname": "name" 95 | }, 96 | { 97 | "link_doctype": "KAI Task", 98 | "link_fieldname": "name" 99 | } 100 | ], 101 | "modified": "2024-04-20 16:35:17.648669", 102 | "modified_by": "Administrator", 103 | "module": "KAI", 104 | "name": "KAI Crew", 105 | "naming_rule": "Set by user", 106 | "owner": "Administrator", 107 | "permissions": [ 108 | { 109 | "create": 1, 110 | "delete": 1, 111 | "email": 1, 112 | "export": 1, 113 | "print": 1, 114 | "read": 1, 115 | "report": 1, 116 | "role": "System Manager", 117 | "share": 1, 118 | "write": 1 119 | } 120 | ], 121 | "sort_field": "modified", 122 | "sort_order": "DESC", 123 | "states": [] 124 | } -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | ## KAI 2 | 3 | KAI is a custom app for Frappe Framework that implements CrewAI framework to integrate AI Agents with Frappe Framework. 4 | If you are not familiar with these platforms please take a look at the following web sites. 5 | 6 | - https://www.crewai.com/ 7 | - https://frappeframework.com/ 8 | 9 | ### KEY CONCEPTS 10 | 11 | - LLM 12 | :: Large Language Models are machine learning models that can comprehend and generate human language text. 13 | - CREW 14 | :: A crew represents a collaborative group of agents working together to achieve a set of tasks. 15 | - AGENT 16 | :: An agent is an autonomous unit programmed to perform TASKS, make decisions and communicate with other agents. 17 | - TASK 18 | :: Specific assignments completed by agents. 19 | - TOOL 20 | :: A tool is a skill or function that agents can utilize to perform various actions. 21 | - JOB 22 | :: Set of Inputs given to a crew to be used by agents to produce a result or output. 23 | 24 | LLM, CREW, AGENT, TASK, TOOL, JOB are implemented as DocType.\ 25 | So you can create unlimited Crews, Agents and Tasks to accomplish unique goals.\ 26 | You can interact with Crews via UI or python fucntion calls.\ 27 | 28 | Currently KAI can interface with the following LLM providers: 29 | - GroqCloud (fastest, free for now) 30 | - Ollama (local, slow but free) 31 | - OpenAI (soon, paid) 32 | - AWS Bedrock (soon, paid) 33 | 34 | We have tested KAI with llama3-8B and llama3-70B on GroqCloud but there is no reason why you cannot use other LLMs. 35 | 36 | ### INSTALLATION 37 | 38 | Since KAI is a Custom Frappe App it can be installed using frappe bench CLI commands. 39 | ``` 40 | bench get-app https://github.com/KorucuTech/kai.git 41 | ``` 42 | ``` 43 | bench --site your-site-name install kai 44 | ``` 45 | 46 | 47 | 48 | 49 | ### HOW TO RUN 50 | After you create CREW,AGENT,TASK,TOOL definitions you can run the crew with input to get an output. 51 | ``` 52 | import frappe 53 | 54 | crew_name = "My Science Crew" 55 | crew = frappe.get_doc("KAI Crew",crew_name) 56 | 57 | inputs = { "question": "Why is the sky Blue" } 58 | output = crew.kickoff(inputs=inputs) 59 | print(output) 60 | ``` 61 | 62 | How about this to verify if a user exists in Frappe and is Authorized. 63 | 64 | ``` 65 | import frappe 66 | 67 | crew_name = "My Security Crew" 68 | crew = frappe.get_doc("KAI Crew",crew_name) 69 | 70 | inputs = { "email": "me@here.com" } 71 | output = crew.kickoff(inputs=inputs) 72 | print(output) 73 | ``` 74 | 75 | You can also run a crew from a JOB 76 | 77 | 78 | 79 | This is the AGENT that answered the question. 80 | 81 | 82 | 83 | This was the TASK at hand. 84 | 85 | 86 | 87 | Agent decides if it needs to use a tool to complete a TASK. Here is a TOOL definition. 88 | 89 | 90 | 91 | And here is the very simple CREW that has only one AGENT that worked on the answer. 92 | 93 | 94 | 95 | You must have an LLM setup to begin with. 96 | You can setup multiple LLM providers and even assign different LLMs to each AGENT or CREW. 97 | 98 | 99 | 100 | Technically you can write these CREWS,AGENTS,TASKS etc. in pure python. 101 | KAI gives you a way to do it via frappe UI and use/call them directly from any frappe app or server script. 102 | 103 | It is possible to add more TOOLS to do much more with Frappe or even ERPNext. 104 | 105 | Here is a simple TOOL that checks if a user exists if given an email address. 106 | 107 | 108 | 109 | Here is the backend of this TOOL! 110 | 111 | 112 | 113 | Hard part of this is writing/testing/re-writing the "prompts" so that AGNETS can produce the result you want. 114 | 115 | Let me know what you think! 116 | 117 | ### LICENSE 118 | 119 | MIT 120 | -------------------------------------------------------------------------------- /kai/kai/doctype/kai_agent/kai_agent.json: -------------------------------------------------------------------------------- 1 | { 2 | "actions": [], 3 | "allow_rename": 1, 4 | "autoname": "prompt", 5 | "creation": "2024-04-19 09:56:42.207978", 6 | "doctype": "DocType", 7 | "engine": "InnoDB", 8 | "field_order": [ 9 | "role", 10 | "goal", 11 | "backstory", 12 | "tools", 13 | "llm", 14 | "function_calling_llm", 15 | "max_iterations", 16 | "max_rpm", 17 | "max_execution_time", 18 | "verbose", 19 | "allow_delegation" 20 | ], 21 | "fields": [ 22 | { 23 | "description": "Defines the agent's function within the crew. It determines the kind of tasks the agent is best suited for.", 24 | "fieldname": "role", 25 | "fieldtype": "Text", 26 | "in_list_view": 1, 27 | "label": "Role", 28 | "reqd": 1 29 | }, 30 | { 31 | "description": "The individual objective that the agent aims to achieve. It guides the agent's decision-making process.", 32 | "fieldname": "goal", 33 | "fieldtype": "Text", 34 | "in_list_view": 1, 35 | "label": "Goal", 36 | "reqd": 1 37 | }, 38 | { 39 | "description": "Provides context to the agent's role and goal, enriching the interaction and collaboration dynamics.", 40 | "fieldname": "backstory", 41 | "fieldtype": "Text", 42 | "in_list_view": 1, 43 | "label": "Backstory", 44 | "reqd": 1 45 | }, 46 | { 47 | "default": "0", 48 | "description": "(OPTIONAL) Setting this to True configures the internal logger to provide detailed execution logs, aiding in debugging and monitoring.", 49 | "fieldname": "verbose", 50 | "fieldtype": "Check", 51 | "label": "Verbose" 52 | }, 53 | { 54 | "default": "1", 55 | "description": "(OPTIONAL) Agents can delegate tasks or questions to one another, ensuring that each task is handled by the most suitable agent.", 56 | "fieldname": "allow_delegation", 57 | "fieldtype": "Check", 58 | "label": "Allow Delegation" 59 | }, 60 | { 61 | "default": "600", 62 | "description": "(OPTIONAL) Maximum execution time for an agent to execute a task (seconds)", 63 | "fieldname": "max_execution_time", 64 | "fieldtype": "Int", 65 | "label": "Max Execution Time", 66 | "non_negative": 1 67 | }, 68 | { 69 | "description": "(OPTIONAL) Set of capabilities or functions that the agent can use to perform tasks.", 70 | "fieldname": "tools", 71 | "fieldtype": "Table MultiSelect", 72 | "label": "Tools", 73 | "options": "KAI Agent Tool" 74 | }, 75 | { 76 | "description": "(OPTIONAL) Language model that will run the agent.", 77 | "fieldname": "llm", 78 | "fieldtype": "Link", 79 | "label": "LLM", 80 | "options": "KAI LLM" 81 | }, 82 | { 83 | "description": "(OPTIONAL) Specifies the language model that will handle the tool calling for this agent, overriding the crew function calling LLM if set.", 84 | "fieldname": "function_calling_llm", 85 | "fieldtype": "Link", 86 | "label": "Function Calling LLM", 87 | "options": "KAI LLM" 88 | }, 89 | { 90 | "default": "25", 91 | "description": "(OPTIONAL) The maximum number of iterations the agent can perform before being forced to give its best answer.", 92 | "fieldname": "max_iterations", 93 | "fieldtype": "Int", 94 | "label": "Max Iterations", 95 | "non_negative": 1 96 | }, 97 | { 98 | "default": "600", 99 | "description": "(OPTIONAL) The maximum number of requests per minute the agent can perform to avoid rate limits.", 100 | "fieldname": "max_rpm", 101 | "fieldtype": "Int", 102 | "label": "Max RPM", 103 | "non_negative": 1 104 | } 105 | ], 106 | "index_web_pages_for_search": 1, 107 | "links": [], 108 | "modified": "2024-04-29 21:15:36.532166", 109 | "modified_by": "Administrator", 110 | "module": "KAI", 111 | "name": "KAI Agent", 112 | "naming_rule": "Set by user", 113 | "owner": "Administrator", 114 | "permissions": [ 115 | { 116 | "create": 1, 117 | "delete": 1, 118 | "email": 1, 119 | "export": 1, 120 | "print": 1, 121 | "read": 1, 122 | "report": 1, 123 | "role": "System Manager", 124 | "share": 1, 125 | "write": 1 126 | } 127 | ], 128 | "sort_field": "modified", 129 | "sort_order": "DESC", 130 | "states": [] 131 | } -------------------------------------------------------------------------------- /kai/kai/doctype/kai_settings/kai_settings.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2024, Kemal Korucu and contributors 2 | # For license information, please see license.txt 3 | 4 | import frappe 5 | from frappe.model.document import Document 6 | import json 7 | from jinja2 import Template,Environment 8 | from ollama import Client 9 | from openai import OpenAI 10 | from groq import Groq 11 | from pydantic import BaseModel 12 | 13 | class KAISettings(Document): 14 | pass 15 | 16 | @frappe.whitelist() 17 | def ai_call(**args): 18 | 19 | cmd = args.get("cmd") 20 | if cmd != "kai.kai.doctype.kai_settings.kai_settings.ai_call": 21 | raise Exception("Invalid command") 22 | 23 | if args.get("enabled")=="1": 24 | llm_name = args.get("llm") 25 | connection = frappe.get_doc("KAI LLM",llm_name) 26 | settings = json.loads(connection.settings) 27 | 28 | if settings=={}: 29 | raise Exception("Invalid KAI Connection Settings") 30 | 31 | if connection.type=="Ollama": 32 | return ollama_call(settings,**args) 33 | elif connection.type=="OpenAI": 34 | return openai_call(settings,**args) 35 | elif connection.type=="AWS Bedrock": 36 | return aws_bedrock_call(settings,**args) 37 | elif connection.type=="GroqCloud": 38 | return groqcloud_call(settings,**args) 39 | else: 40 | raise Exception("Invalid KAI Connection Type") 41 | else: 42 | raise Exception("KAI is not enabled") 43 | return 44 | 45 | #================================================================================================================= 46 | def openai_call(settings,**args): 47 | 48 | client = OpenAI(organization="org-JER4FXhVu4MFXOvivkVp8VGJ", 49 | project="proj_akxU2ChkyMciKKTLymW77Nho", 50 | 51 | api_key=args.get("api_access_key")) 52 | 53 | agent_instruction_prompt = args.get("agent_instruction_prompt") 54 | print(agent_instruction_prompt) 55 | 56 | environment = Environment() 57 | template = environment.from_string(args.get("system_prompt")) 58 | system_prompt = template.render(agent_instruction_prompt=agent_instruction_prompt) 59 | 60 | print(system_prompt) 61 | 62 | 63 | response = client. Completion.create( 64 | engine="text-davinci-003", # Model to use for completion 65 | prompt=system_prompt, 66 | temperature=0.7, # Controls randomness of the response 67 | max_tokens=50, # Maximum number of tokens (words) in the response 68 | ) 69 | 70 | print(response) 71 | return response 72 | 73 | #================================================================================================================= 74 | def ollama_call(settings,**args): 75 | 76 | agent_instruction_prompt = args.get("agent_instruction_prompt") 77 | 78 | environment = Environment() 79 | template = environment.from_string(args.get("system_prompt")) 80 | system_prompt = template.render(agent_instruction_prompt=agent_instruction_prompt) 81 | 82 | print(system_prompt) 83 | 84 | client = Client(settings["host"]) 85 | response = client.chat(model=settings["model"],stream=settings["stream"],options=settings["options"], messages=[ 86 | { 87 | 'role': 'system', 88 | 'content': system_prompt 89 | }, 90 | { 91 | 'role': 'user', 92 | 'content': args.get("user_request") 93 | } 94 | ]) 95 | 96 | response = json.loads(json.dumps(response)) 97 | answer = response["message"]["content"] 98 | print(answer) 99 | return str(answer) 100 | 101 | #================================================================================================================= 102 | def aws_bedrock_call(settings,**args): 103 | return args 104 | 105 | #================================================================================================================= 106 | def groqcloud_call(settings,**args): 107 | client = Groq(api_key=settings["api_key"]) 108 | 109 | agent_instruction_prompt = args.get("agent_instruction_prompt") 110 | 111 | environment = Environment() 112 | template = environment.from_string(args.get("system_prompt")) 113 | system_prompt = template.render(agent_instruction_prompt=agent_instruction_prompt) 114 | 115 | print(system_prompt) 116 | 117 | response = client.chat.completions.create(messages=[ 118 | { 119 | 'role': 'system', 120 | 'content': system_prompt 121 | }, 122 | { 123 | 'role': 'user', 124 | 'content': args.get("user_request") 125 | } 126 | ], 127 | model=settings["model"], 128 | temperature=settings["temperature"] 129 | ) 130 | print(response) 131 | 132 | return response.choices[0].message.content 133 | 134 | 135 | -------------------------------------------------------------------------------- /kai/hooks.py: -------------------------------------------------------------------------------- 1 | app_name = "kai" 2 | app_title = "KAI" 3 | app_publisher = "Kemal Korucu" 4 | app_description = "KAI" 5 | app_email = "kemal@korucutech.com" 6 | app_license = "mit" 7 | # required_apps = [] 8 | 9 | # Includes in 10 | # ------------------ 11 | 12 | # include js, css files in header of desk.html 13 | # app_include_css = "/assets/kai/css/kai.css" 14 | # app_include_js = "/assets/kai/js/kai.js" 15 | 16 | # include js, css files in header of web template 17 | # web_include_css = "/assets/kai/css/kai.css" 18 | # web_include_js = "/assets/kai/js/kai.js" 19 | 20 | # include custom scss in every website theme (without file extension ".scss") 21 | # website_theme_scss = "kai/public/scss/website" 22 | 23 | # include js, css files in header of web form 24 | # webform_include_js = {"doctype": "public/js/doctype.js"} 25 | # webform_include_css = {"doctype": "public/css/doctype.css"} 26 | 27 | # include js in page 28 | # page_js = {"page" : "public/js/file.js"} 29 | 30 | # include js in doctype views 31 | # doctype_js = {"doctype" : "public/js/doctype.js"} 32 | # doctype_list_js = {"doctype" : "public/js/doctype_list.js"} 33 | # doctype_tree_js = {"doctype" : "public/js/doctype_tree.js"} 34 | # doctype_calendar_js = {"doctype" : "public/js/doctype_calendar.js"} 35 | 36 | # Svg Icons 37 | # ------------------ 38 | # include app icons in desk 39 | # app_include_icons = "kai/public/icons.svg" 40 | 41 | # Home Pages 42 | # ---------- 43 | 44 | # application home page (will override Website Settings) 45 | # home_page = "login" 46 | 47 | # website user home page (by Role) 48 | # role_home_page = { 49 | # "Role": "home_page" 50 | # } 51 | 52 | # Generators 53 | # ---------- 54 | 55 | # automatically create page for each record of this doctype 56 | # website_generators = ["Web Page"] 57 | 58 | # Jinja 59 | # ---------- 60 | 61 | # add methods and filters to jinja environment 62 | # jinja = { 63 | # "methods": "kai.utils.jinja_methods", 64 | # "filters": "kai.utils.jinja_filters" 65 | # } 66 | 67 | # Installation 68 | # ------------ 69 | 70 | # before_install = "kai.install.before_install" 71 | # after_install = "kai.install.after_install" 72 | 73 | # Uninstallation 74 | # ------------ 75 | 76 | # before_uninstall = "kai.uninstall.before_uninstall" 77 | # after_uninstall = "kai.uninstall.after_uninstall" 78 | 79 | # Integration Setup 80 | # ------------------ 81 | # To set up dependencies/integrations with other apps 82 | # Name of the app being installed is passed as an argument 83 | 84 | # before_app_install = "kai.utils.before_app_install" 85 | # after_app_install = "kai.utils.after_app_install" 86 | 87 | # Integration Cleanup 88 | # ------------------- 89 | # To clean up dependencies/integrations with other apps 90 | # Name of the app being uninstalled is passed as an argument 91 | 92 | # before_app_uninstall = "kai.utils.before_app_uninstall" 93 | # after_app_uninstall = "kai.utils.after_app_uninstall" 94 | 95 | # Desk Notifications 96 | # ------------------ 97 | # See frappe.core.notifications.get_notification_config 98 | 99 | # notification_config = "kai.notifications.get_notification_config" 100 | 101 | # Permissions 102 | # ----------- 103 | # Permissions evaluated in scripted ways 104 | 105 | # permission_query_conditions = { 106 | # "Event": "frappe.desk.doctype.event.event.get_permission_query_conditions", 107 | # } 108 | # 109 | # has_permission = { 110 | # "Event": "frappe.desk.doctype.event.event.has_permission", 111 | # } 112 | 113 | # DocType Class 114 | # --------------- 115 | # Override standard doctype classes 116 | 117 | # override_doctype_class = { 118 | # "ToDo": "custom_app.overrides.CustomToDo" 119 | # } 120 | 121 | # Document Events 122 | # --------------- 123 | # Hook on document methods and events 124 | 125 | # doc_events = { 126 | # "*": { 127 | # "on_update": "method", 128 | # "on_cancel": "method", 129 | # "on_trash": "method" 130 | # } 131 | # } 132 | 133 | # Scheduled Tasks 134 | # --------------- 135 | 136 | # scheduler_events = { 137 | # "all": [ 138 | # "kai.tasks.all" 139 | # ], 140 | # "daily": [ 141 | # "kai.tasks.daily" 142 | # ], 143 | # "hourly": [ 144 | # "kai.tasks.hourly" 145 | # ], 146 | # "weekly": [ 147 | # "kai.tasks.weekly" 148 | # ], 149 | # "monthly": [ 150 | # "kai.tasks.monthly" 151 | # ], 152 | # } 153 | 154 | # Testing 155 | # ------- 156 | 157 | # before_tests = "kai.install.before_tests" 158 | 159 | # Overriding Methods 160 | # ------------------------------ 161 | # 162 | # override_whitelisted_methods = { 163 | # "frappe.desk.doctype.event.event.get_events": "kai.event.get_events" 164 | # } 165 | # 166 | # each overriding function accepts a `data` argument; 167 | # generated from the base implementation of the doctype dashboard, 168 | # along with any modifications made in other Frappe apps 169 | # override_doctype_dashboards = { 170 | # "Task": "kai.task.get_dashboard_data" 171 | # } 172 | 173 | # exempt linked doctypes from being automatically cancelled 174 | # 175 | # auto_cancel_exempted_doctypes = ["Auto Repeat"] 176 | 177 | # Ignore links to specified DocTypes when deleting documents 178 | # ----------------------------------------------------------- 179 | 180 | # ignore_links_on_delete = ["Communication", "ToDo"] 181 | 182 | # Request Events 183 | # ---------------- 184 | # before_request = ["kai.utils.before_request"] 185 | # after_request = ["kai.utils.after_request"] 186 | 187 | # Job Events 188 | # ---------- 189 | # before_job = ["kai.utils.before_job"] 190 | # after_job = ["kai.utils.after_job"] 191 | 192 | # User Data Protection 193 | # -------------------- 194 | 195 | # user_data_fields = [ 196 | # { 197 | # "doctype": "{doctype_1}", 198 | # "filter_by": "{filter_by}", 199 | # "redact_fields": ["{field_1}", "{field_2}"], 200 | # "partial": 1, 201 | # }, 202 | # { 203 | # "doctype": "{doctype_2}", 204 | # "filter_by": "{filter_by}", 205 | # "partial": 1, 206 | # }, 207 | # { 208 | # "doctype": "{doctype_3}", 209 | # "strict": False, 210 | # }, 211 | # { 212 | # "doctype": "{doctype_4}" 213 | # } 214 | # ] 215 | 216 | # Authentication and authorization 217 | # -------------------------------- 218 | 219 | # auth_hooks = [ 220 | # "kai.auth.validate" 221 | # ] 222 | 223 | # Automatically update python controller files with type annotations for this app. 224 | # export_python_type_annotations = True 225 | 226 | # default_log_clearing_doctypes = { 227 | # "Logging DocType Name": 30 # days to retain logs 228 | # } 229 | 230 | -------------------------------------------------------------------------------- /kai/crewbuilder.py: -------------------------------------------------------------------------------- 1 | import frappe 2 | from crewai import Crew, Agent, Task, Process 3 | from langchain_community.chat_models import ChatOllama 4 | from langchain_openai import ChatOpenAI, OpenAI 5 | from langchain_groq import ChatGroq 6 | from kai.toolbuilder import ToolBuilder 7 | import json 8 | import pprint 9 | import os 10 | 11 | class CrewBuilder: 12 | def __init__(self,kai_crew_name): 13 | print("ENTERING:__init__("+kai_crew_name+")") 14 | #These act as cache for created objects 15 | self.llm_list = {} 16 | self.tool_list = {} 17 | self.task_list = {} 18 | self.agent_list = {} 19 | 20 | # Variables for passing obejcts to crew at the end 21 | self.crew = None 22 | self.crew_tasks = [] 23 | self.crew_agents = [] 24 | self.crew_manager_llm = None 25 | self.crew_function_calling_llm = None 26 | 27 | # Get "KAI Crew" Doc by crew name 28 | self.kai_crew_doc = frappe.get_doc("KAI Crew",kai_crew_name) 29 | print("CREW.AGENTS:",self.kai_crew_doc.agents) 30 | print("CREW.TASKS:",self.kai_crew_doc.tasks) 31 | 32 | # Set Crew Config from doc 33 | self.crew_config = { 34 | 'process': self.kai_crew_doc.process_flow, 35 | 'verbose': self.kai_crew_doc.verbose, 36 | 'max_rpm': self.kai_crew_doc.max_rpm, 37 | 'full_output': self.kai_crew_doc.full_output, 38 | 'memory': self.kai_crew_doc.memory 39 | } 40 | 41 | # Set Manager LLM for Crew from doc 42 | m_llm = self.get_llm(self.kai_crew_doc.manager_llm) 43 | if m_llm: 44 | self.crew_manager_llm = m_llm 45 | 46 | # Set Function Calling LLM for Crew 47 | f_llm = self.get_llm(self.kai_crew_doc.function_calling_llm) 48 | if f_llm: 49 | self.crew_function_calling_llm = f_llm 50 | 51 | # Set Agents for Crew 52 | if self.kai_crew_doc.agents==[]: 53 | raise Exception("KAI Crew has no actions assigned") 54 | else: 55 | for kai_agent in self.kai_crew_doc.agents: 56 | kai_agent_name = kai_agent.agent 57 | agent = self.get_agent(kai_agent_name) 58 | if agent: 59 | self.crew_agents.append(agent) 60 | 61 | # Set Tasks for Crew 62 | if self.kai_crew_doc.tasks==[]: 63 | raise Exception("KAI Crew has no tasks assigned") 64 | else: 65 | for kai_task in self.kai_crew_doc.tasks: 66 | kai_task_name = kai_task.task 67 | task = self.get_task(kai_task_name) 68 | if task: 69 | self.crew_tasks.append(task) 70 | 71 | # Build Crew 72 | self.crew = Crew(agents=self.crew_agents, 73 | tasks=self.crew_tasks, 74 | process=self.kai_crew_doc.process_flow, 75 | verbode=self.kai_crew_doc.verbose, 76 | manager_llm=self.crew_manager_llm, 77 | function_calling_llm=self.crew_function_calling_llm 78 | ) 79 | 80 | 81 | # Create or return an existing LLM 82 | def get_llm(self,kai_llm_name): 83 | print("ENTERING:get_llm("+kai_llm_name+")") 84 | # if llm name not provided return None 85 | if not kai_llm_name: 86 | return None 87 | # if LLM is already created just return it 88 | if kai_llm_name in self.llm_list: 89 | return self.llm_list[kai_llm_name] 90 | else: 91 | kai_llm_doc = frappe.get_doc("KAI LLM",kai_llm_name) 92 | llm_provider = kai_llm_doc.llm_provider 93 | llm_settings = json.loads(kai_llm_doc.settings) 94 | 95 | # Create llm based on llm provider type 96 | if llm_provider=='Ollama': 97 | os.environ["OPENAI_API_KEY"] = "NA" 98 | llm = ChatOpenAI(model=llm_settings["model"], 99 | base_url = llm_settings["base_url"]) 100 | if llm: 101 | self.llm_list[kai_llm_name] = llm 102 | return llm 103 | elif llm_provider=='OpenAI': 104 | pass 105 | elif llm_provider=='AWS Bedrock': 106 | pass 107 | elif llm_provider=='GroqCloud': 108 | llm = ChatGroq( 109 | #groq_api_base=llm_settings["groq_api_base"], 110 | temperature=llm_settings["temperature"], 111 | groq_api_key=llm_settings["groq_api_key"], 112 | model_name=llm_settings["model_name"], 113 | streaming=llm_settings["streaming"], 114 | max_retries=llm_settings["max_retries"], 115 | max_tokens=llm_settings["max_tokens"], 116 | verbose=llm_settings["verbose"] 117 | ) 118 | if llm: 119 | self.llm_list[kai_llm_name] = llm 120 | return llm 121 | else: 122 | raise Exception("Unknow LLM Provider") 123 | 124 | # Create or return an existing Agent 125 | def get_agent(self,kai_agent_name): 126 | print("ENTERING:get_agent("+kai_agent_name+")") 127 | # if agent name is not provided return None 128 | if not kai_agent_name: 129 | return None 130 | # If agent is already created just rewutn it 131 | if kai_agent_name in self.agent_list: 132 | return self.agent_list[kai_agent_name] 133 | else: 134 | kai_agent_doc = frappe.get_doc("KAI Agent",kai_agent_name) 135 | agent_tools=[] 136 | for kai_agent_tool in kai_agent_doc.tools: 137 | kai_agent_tool_name = kai_agent_tool.tool 138 | kai_tool = frappe.get_doc("KAI Tool",kai_agent_tool_name) 139 | tool = self.get_tool(kai_tool.name) 140 | if tool: 141 | agent_tools.append(tool) 142 | 143 | agent = Agent(role=kai_agent_doc.role, 144 | goal=kai_agent_doc.goal, 145 | backstory=kai_agent_doc.backstory, 146 | llm=self.get_llm(kai_agent_doc.llm), 147 | function_calling_llm=self.get_llm(kai_agent_doc.function_calling_llm), 148 | max_iter=kai_agent_doc.max_iterations, 149 | max_rpm=kai_agent_doc.max_rpm, 150 | max_execution_time=kai_agent_doc.max_execution_time, 151 | verbose=kai_agent_doc.verbose, 152 | allow_delegation=kai_agent_doc.allow_delegation, 153 | tools=agent_tools 154 | ) 155 | # Save the created Agent 156 | if agent: 157 | self.agent_list[kai_agent_name] = agent 158 | return agent 159 | 160 | # Create or return an existing Task 161 | def get_task(self,kai_task_name): 162 | print("ENTERING:get_task("+kai_task_name+")") 163 | # if task name is not provided return None 164 | if not kai_task_name: 165 | return None 166 | # If task is already created just return it 167 | if kai_task_name in self.task_list: 168 | return self.task_list[kai_task_name] 169 | else: 170 | kai_task_doc = frappe.get_doc("KAI Task",kai_task_name) 171 | # Get Tools for the Task 172 | task_tools=[] 173 | for kai_task_tool in kai_task_doc.tools: 174 | kai_task_tool_name = kai_task_tool.tool 175 | kai_tool = frappe.get_doc("KAI Tool",kai_task_tool_name) 176 | tool = self.get_tool(kai_tool.name) 177 | if tool: 178 | task_tools.append(tool) 179 | # Get Context Tasks for the Task 180 | task_context=[] 181 | for kai_context in kai_task_doc.context: 182 | kai_context_name = kai_context.task 183 | context = self.get_task(kai_context_name) 184 | if context: 185 | task_context.append(context) 186 | 187 | task = Task(agent=self.get_agent(kai_task_doc.agent), 188 | description=kai_task_doc.description, 189 | expected_output=kai_task_doc.expected_output, 190 | tools=task_tools, 191 | context=task_context 192 | ) 193 | if task: 194 | self.task_list[kai_task_name] = task 195 | return task 196 | 197 | # Create or return an existing Tool 198 | def get_tool(self,kai_tool_name): 199 | print("ENTERING:crewbuilder.get_tool("+kai_tool_name+")") 200 | # if tool name is not provided return None 201 | if not kai_tool_name: 202 | return None 203 | # If tool is already created just return it 204 | if kai_tool_name in self.tool_list: 205 | return self.tool_list[kai_tool_name] 206 | else: 207 | tool = self.make_tool(kai_tool_name) 208 | if tool: 209 | self.tool_list[kai_tool_name] = tool 210 | return tool 211 | 212 | # Return the generated Crew 213 | def get_crew(self): 214 | print("ENTERING:get_crew()") 215 | return self.crew 216 | 217 | # Run the Crew 218 | def kickoff(self,**kwargs): 219 | print("ENTERING:kickoff()") 220 | return self.crew.kickoff(inputs=kwargs.get("inputs")) 221 | 222 | 223 | def make_tool(self,kai_tool_name): 224 | # if tool name is not provided return None 225 | if not kai_tool_name: 226 | print("ENTERING:crewbuilder.make_tool(NONE)") 227 | return None 228 | try: 229 | print("ENTERING:crewbuilder.make_tool("+kai_tool_name+")") 230 | kai_tool_doc = frappe.get_doc("KAI Tool",kai_tool_name) 231 | kai_tool_package = kai_tool_doc.from_package 232 | kai_tool_function = kai_tool_doc.tool_function 233 | kai_tool_config = kai_tool_doc.tool_config 234 | tool = ToolBuilder.make_tool(kai_tool_package,kai_tool_function,kai_tool_config) 235 | except Exception: 236 | print("ERROR: make_tool") 237 | return None 238 | 239 | return tool 240 | 241 | 242 | 243 | --------------------------------------------------------------------------------