From 34db92b99ae3d76488f020353233486863c023ba Mon Sep 17 00:00:00 2001 From: Nikita Bobrovskiy <39348559+bonk1t@users.noreply.github.com> Date: Sun, 4 Feb 2024 02:44:21 +0000 Subject: [PATCH] API-FrontEnd Alignment 2 (#22) Features: * Save sessions to Firestore API: * Add GET /session/list endpoint * Add GET /message endpoint * Add POST /tool/execute endpoint: for manual tool execution using natural language prompts. * Add /version endpoint Other: * Improved logging: using Queue to queue log messages and send them in a separate thread. * Add back previously removed tools: print_all_files_in_path.py, summarize_all_code_in_path.py * For SummarizeCode: Add output truncation for GPT-3 (16k tokens context window, we pass max 8k for better results) based on tokens * Update AutoGen to latest version * Update Python deps * Add tests (total coverage now is 84.74% (+2.90%)) --- .gitignore | 2 + frontend/package.json | 2 +- frontend/src/components/atoms.tsx | 206 ++++-- frontend/src/components/footer.tsx | 31 +- frontend/src/components/types.ts | 4 +- frontend/src/components/utils.ts | 27 +- .../src/components/views/builder/agents.tsx | 22 +- .../src/components/views/builder/build.tsx | 19 +- .../src/components/views/builder/models.tsx | 380 ++++++++++ .../src/components/views/builder/workflow.tsx | 22 +- .../src/components/views/gallery/gallery.tsx | 7 +- .../components/views/playground/chatbox.tsx | 5 +- .../src/components/views/playground/ra.tsx | 2 +- frontend/src/hooks/store.tsx | 4 + nalgonda/custom_tools/__init__.py | 4 + .../custom_tools/print_all_files_in_path.py | 66 ++ nalgonda/custom_tools/print_file_contents.py | 12 +- .../summarize_all_code_in_path.py | 87 +++ nalgonda/custom_tools/summarize_code.py | 4 +- nalgonda/custom_tools/utils.py | 10 + .../agent/default_config_ceo.json | 7 - .../agent/default_config_developer.json | 12 - .../agent/default_config_va.json | 10 - nalgonda/dependencies/auth.py | 7 + nalgonda/dependencies/dependencies.py | 11 +- nalgonda/exception_handlers.py | 11 +- nalgonda/main.py | 26 +- nalgonda/models/request_models.py | 11 +- nalgonda/models/session_config.py | 10 + .../agency_config_firestore_storage.py | 20 +- .../agent_config_firestore_storage.py | 13 +- .../repositories/session_firestore_storage.py | 26 + .../tool_config_firestore_storage.py | 13 +- nalgonda/routers/v1/api/__init__.py | 10 +- nalgonda/routers/v1/api/agency.py | 7 + nalgonda/routers/v1/api/agent.py | 9 + nalgonda/routers/v1/api/auth.py | 3 + nalgonda/routers/v1/api/message.py | 82 +++ nalgonda/routers/v1/api/session.py | 77 +-- nalgonda/routers/v1/api/tool.py | 39 +- nalgonda/routers/v1/api/version.py | 16 + nalgonda/routers/v1/websocket.py | 18 +- nalgonda/services/agency_manager.py | 22 +- nalgonda/services/agent_manager.py | 6 +- .../{thread_manager.py => session_manager.py} | 24 +- nalgonda/services/tool_service.py | 61 ++ nalgonda/utils.py | 34 - nalgonda/utils/__init__.py | 85 +++ nalgonda/utils/logging_utils/__init__.py | 63 ++ .../utils/logging_utils/json_formatter.py | 75 ++ nalgonda/version.py | 1 + package.json | 2 +- poetry.lock | 650 +++++++++++------- pyproject.toml | 11 +- requirements.txt | 198 +++--- tests/conftest.py | 6 + tests/functional/conftest.py | 10 +- tests/functional/test_logging_utils.py | 39 ++ .../v1/api/test_agency_endpoints.py | 2 +- .../functional/v1/api/test_agent_endpoints.py | 29 +- .../v1/api/test_message_endpoints.py | 125 ++++ .../v1/api/test_session_endpoints.py | 111 +-- .../functional/v1/api/test_tool_endpoints.py | 57 ++ tests/test_utils/mock_firestore_client.py | 5 +- .../test_print_all_files_in_path.py | 75 ++ .../test_summarize_all_code_in_path.py | 40 ++ .../test_session_firestore_storage.py | 50 ++ tests/unit/services/test_tool_service.py | 76 ++ tests/unit/utils/__init__.py | 0 tests/unit/utils/test_json_formatter.py | 84 +++ tests/unit/utils/test_utils.py | 50 ++ 71 files changed, 2587 insertions(+), 758 deletions(-) create mode 100644 frontend/src/components/views/builder/models.tsx create mode 100644 nalgonda/custom_tools/print_all_files_in_path.py create mode 100644 nalgonda/custom_tools/summarize_all_code_in_path.py delete mode 100644 nalgonda/data/default_configs/agent/default_config_ceo.json delete mode 100644 nalgonda/data/default_configs/agent/default_config_developer.json delete mode 100644 nalgonda/data/default_configs/agent/default_config_va.json create mode 100644 nalgonda/models/session_config.py create mode 100644 nalgonda/repositories/session_firestore_storage.py create mode 100644 nalgonda/routers/v1/api/message.py create mode 100644 nalgonda/routers/v1/api/version.py rename nalgonda/services/{thread_manager.py => session_manager.py} (66%) delete mode 100644 nalgonda/utils.py create mode 100644 nalgonda/utils/__init__.py create mode 100644 nalgonda/utils/logging_utils/__init__.py create mode 100644 nalgonda/utils/logging_utils/json_formatter.py create mode 100644 nalgonda/version.py create mode 100644 tests/functional/test_logging_utils.py create mode 100644 tests/functional/v1/api/test_message_endpoints.py create mode 100644 tests/unit/custom_tools/test_print_all_files_in_path.py create mode 100644 tests/unit/custom_tools/test_summarize_all_code_in_path.py create mode 100644 tests/unit/repositories/test_session_firestore_storage.py create mode 100644 tests/unit/services/test_tool_service.py create mode 100644 tests/unit/utils/__init__.py create mode 100644 tests/unit/utils/test_json_formatter.py create mode 100644 tests/unit/utils/test_utils.py diff --git a/.gitignore b/.gitignore index d4f02ae1..1dffeb5c 100644 --- a/.gitignore +++ b/.gitignore @@ -165,6 +165,8 @@ settings.json .env +*.log.jsonl + # UI folder nalgonda/ui/* nalgonda/data/agency_data/* diff --git a/frontend/package.json b/frontend/package.json index c364aa2f..c3c5f63d 100644 --- a/frontend/package.json +++ b/frontend/package.json @@ -1,6 +1,6 @@ { "name": "ai-in-hand-platform-ui", - "version": "1.0.0", + "version": "0.1.0", "private": true, "description": "AI in Hand Platform - Build and Test Your AI Workforce", "author": "AI in Hand Team", diff --git a/frontend/src/components/atoms.tsx b/frontend/src/components/atoms.tsx index f9071985..c01112ab 100644 --- a/frontend/src/components/atoms.tsx +++ b/frontend/src/components/atoms.tsx @@ -8,6 +8,8 @@ import { ArrowPathIcon, ArrowDownRightIcon, PencilIcon, + UserGroupIcon, + UsersIcon, } from "@heroicons/react/24/outline"; import React, { ReactNode, useEffect, useRef, useState } from "react"; import Icon from "./icons"; @@ -616,6 +618,14 @@ export const ModelSelector = ({ null ); const [editIndex, setEditIndex] = useState(null); + const [loading, setLoading] = useState(false); + const [error, setError] = useState(null); + + const [models, setModels] = useState([]); + const serverUrl = getServerUrl(); + + const { user } = React.useContext(appContext); + const listModelsUrl = `${serverUrl}/models?user_id=${user?.email}`; const sanitizeModelConfig = (config: IModelConfig) => { const sanitizedConfig: IModelConfig = { model: config.model }; @@ -628,6 +638,7 @@ export const ModelSelector = ({ const handleRemoveConfig = (index: number) => { const updatedConfigs = configs.filter((_, i) => i !== index); + setConfigs(updatedConfigs); }; @@ -637,6 +648,78 @@ export const ModelSelector = ({ setIsModalVisible(true); }; + const fetchModels = () => { + setError(null); + setLoading(true); + // const fetch; + const payLoad = { + method: "GET", + headers: { + "Content-Type": "application/json", + }, + }; + + const onSuccess = (data: any) => { + if (data && data.status) { + // message.success(data.message); + setModels(data.data); + } else { + message.error(data.message); + } + setLoading(false); + }; + const onError = (err: any) => { + setError(err); + message.error(err.message); + setLoading(false); + }; + fetchJSON(listModelsUrl, payLoad, onSuccess, onError); + }; + + useEffect(() => { + fetchModels(); + }, []); + + const modelItems: MenuProps["items"] = + models.length > 0 + ? models.map((model: IModelConfig, index: number) => ({ + key: index, + label: model.model, + value: index, + })) + : [ + { + key: -1, + label: "No models found", + value: 0, + }, + ]; + + const modelOnClick: MenuProps["onClick"] = ({ key }) => { + const selectedIndex = parseInt(key.toString()); + let selectedModel = models[selectedIndex]; + selectedModel = sanitizeModelConfig(selectedModel); + const updatedConfigs = [...configs, selectedModel]; + setConfigs(updatedConfigs); + }; + + const AddModelsDropDown = () => { + return ( + +
+ add +
+
+ ); + }; + const handleOk = () => { if (newModelConfig?.model.trim()) { const sanitizedConfig = sanitizeModelConfig(newModelConfig); @@ -707,24 +790,7 @@ export const ModelSelector = ({
{modelButtons} -
- showModal( - { - model: "", - api_key: "", - base_url: "", - api_type: "", - api_version: "", - }, - null - ) - } - > - add -
+
{ + if (key === "llm_config") { + if (value.config_list.length === 0) { + value = false; + } + } const updatedFlowSpec = { ...localFlowSpec, config: { ...localFlowSpec.config, [key]: value }, }; + console.log(updatedFlowSpec.config.llm_config); setLocalFlowSpec(updatedFlowSpec); setFlowSpec(updatedFlowSpec); }; - const onDebouncedControlChange = React.useCallback( - debounce((value: any, key: string) => { - onControlChange(value, key); - console.log("debounce"); - }, 3000), - [onControlChange] - ); - const llm_config = localFlowSpec.config.llm_config || { config_list: [] }; return ( @@ -1006,15 +1070,15 @@ export const AgentFlowSpecView = ({ title="System Message" className="mt-4" description="Free text to control agent behavior" - value={flowSpec.config.system_message} + value={flowSpec.config.instructions} control={