From 778aa5aa4a5ff2da586bd8009cdcdf85083a7908 Mon Sep 17 00:00:00 2001 From: Harrison Chase Date: Wed, 31 Jan 2024 08:43:06 -0800 Subject: [PATCH] update readme --- MEMORY.md | 40 -------------------------------- README.md | 55 ++++++++++++++++++++++++++++++++++++++++++-- _static/agent.png | Bin 0 -> 14249 bytes _static/chatbot.png | Bin 0 -> 6606 bytes _static/rag.png | Bin 0 -> 9689 bytes 5 files changed, 53 insertions(+), 42 deletions(-) delete mode 100644 MEMORY.md create mode 100644 _static/agent.png create mode 100644 _static/chatbot.png create mode 100644 _static/rag.png diff --git a/MEMORY.md b/MEMORY.md deleted file mode 100644 index 01128dd9..00000000 --- a/MEMORY.md +++ /dev/null @@ -1,40 +0,0 @@ -# Long-Term memory -Memory is one part of a cognitive architecture. -Just as with cognitive architectures, we've found in practice that more application specific forms of memory can go a long way in increasing the reliability and performance of your application. - -When we think of long term memory, the most general abstraction is: -- There exists some state that is tracked over time -- This state is updated at some period -- This state is combined into the prompt in some way - - -So when you're building your application, we would highly recommend asking the above questions: -- What is the state that is tracked? -- How is the state updated? -- How is the state used? - -Of course, this is easier said than done. -And then even if you are able to answer those questions, how can you actually build it? -We've decided to give this a go within OpenGPTs and build a specific type of chatbot with a specific form of memory. - -We decided to build a chatbot that could reliably serve as a dungeon master for a game of dungeon and dragons. -What is the specific type of memory we wanted for this? - -**What is the state that is tracked?** - -We wanted to first make sure to track the characters that we're involved in the game. Who they were, their descriptions, etc. This seems like something that should be known. -We then also wanted to track the state of the game itself. What had happened up to that point, where they were, etc. -We decided to split this into two distinct things - so we were actually tracking an updating two different states. - -**How is the state updated?** - -For the character description, we just wanted to update that once at beginning. So we wanted our chatbot to gather all relevant information, update that state, and then never update it again. -Afterwards, we wanted our chatbot to attempt to update the state of the game every turn. If it decides that no update is necessary, then we won't update it. Otherwise, we will override the current state of the game with an LLM generated new state. - -**How is the state used?** - -We wanted both the character description and the state of the game to always be inserted into the prompt. This is pretty straightforward since they were both text, so it was just some prompt engineering with some placeholders for those variables. - -## Implementation -You can see the implementation for this in [this file](backend/packages/agent-executor/agent_executor/dnd.py). -This should be easily modifiable to track another state - to do so, you will want to update the prompts and maybe some of the channels that are written to. \ No newline at end of file diff --git a/README.md b/README.md index 957a0566..88db65c6 100644 --- a/README.md +++ b/README.md @@ -1,7 +1,8 @@ # OpenGPTs This is an open source effort to create a similar experience to OpenAI's GPTs and Assistants API. -It builds upon [LangChain](https://github.com/langchain-ai/langchain), [LangServe](https://github.com/langchain-ai/langserve) and [LangSmith](https://smith.langchain.com/). +It is powered by [LangGraph](https://github.com/langchain-ai/langgraph) - a framework for creating agent runtimes. +It also builds upon [LangChain](https://github.com/langchain-ai/langchain), [LangServe](https://github.com/langchain-ai/langserve) and [LangSmith](https://smith.langchain.com/). OpenGPTs gives you more control, allowing you to configure: - The LLM you use (choose between the 60+ that LangChain offers) @@ -11,6 +12,16 @@ OpenGPTs gives you more control, allowing you to configure: - The retrieval algorithm you use - The chat history database you use +Most importantly, it gives you full control over the **cognitive architecture** of your application. +Currently, there are three different architectures implemented: + +- Assistant +- RAG +- Chatbot +- +See below for more details on those. +Because this is open source, if you do not like those architectures or want to modify them, you can easily do that! +

