diff --git a/README.md b/README.md index 68cddee..c04c9d1 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,9 @@ The future of Maps - [x] find minimalistic chatinterface for the left side -- [ ] add a minimalistic field where a user can enter a text together with an button +- [x] add a minimalistic field where a user can enter a text together with an button - [ ] find a one examples from existing chatgpt plugin what can be worth to implement in combination with the map + - [ ] user types in "go to X" and on the map it goes to X should i do a custom implementation for now or should i use existing tepl @@ -12,4 +13,9 @@ the thing holding me back using framework is that i later might want to use cust how should i implement this part with the chatinterface. either i use vercel chatbot or i use -if we build this from scratch than i dont even need supabase \ No newline at end of file +if we build this from scratch than i dont even need supabase + + +## backlog + +- [ ] add cyberpunk mode to map - if the user clicks one of the major cities here futuristic gen ai images of the city are displayed \ No newline at end of file diff --git a/api/index.py b/api/index.py index ef832ef..ec01dc0 100644 --- a/api/index.py +++ b/api/index.py @@ -57,6 +57,9 @@ async def get_events(): logger.error(f"Exception occurred: {e}") raise HTTPException(status_code=500, detail=str(e)) + +#how to build a good agent system with tools - thinking of just using openai function calling + @app.post("/api/ask") async def ask(req: dict): logger.info("Received request for /api/ask with data: %s", req) diff --git a/function_calling.ipynb b/function_calling.ipynb new file mode 100644 index 0000000..d9c0283 --- /dev/null +++ b/function_calling.ipynb @@ -0,0 +1,230 @@ +{ + "cells": [ + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [ + "\"\"\" \n", + "the input will be a string and based on this string i need to call a function \n", + "\n", + "option i am considering:\n", + "\n", + "- use openai function calling\n", + "- create my own function calling framework\n", + "\n", + "really good blog https://docs.mistral.ai/capabilities/function_calling/\n", + "\"\"\"" + ] + }, + { + "cell_type": "code", + "execution_count": 1, + "metadata": {}, + "outputs": [], + "source": [ + "#tools \n", + "def go_to_place_in_map(place):\n", + " print(f\"going to {place}\")\n", + " #thats it for now - later i will add more functionalit" + ] + }, + { + "cell_type": "code", + "execution_count": 2, + "metadata": {}, + "outputs": [], + "source": [ + "tools = [\n", + " {\n", + " \"type\": \"function\",\n", + " \"function\": {\n", + " \"name\": \"go_to_place_in_map\",\n", + " \"description\": \"Go to a place in the map\",\n", + " \"parameters\": {\n", + " \"type\": \"object\",\n", + " \"properties\": {\n", + " \"place\": {\n", + " \"type\": \"string\",\n", + " \"description\": \"The name of the place to navigate to.\",\n", + " }\n", + " },\n", + " \"required\": [\"place\"],\n", + " },\n", + " },\n", + " }\n", + "]" + ] + }, + { + "cell_type": "code", + "execution_count": 3, + "metadata": {}, + "outputs": [], + "source": [ + "import functools\n", + "\n", + "names_to_functions = {\n", + " 'go_to_place_in_map': functools.partial(go_to_place_in_map)\n", + "}" + ] + }, + { + "cell_type": "code", + "execution_count": 6, + "metadata": {}, + "outputs": [], + "source": [ + "#this cell figures out what function to call\n", + "from openai import OpenAI\n", + "import os \n", + "\n", + "openai_api_key = os.environ.get(\"OPENAI_API_KEY\")\n", + "client = OpenAI(api_key=openai_api_key)\n", + "\n", + "\n", + "system=f\"\"\"\n", + "You are a chatbot on top of a map. Your job is to help the user navigate the map. You can use the available functions to help you with this task.\n", + "\"\"\"\n", + "user_query=\"Go to berlin.\"\n", + "user_content=f\"\"\"\n", + "You are giving a chat conversation and based on this conversation you need to decide if an function from the available functions needs to be called. the available functions are:\n", + "\n", + "---\n", + "{tools}\n", + "---\n", + "\n", + "in the case a function can be called return the function name and the arguments that need to be passed to the function in JSON. Its important that the name of the key for the function name is `function_name` and the name of the key for the arguments is `arguments`. In the case a function cannot be called return an empty JSON object. \n", + "\n", + "Following the chat conversation:\n", + "\n", + "---\n", + "{user_query}\n", + "---\n", + "\"\"\"\n", + "\n", + "\n", + "\n", + "completion = client.chat.completions.create(\n", + " model=\"gpt-3.5-turbo\",\n", + " response_format={ \"type\": \"json_object\" },\n", + " temperature=0.0,\n", + " messages=[\n", + " {\"role\": \"system\", \"content\": system},\n", + " {\"role\": \"user\", \"content\": user_content}\n", + " ]\n", + ")\n", + "response_content = completion.choices[0].message.content" + ] + }, + { + "cell_type": "code", + "execution_count": 7, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "{\n", + " \"function_name\": \"go_to_place_in_map\",\n", + " \"arguments\": {\n", + " \"place\": \"berlin\"\n", + " }\n", + "}\n" + ] + } + ], + "source": [ + "print(response_content)" + ] + }, + { + "cell_type": "code", + "execution_count": 8, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "go_to_place_in_map {'place': 'berlin'}\n", + "going to berlin\n" + ] + } + ], + "source": [ + "#this cell is executing a function if there is one to execute\n", + "import json\n", + "\n", + "response_json = json.loads(response_content)\n", + "\n", + "function_name = response_json[\"function_name\"]\n", + "function_params = response_json[\"arguments\"]\n", + "print(function_name, function_params)\n", + "\n", + "function_result = names_to_functions[function_name](**function_params)" + ] + }, + { + "cell_type": "code", + "execution_count": 11, + "metadata": {}, + "outputs": [ + { + "name": "stdout", + "output_type": "stream", + "text": [ + "If you need any more information or further assistance while you're in Berlin, feel free to ask. Enjoy your time in the city!\n" + ] + } + ], + "source": [ + "#generate final answer\n", + "prompt_for_final_response=\"Provide a final response to the user\"\n", + "\n", + "completion = client.chat.completions.create(\n", + " model=\"gpt-4-turbo\",\n", + " temperature=0.0,\n", + " messages = [\n", + " {\"role\": \"system\", \"content\": system},\n", + " {\"role\": \"user\", \"content\": user_query},\n", + " {\"role\": \"assistant\", \"content\": response_content},\n", + " {\"role\": \"user\", \"content\": prompt_for_final_response}\n", + "]\n", + ")\n", + "response_content = completion.choices[0].message.content\n", + "print(response_content)" + ] + }, + { + "cell_type": "code", + "execution_count": null, + "metadata": {}, + "outputs": [], + "source": [] + } + ], + "metadata": { + "kernelspec": { + "display_name": "base", + "language": "python", + "name": "python3" + }, + "language_info": { + "codemirror_mode": { + "name": "ipython", + "version": 3 + }, + "file_extension": ".py", + "mimetype": "text/x-python", + "name": "python", + "nbconvert_exporter": "python", + "pygments_lexer": "ipython3", + "version": "3.11.7" + } + }, + "nbformat": 4, + "nbformat_minor": 2 +} diff --git a/public/chat.js b/public/chat.js index 71460de..052f8cd 100644 --- a/public/chat.js +++ b/public/chat.js @@ -4,6 +4,8 @@ document.addEventListener("DOMContentLoaded", function() { const chatMessages = document.getElementById("chatMessages"); let isStreaming = false; // Flag to track if a response is being streamed + //const baseURL = window.location.hostname === "localhost" ? "http://localhost:8000" : "https://www.pantheon.so"; + function sendMessage() { if (isStreaming) { alert("Please wait for the current response to finish."); @@ -24,7 +26,7 @@ document.addEventListener("DOMContentLoaded", function() { isStreaming = true; // Set the flag to true when streaming starts - fetch("/api/ask", { + fetch("http://127.0.0.1:8000/api/ask", { method: "POST", headers: { "Content-Type": "application/json"