Configure Chat @@ -20,7 +31,6 @@ OpenGPTs gives you more control, allowing you to configure: - [GPTs: a simple hosted version](https://opengpts-example-vz4y4ooboq-uc.a.run.app/) - [Assistants API: a getting started guide](API.md) -- [Memory: how to use long-term memory](MEMORY.md) ## Quickstart @@ -176,6 +186,47 @@ The big appeal of OpenGPTs as compared to using OpenAI directly is that it is mo Specifically, you can choose which language models to use as well as more easily add custom tools. You can also use the underlying APIs directly and build a custom UI yourself should you choose. +### Cognitive Architecture + +This refers to the logic of how the GPT works. +There are currently three different architectures supported, but because they are all written in LangGraph, it is very easy to modify them or add your own. + +The three different architectures supported are assistants, RAG, and chatbots. + +**Assistants** + +Assistants can be equipped with arbitrary amount of tools and use an LLM to decide when to use them. This makes them the most flexible choice, but they work well with fewer models and can be less reliable. + +When creating an assistant, you specify a few things. + +First, you choose the language model to use. Only a few language models can be used reliably well: GPT-3.5, GPT-4, Claude, and Gemini. + +Second, you choose the tools to use. These can be predefined tools OR a retriever constructed from uploaded files. You can choose however many you want. + +The cognitive architecture can then be thought of as a loop. First, the LLM is called to determine what (if any) actions to take. If it decides to take actions, then those actions are executed and it loops back. If no actions are decided to take, then the response of the LLM is the final response, and it finishes the loop. + +![](_static/agent.png) + +This can be a really powerful and flexible architecture. This is probably closest to how us humans operate. However, these also can be not super reliable, and generally only work with the more performant models (and even then they can mess up). Therefore, we introduced a few simpler architecures. + +**RAGBot** + +One of the big use cases of the GPT store is uploading files and giving the bot knowledge of those files. What would it mean to make an architecture more focused on that use case? + +We added RAGBot - a retrieval-focused GPT with a straightforward architecture. First, a set of documents are retrieved. Then, those documents are passed in the system message to a separate call to the language model so it can respond. + +Compared to assistants, it is more structured (but less powerful). It ALWAYS looks up something - which is good if you know you want to look things up, but potentially wasteful if the user is just trying to have a normal conversation. Also importantly, this only looks up things once - so if it doesn’t find the right results then it will yield a bad result (compared to an assistant, which could decide to look things up again). + +![](_static/rag.png) + +Despite this being a more simple architecture, it is good for a few reasons. First, because it is simpler it can work pretty well with a wider variety of models (including lots of open source models). Second, if you have a use case where you don’t NEED the flexibility of an assistant (eg you know users will be looking up information every time) then it can be more focused. And third, compared to the final architecture below it can use external knowledge. + +**ChatBot** + +The final architecture is dead simple - just a call to a language model, parameterized by a system message. This allows the GPT to take on different personas and characters. This is clearly far less powerful than Assistants or RAGBots (which have access to external sources of data/computation) - but it’s still valuable! A lot of popular GPTs are just system messages at the end of the day, and CharacterAI is crushing it despite largely just being system messages as well. + +![](_static/chatbot.png) + ### LLMs You can choose between different LLMs to use. diff --git a/_static/agent.png b/_static/agent.png new file mode 100644 index 0000000000000000000000000000000000000000..6394a3b79e5d7fc6b6c57f21fd600b3db5056259 GIT binary patch literal 14249 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 literal 0 HcmV?d00001 diff --git a/_static/chatbot.png b/_static/chatbot.png new file mode 100644 index 0000000000000000000000000000000000000000..43537b4088bfd5b517a57e6fba5ed3282b09c1bc GIT binary patch literal 6606 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