[
  {
    "path": ".github/actions/image_builder/action.yaml",
    "content": "name: 'Build Docker images for PromethAI'\ndescription: 'Build PromethAI-related Docker images and push to the Docker registry (AWS ECR)'\ninputs:\n  stage:\n    description: 'The stage of the pipeline, such as \"dev\" or \"prd\", for the PromethAI app'\n    required: true\n  aws_account_id:\n    description: 'The AWS account ID for the PromethAI app'\n    required: true\n  should_publish:\n    description: 'Whether to publish the PromethAI Docker image to AWS ECR; should be either \"true\" or \"false\"'\n    required: true\n  ecr_image_repo_name:\n    description: 'The Docker image ECR repository name for the PromethAI app, such as \"workflows\"'\n    required: true\n  dockerfile_location:\n    description: 'The  directory location of the Dockerfile for the PromethAI app'\n    required: true\n\nruns:\n  using: \"composite\"\n  steps:\n    - name: Build PromethAI App Docker image\n      shell: bash\n      env:\n        STAGE: ${{ inputs.stage }}\n      run: |\n        export SHA_SHORT=\"$(git rev-parse --short HEAD)\"\n        export CUR_DATE=\"$(date +%Y%m%d%H%M%S)\"\n        export VERSION=\"${{ inputs.stage }}-$CUR_DATE-$SHA_SHORT\"\n        export STAGE=\"${{ inputs.stage }}\"\n        export APP_DIR=\"$PWD/${{ inputs.dockerfile_location }}\"\n        image_name=\"${{ inputs.ecr_image_repo_name }}\" docker_login=\"true\" version=\"$VERSION\" account=\"${{ inputs.aws_account_id }}\" app_dir=\"$APP_DIR\" publish=\"${{ inputs.should_publish }}\" ./bin/dockerize\n        echo \"Docker tag is: $VERSION\"\n        echo $VERSION > /tmp/.DOCKER_IMAGE_VERSION\n"
  },
  {
    "path": ".github/workflows/cd.yaml",
    "content": "name: Publishing promethai-backend Docker image\n\non:\n  push:\n    branches:\n      - dev\n      - feature/*\n    paths-ignore:\n      - 'examples/**'\n      - 'document_store/**'\n      - '**.md'\n\nenv:\n  AWS_ROLE_DEV_CICD: \"arn:aws:iam::463722570299:role/promethai-dev-base-role-github-ci-cd\"\n  AWS_ACCOUNT_ID_DEV: \"463722570299\"\n\njobs:\n\n  publish_docker_to_ecr:\n    name: Publish Docker PromethAI image\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n      contents: read\n    steps:\n      - name: Take code from repo\n        uses: actions/checkout@v3\n      - name: Set environment variable for stage\n        id: set-env\n        run: |\n          if [[ \"${{ github.ref }}\" == \"refs/heads/main\" ]]; then\n            echo \"STAGE=prd\" >> $GITHUB_ENV\n            echo \"::set-output name=stage::prd\"\n          else\n            echo \"STAGE=dev\" >> $GITHUB_ENV\n            echo \"::set-output name=stage::dev\"\n          fi\n      - name: Use output\n        run: echo \"The stage is ${{ steps.set-env.outputs.stage }}\"\n      - name: Configure AWS credentials\n        uses: aws-actions/configure-aws-credentials@v1\n        with:\n          role-to-assume: ${{ env.AWS_ROLE_DEV_CICD }}\n          aws-region: eu-west-1\n      - name: Create Docker image and push to ECR\n        uses: ./.github/actions/image_builder\n        id: generate-promethai-docker\n        with:\n          stage: dev\n          aws_account_id: ${{ env.AWS_ACCOUNT_ID_DEV }}\n          should_publish: true\n          ecr_image_repo_name: promethai-dev-backend-promethai-backend\n          dockerfile_location: ./\n      - name: Export Docker image tag\n        id: export-promethai-docker-tag\n        run: |\n          export DOCKER_TAG=$(cat /tmp/.DOCKER_IMAGE_VERSION)\n          echo \"Docker tag is: $DOCKER_TAG\"\n          echo \"promethai_docker_tag_backend=$DOCKER_TAG\" >> $GITHUB_OUTPUT\n    outputs:\n      promethai_docker_tag_backend: ${{ steps.export-promethai-docker-tag.outputs.promethai_docker_tag_backend }}\n\n  apply_tf:\n    name: Trigger terraform apply workflow\n    runs-on: ubuntu-latest\n    needs: publish_docker_to_ecr\n    steps:\n      - name: TF apply workflow triggers step\n        uses: actions/github-script@v6\n        with:\n          github-token: ${{ secrets.PAT_FOR_CROSS_REPOS_CICD_TRIGGERING }}\n          script: |\n            await github.rest.actions.createWorkflowDispatch({\n              owner: 'topoteretes',\n              repo: 'PromethAI-Infra',\n              workflow_id: 'terraform.apply.yml',\n              ref: 'main'\n            })\n"
  },
  {
    "path": ".github/workflows/cd_prd.yaml",
    "content": "on:\n  push:\n    branches:\n        - main\n    paths-ignore:\n      - '**.md'\n      - 'examples/**'\nname: Publishing promethai-backend Docker image to prd ECR\n\nenv:\n  AWS_ROLE_DEV_CICD: \"arn:aws:iam::463722570299:role/promethai-dev-base-role-github-ci-cd\"\n  AWS_ACCOUNT_ID_DEV: \"463722570299\"\n  ENVIRONMENT: prd\n\njobs:\n\n  publish_docker_to_ecr:\n    name: Publish Docker PromethAI image\n    runs-on: ubuntu-latest\n    permissions:\n      id-token: write\n      contents: read\n    steps:\n      - name: Take code from repo\n        uses: actions/checkout@v3\n      - name: Set environment variable for stage\n        id: set-env\n        run: |\n          if [[ \"${{ github.ref }}\" == \"refs/heads/main\" ]]; then\n            echo \"STAGE=prd\" >> $GITHUB_ENV\n            echo \"::set-output name=stage::prd\"\n          else\n            echo \"STAGE=dev\" >> $GITHUB_ENV\n            echo \"::set-output name=stage::dev\"\n          fi\n      - name: Use output\n        run: echo \"The stage is ${{ steps.set-env.outputs.stage }}\"\n      - name: Configure AWS credentials\n        uses: aws-actions/configure-aws-credentials@v1\n        with:\n          role-to-assume: ${{ env.AWS_ROLE_DEV_CICD }}\n          aws-region: eu-west-1\n      - name: Create Docker image and push to ECR\n        uses: ./.github/actions/image_builder\n        id: generate-promethai-docker\n        with:\n          stage: prd\n          aws_account_id: ${{ env.AWS_ACCOUNT_ID_DEV }}\n          should_publish: true\n          ecr_image_repo_name: promethai-prd-backend-promethai-backend\n          dockerfile_location: ./\n      - name: Export Docker image tag\n        id: export-promethai-docker-tag\n        run: |\n          export DOCKER_TAG=$(cat /tmp/.DOCKER_IMAGE_VERSION)\n          echo \"Docker tag is: $DOCKER_TAG\"\n          echo \"promethai_docker_tag_backend=$DOCKER_TAG\" >> $GITHUB_OUTPUT\n\n#      - name: Create Tag and Release\n#        runs-on: ubuntu-latest\n#        uses: actions/checkout@v3\n#        needs: publish_docker_to_ecr  # ensure this job runs after Docker image is pushed\n#        steps:\n#          - name: Check out code\n#            uses: actions/checkout@v3\n#          - name: Bump version and push tag\n#            id: bump_version_and_push_tag\n#            uses: anothrNick/github-tag-action@1.34.0\n#            env:\n#              GITHUB_TOKEN: ${{ secrets.PAT_FOR_CROSS_REPOS_CICD_TRIGGERING }}\n#              WITH_V: true\n#              DEFAULT_BUMP: 'minor'  # or 'minor' or 'major'\n#          - name: Create Release\n#            id: create_release\n#            uses: actions/create-release@v1\n#            env:\n#              GITHUB_TOKEN: ${{ secrets.PAT_FOR_CROSS_REPOS_CICD_TRIGGERING }}\n#            with:\n#              tag_name: ${{ steps.bump_version_and_push_tag.outputs.tag }}\n#              release_name: Release ${{ steps.bump_version_and_push_tag.outputs.tag }}\n    outputs:\n      promethai_docker_tag_backend: ${{ steps.export-promethai-docker-tag.outputs.promethai_docker_tag_backend }}\n\n  apply_tf:\n    name: Trigger terraform apply workflow\n    runs-on: ubuntu-latest\n    needs: publish_docker_to_ecr\n    steps:\n      - name: TF apply workflow triggers step\n        uses: actions/github-script@v6\n        with:\n          github-token: ${{ secrets.PAT_FOR_CROSS_REPOS_CICD_TRIGGERING }}\n          script: |\n            await github.rest.actions.createWorkflowDispatch({\n              owner: 'topoteretes',\n              repo: 'PromethAI-Infra',\n              workflow_id: 'terraform.apply.yml',\n              ref: 'main'\n            })\n"
  },
  {
    "path": ".github/workflows/ci.yaml",
    "content": "name: Test build docker image for PromethAI backend app\n\non: pull_request\n\nenv:\n  AWS_ACCOUNT_ID_DEV: \"463722570299\"\n\njobs:\n\n  build_docker:\n    name: Build PromethAI Backend Docker App Image\n    runs-on: ubuntu-latest\n    steps:\n      - name: Check out PromethAI code\n        uses: actions/checkout@v3\n\n      - name: Build PromethAI backend Docker image tag\n        id: backend-docker-tag\n        run: |\n          export SHA_SHORT=\"$(git rev-parse --short HEAD)\"\n          export CUR_DATE=\"$(date +%Y%m%d%H%M%S)\"\n          export VERSION=\"dev-$CUR_DATE-$SHA_SHORT\"\n          image_name=\"backend\" docker_login=\"false\" version=\"$VERSION\" account=\"${{ env.AWS_ACCOUNT_ID_DEV }}\" app_dir=\"backend\" publish=\"false\" ./bin/dockerize\n          export DOCKER_TAG=$(cat /tmp/.DOCKER_IMAGE_VERSION)\n          echo \"Successfully built PromethAI backend Docker tag is: $DOCKER_TAG\"\n"
  },
  {
    "path": ".gitignore",
    "content": ".env\n__pycache__\ntst.py\n.idea"
  },
  {
    "path": "CODE_OF_CONDUCT.md",
    "content": "# Code of Conduct for Auto-GPT\n\n## 1. Purpose\n\nThe purpose of this Code of Conduct is to provide guidelines for contributors to the auto-gpt project on GitHub. We aim to create a positive and inclusive environment where all participants can contribute and collaborate effectively. By participating in this project, you agree to abide by this Code of Conduct.\n\n## 2. Scope\n\nThis Code of Conduct applies to all contributors, maintainers, and users of the auto-gpt project. It extends to all project spaces, including but not limited to issues, pull requests, code reviews, comments, and other forms of communication within the project.\n\n## 3. Our Standards\n\nWe encourage the following behavior:\n\n* Being respectful and considerate to others\n* Actively seeking diverse perspectives\n* Providing constructive feedback and assistance\n* Demonstrating empathy and understanding\n\nWe discourage the following behavior:\n\n* Harassment or discrimination of any kind\n* Disrespectful, offensive, or inappropriate language or content\n* Personal attacks or insults\n* Unwarranted criticism or negativity\n\n## 4. Reporting and Enforcement\n\nIf you witness or experience any violations of this Code of Conduct, please report them to the project maintainers by email or other appropriate means. The maintainers will investigate and take appropriate action, which may include warnings, temporary or permanent bans, or other measures as necessary.\n\nMaintainers are responsible for ensuring compliance with this Code of Conduct and may take action to address any violations.\n\n## 5. Acknowledgements\n\nThis Code of Conduct is adapted from the [Contributor Covenant](https://www.contributor-covenant.org/version/2/0/code_of_conduct.html).\n\n## 6. Contact\n\nIf you have any questions or concerns, please contact the project maintainers."
  },
  {
    "path": "Dockerfile",
    "content": "\nFROM python:3.11-slim\n\n# Set build argument\nARG API_ENABLED\n\n# Set environment variable based on the build argument\nENV API_ENABLED=${API_ENABLED} \\\n    PIP_NO_CACHE_DIR=true\nENV PATH=\"${PATH}:/root/.poetry/bin\"\nRUN pip install poetry\n\nWORKDIR /app\nCOPY pyproject.toml poetry.lock /app/\n\n# Install the dependencies\nRUN poetry config virtualenvs.create false && \\\n    poetry install --no-root --no-dev\n\nRUN apt-get update -q && \\\n    apt-get install curl zip jq netcat-traditional -y -q\nRUN curl \"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip\" -o \"awscliv2.zip\" && \\\n    unzip -qq awscliv2.zip && ./aws/install && \\\n    apt-get clean && \\\n    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\n\n#RUN playwright install\n#RUN playwright install-deps\n\nWORKDIR /app\nCOPY . /app\nCOPY entrypoint.sh /app/entrypoint.sh\nRUN chmod +x /app/entrypoint.sh\n\nENTRYPOINT [\"/app/entrypoint.sh\"]\n"
  },
  {
    "path": "LICENSE.md",
    "content": "MIT License\n\nCopyright (c) 2023 topoteretes\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
  },
  {
    "path": "README.md",
    "content": "# PromethAI\n\n\n<p align=\"center\">\n  <a href=\"https://prometh.ai//#gh-light-mode-only\">\n    <img src=\"assets/topoteretes_logo.png\" width=\"10%\" alt=\"promethAI logo\" />\n  </a>\n\n  \n</p>\n\n<p align=\"center\"><i>Open-source framework that gives you AI Agents that help you navigate decision-making, get personalized goals and  execute them </i></p>\n\n<p align=\"center\">\n<a href=\"https://github.com/topoteretes/PromethAI-Backend/fork\" target=\"blank\">\n<img src=\"https://img.shields.io/github/forks/topoteretes/PromethAI-Backend?style=for-the-badge\" alt=\"promethAI forks\"/>\n</a>\n\n<a href=\"https://github.com/topoteretes/PromethAI-Backend/stargazers\" target=\"blank\">\n<img src=\"https://img.shields.io/github/stars/topoteretes/PromethAI-Backend?style=for-the-badge\" alt=\"promethAI stars\"/>\n</a>\n<a href=\"https://github.com/topoteretes/PromethAI-Backend/pulls\" target=\"blank\">\n<img src=\"https://img.shields.io/github/issues-pr/topoteretes/PromethAI-Backend?style=for-the-badge\" alt=\"promethAI pull-requests\"/>\n</a>\n<a href='https://github.com/topoteretes/PromethAI-Backend/releases'>\n<img src='https://img.shields.io/github/release/topoteretes/PromethAI-Backend?&label=Latest&style=for-the-badge'>\n</a>\n\n</p>\n\n[//]: # (<p align=\"center\"><b>Follow PromethAI </b></p>)\n\n[//]: # (<p align=\"center\">)\n\n[//]: # (<a href=\"https://twitter.com/_promethAI\" target=\"blank\">)\n\n[//]: # (<img src=\"https://img.shields.io/twitter/follow/_promethAI?label=Follow: _promethAI&style=social\" alt=\"Follow _promethAI\"/>)\n\n[//]: # (</a>)\n\n[//]: # (<p align=\"center\">)\n\n[//]: # (<a href=\"https://prometh.ai\" target=\"_blank\"><img src=\"https://img.shields.io/twitter/url?label=promethAI Website&logo=website&style=social&url=https://github.com/topoteretes/PromethAI-Backend-Backend\"/></a>)\n\n[//]: # (<p align=\"center\">)\n\n[//]: # (<a href=\"https://www.youtube.com/@_promethAI\" target=\"_blank\"><img src=\"https://img.shields.io/twitter/url?label=Youtube&logo=youtube&style=social&url=https://github.com/topoteretes/PromethAI-Backend-Backend\"/></a>)\n\n[//]: # (</p>)\n\n\n<p align=\"center\"><b>Share promethAI Repository</b></p>\n\n<p align=\"center\">\n\n<a href=\"https://twitter.com/intent/tweet?text=Check%20this%20GitHub%20repository%20out.%20promethAI%20-%20Let%27s%20you%20easily%20build,%20manage%20and%20run%20useful%20autonomous%20AI%20agents.&url=https://github.com/topoteretes/PromethAI-Backend-Backend&hashtags=promethAI,AGI,Autonomics,future\" target=\"blank\">\n<img src=\"https://img.shields.io/twitter/follow/_promethAI?label=Share Repo on Twitter&style=social\" alt=\"Follow _promethAI\"/></a> \n<a href=\"https://t.me/share/url?text=Check%20this%20GitHub%20repository%20out.%20promethAI%20-%20Let%27s%20you%20easily%20build,%20manage%20and%20run%20useful%20autonomous%20AI%20agents.&url=https://github.com/topoteretes/PromethAI-Backend\" target=\"_blank\"><img src=\"https://img.shields.io/twitter/url?label=Telegram&logo=Telegram&style=social&url=https://github.com/topoteretes/PromethAI-Backend\" alt=\"Share on Telegram\"/></a>\n<a href=\"https://api.whatsapp.com/send?text=Check%20this%20GitHub%20repository%20out.%20promethAI%20-%20Let's%20you%20easily%20build,%20manage%20and%20run%20useful%20autonomous%20AI%20agents.%20https://github.com/topoteretes/PromethAI-Backend\"><img src=\"https://img.shields.io/twitter/url?label=whatsapp&logo=whatsapp&style=social&url=https://github.com/topoteretes/PromethAI-Backend\" /></a> <a href=\"https://www.reddit.com/submit?url=https://github.com/topoteretes/PromethAI-Backend&title=Check%20this%20GitHub%20repository%20out.%20promethAI%20-%20Let's%20you%20easily%20build,%20manage%20and%20run%20useful%20autonomous%20AI%20agents.\n\" target=\"blank\">\n<img src=\"https://img.shields.io/twitter/url?label=Reddit&logo=Reddit&style=social&url=https://github.com/topoteretes/PromethAI-Backend\" alt=\"Share on Reddit\"/>\n</a> <a href=\"mailto:?subject=Check%20this%20GitHub%20repository%20out.&body=promethAI%20-%20Let%27s%20you%20easily%20build,%20manage%20and%20run%20useful%20autonomous%20AI%20agents.%3A%0Ahttps://github.com/topoteretes/PromethAI-Backend\" target=\"_blank\"><img src=\"https://img.shields.io/twitter/url?label=Gmail&logo=Gmail&style=social&url=https://github.com/topoteretes/PromethAI-Backend\"/></a> <a href=\"https://www.buymeacoffee.com/promethAI\" target=\"_blank\"><img src=\"https://cdn.buymeacoffee.com/buttons/default-orange.png\" alt=\"Buy Me A Coffee\" height=\"23\" width=\"100\" style=\"border-radius:1px\"></a>\n\n</p>\n\n<hr>\n\n## We took all the work we did with PromethAI into our new product, cognee -> check it out [here](https://github.com/topoteretes/cognee)\n\n## What is it\n\nPromethAI is a Python-based AGI project that recommends  choices based on a user's goals and preferences and can modify its recommendations based on user feedback.\n\nOur focus is currently on food, but the system is extendible to any area.\n\n## 💡 Features\n\n- Optimized for Autonomous Agents\n- Personalized for each user\n- Introduces decision trees to help user navigate and decide on a solution\n- Runs asynchronusly\n- For App builds, check out this repo [promethAI-GUI](https://github.com/topoteretes/PromethAI-Mobile)\n- Supports automating tasks and executing decisions\n- Multiple Vector DBs supported trough Langchain \n- Low latency\n- Easy to use\n- Easy to deploy\n\n\n## 💻 Demo\n\n\n<p align=\"center\">\n  <a href=\"https://prometh.ai\">\n    <img  src=\"https://promethai-public-assets.s3.eu-west-1.amazonaws.com/product_demo-min.gif\"  width=\"25%\" height=\"50%\"/>\n  </a>\n</p>\n\n\n\n\n## 🛣 Architecture\n<p align=\"center\">\n  <img src=\"assets/PromethAI_infra.png\" alt=\"PromethAI Architecture\" width=\"50%\" height=\"50%\">\n</p>\n\n\n## 🛣 Roadmap\n<p align=\"center\">\n  <img src=\"assets/roadmap.png\" alt=\"Topoteretes Roadmap\" width=\"50%\" height=\"50%\">\n</p>\n\n\n## ⚙️ Setting up\n\n1. Download the repo using `git clone https://github.com/topoteretes/PromethAI-Backend-Backend.git` in your terminal or directly from github page in zip format.\n2. Navigate to the directory using `cd PromethAI-Backend` and create a copy of `.env.template` and name it `.env`.\n3. Enter your unique OpenAI API Key, Google key, Custom search engine ID without any quotes or spaces in `.env` file. Follow the links below to get your keys:\n\n| Keys                        | Accessing the keys                                                                                                                                                                                                |\n|-----------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n| **OpenAI API Key**          | Sign up and create an API key at [OpenAI Developer](https://beta.openai.com/signup/)                                                                                                                              |\n| **Pinecone API Key**        | Sign up and create an API key at [Pinecone.io](https://www.pinecone.io/)                                                                                                                                          |\n| **Google API key**          | Create a project in the [Google Cloud Console](https://console.cloud.google.com/) and enable the API you need (for example: Google Custom Search JSON API). Then, create an API key in the \"Credentials\" section. |\n| **Custom search engine ID** | Visit [Google Programmable Search Engine](https://programmablesearchengine.google.com/about/) to create a custom search engine for your application and obtain the search engine ID.                              |\n\n4. Ensure that Docker and Docker Compose are installed in your system, if not, Install it from [here](https://docs.docker.com/get-docker/). \n5. Once you have Docker Desktop running, run command : `docker-compose up promethai --build` in promethai directory. Open your browser and go to `localhost:3000` to see promethAI running.\n\n\n## Resources\nPapers like [\"Generative Agents: Interactive Simulacra of Human Behavior\"](https://arxiv.org/abs/2304.03442)\n\n\n## Quick start \nMake sure to add your credentions in the .env file.Launch the app with:\n\n```docker-compose build promethai && docker-compose up promethai```\n\n\n\n## How it Works\nHere is what happens everytime the AI is queried by the user:\n1. AI vectorizes the query and stores it in a Pinecone Vector Database\n2. AI looks inside its memory and finds memories and past queries that are relevant to the current query\n3. AI thinks about what action to take\n4. AI stores the thought from Step 3\n5. Based on the thought from Step 3 and relevant memories from Step 2, AI generates an output\n6. AI stores the current query and its answer in its Pinecone vector database memory\n\n## How to use\n```\ndocker-compose build  promethai\n```\n6. Access the API by doing CURL requests, example: \n```\ncurl -X POST \"http://0.0.0.0:8000/data-request\" -H \"Content-Type: application/json\" --data-raw \n\n```\n## Example of available endpoint\n\nThe available endpoint:\n```\nPOST request to '/recipe-request' endpoint that takes a JSON payload containing 'user_id', 'session_id', 'factors' keys, and returns a JSON response with a 'response' key.\n\n```\nAll endpoints receive a payload in JSON format and return a response in JSON format.\n\nExample of curl requests\n```\ncurl --location --request POST 'http://0.0.0.0:8000/recipe-request' \\\n--header 'Content-Type: application/json' \\\n--data-raw '{\n  \"payload\": {\n    \"user_id\": \"659\",\n    \"session_id\": \"459\",\n    \"model_speed\":\"slow\",\n    \"prompt\":\"I would like a healthy chicken meal over 125$\"\n    \n  }\n}'\n```\n\n\n\n# 🔰 Notice\n\nPromethAI is a work in progress, delivered to you without any guarantees, whether explicit or implied. By choosing to use this application, you consent to take on any associated risks, including data loss, system failure, or any other complications that may arise.\n\nThe creators and contributors of PromethAI disclaim any responsibility or liability for any potential losses, damages, or any other adverse effects resulting from your use of this software. The onus is solely on you for any decisions or actions you take based on the information given by PromethAI.\n\nPlease be aware that usage of the GPT-4 language model could incur significant costs due to its token consumption. By using this software, you acknowledge and agree to monitor your own token usage and manage the associated costs. We strongly suggest routinely checking your OpenAI API usage and implementing necessary limits or alerts to avoid unexpected fees.\n\nGiven its experimental nature, PromethAI may generate content or perform actions that do not align with real-world business norms or legal obligations. It falls on you to ensure that any actions or decisions based on this software’s output adhere to all relevant laws, regulations, and ethical standards. The creators and contributors of this project will not be held accountable for any fallout from using this software.\n\nBy utilizing PromethAI, you agree to protect, defend, and absolve the creators, contributors, and any affiliated parties from any claims, damages, losses, liabilities, costs, and expenses (including reasonable attorneys' fees) that arise from your use of this software or your violation of these terms.\n\n# 📝 License\n\nMIT License\n\n\n# Credits: \nTeenage AGI -> https://github.com/seanpixel/Teenage-AGI\nBaby AGI -> https://github.com/yoheinakajima/babyagi\n\n\n\n"
  },
  {
    "path": "act.env.example",
    "content": "AWS_ACCESS_KEY_ID=\nAWS_SECRET_ACCESS_KEY=\nAWS_DEFAULT_REGION=eu-west-1\n"
  },
  {
    "path": "agent.py",
    "content": "import openai\nimport os\nimport pinecone\n\nfrom dotenv import load_dotenv\nimport nltk\nfrom langchain.text_splitter import NLTKTextSplitter\nfrom typing import Optional\n\n# Download NLTK for Reading\nnltk.download(\"punkt\")\nimport subprocess\nimport datetime\n\n# Initialize Text Splitter\ntext_splitter = NLTKTextSplitter(chunk_size=2500)\n# Load default environment variables (.env)\nload_dotenv()\n\nOPENAI_MODEL = os.getenv(\"OPENAI_MODEL\") or \"gpt-3.5-turbo\"\n\nOPENAI_TEMPERATURE = float(os.getenv(\"OPENAI_TEMPERATURE\", 0.0))\n\nPINECONE_API_KEY = os.getenv(\"PINECONE_API_KEY\")\nOPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\")\nPINECONE_API_ENV = os.getenv(\"PINECONE_API_ENV\")\n\n\n# Top matches length\nk_n = 3\n\n# initialize pinecone\npinecone.init(api_key=PINECONE_API_KEY, environment=PINECONE_API_ENV)\n\n# initialize openAI\nopenai.api_key = OPENAI_API_KEY  # you can just copy and paste your key here if you want\n\n\ndef get_ada_embedding(text):\n    text = text.replace(\"\\n\", \" \")\n    return openai.Embedding.create(input=[text], model=\"text-embedding-ada-002\")[\n        \"data\"\n    ][0][\"embedding\"]\n"
  },
  {
    "path": "api.py",
    "content": "from llm_chains.chains import Agent\nfrom fastapi import FastAPI\nfrom fastapi.responses import JSONResponse\nfrom pydantic import BaseModel\nfrom typing import Dict, Any\nimport re\nimport json\nimport logging\nimport os\nimport uvicorn\nfrom fastapi import Request\nimport yaml\nfrom fastapi import HTTPException\nCANNED_RESPONSES = False\n\n\n# Set up logging\nlogging.basicConfig(\n    level=logging.INFO,  # Set the logging level (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL)\n    format=\"%(asctime)s [%(levelname)s] %(message)s\",  # Set the log message format\n)\n\nlogger = logging.getLogger(__name__)\nfrom dotenv import load_dotenv\n\n\nload_dotenv()\n\n\napp = FastAPI(debug=True)\nfrom auth.cognito.JWTBearer import JWTBearer\nfrom auth.auth import jwks\nauth = JWTBearer(jwks)\n\nfrom fastapi import Depends\n\n\nclass Payload(BaseModel):\n    payload: Dict[str, Any]\nclass ImageResponse(BaseModel):\n    success: bool\n    message: str\n\n\n\ndef str_to_bool(s):\n    \"\"\"Converts a string to boolean. If the string is not recognizable, returns the original value.\"\"\"\n    if s.lower() == \"true\":\n        return True\n    elif s.lower() == \"false\":\n        return False\n    return s\n\n@app.get(\"/\", )\nasync def root():\n    \"\"\"\n    Root endpoint that returns a welcome message.\n    \"\"\"\n    return {\"message\": \"Hello, World, I am alive!\"}\n\n@app.get(\"/health\",dependencies=[Depends(auth)])\ndef health_check():\n    \"\"\"\n    Health check endpoint that returns the server status.\n    \"\"\"\n    return {\"status\": \"OK\"}\n\n\n\n# @app.post(\"/testbot\", response_model=Dict[str, Any])\n# async def test(request_data: Payload) -> Dict[str, Any]:\n#     \"\"\"\n#     Endpoint to clear the cache.\n#\n#     Parameters:\n#     request_data (Payload): The request data containing the user and session IDs.\n#\n#     Returns:\n#     dict: A dictionary with a message indicating the cache was cleared.\n#     \"\"\"\n#     json_payload = request_data.payload\n#\n#     try:\n#         # Instantiate AppAgent and call manage_resources\n#         app_agent = AppAgent(user_id=json_payload[\"user_id\"])\n#         app_agent.manage_resources(\"add\", \"web_page\", \"https://nav.al/agi\")\n#         return JSONResponse(content={\"response\": \"Test\"}, status_code=200)\n#     except Exception as e:\n#         raise HTTPException(status_code=500, detail=str(e))\n\n\n@app.post(\"/clear-cache\", response_model=dict,dependencies=[Depends(auth)])\nasync def clear_cache(request_data: Payload) -> dict:\n    \"\"\"\n    Endpoint to clear the cache.\n\n    Parameters:\n    request_data (Payload): The request data containing the user and session IDs.\n\n    Returns:\n    dict: A dictionary with a message indicating the cache was cleared.\n    \"\"\"\n    json_payload = request_data.payload\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n    try:\n        agent.clear_cache()\n        return JSONResponse(content={\"response\": \"Cache cleared\"}, status_code=200)\n    except Exception as e:\n        raise HTTPException(status_code=500, detail=str(e))\n\n@app.post(\"/correct-prompt-grammar\", response_model=dict,dependencies=[Depends(auth)])\nasync def prompt_to_correct_grammar(request_data: Payload) -> dict:\n    json_payload = request_data.payload\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n    logging.info(\"Correcting grammar %s\", json_payload[\"prompt_source\"])\n\n    output = agent.prompt_correction(json_payload[\"prompt_source\"], model_speed= json_payload[\"model_speed\"])\n    return JSONResponse(content={\"response\": {\"result\": json.loads(output)}})\n\n\n# @app.post(\"/action-add-zapier-calendar-action\", response_model=dict,dependencies=[Depends(auth)])\n# async def action_add_zapier_calendar_action(\n#     request: Request, request_data: Payload\n# ) -> dict:\n#     json_payload = request_data.payload\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     # Extract the bearer token from the header\n#     auth_header = request.headers.get(\"Authorization\")\n#     if auth_header:\n#         bearer_token = auth_header.replace(\"Bearer \", \"\")\n#     else:\n#         bearer_token = None\n#     outcome = agent.add_zapier_calendar_action(\n#         prompt_base=json_payload[\"prompt_base\"],\n#         token=bearer_token,\n#         model_speed=json_payload[\"model_speed\"],\n#     )\n#     return JSONResponse(content={\"response\": outcome})\n\n\n@app.post(\"/prompt-to-choose-meal-tree\", response_model=dict,dependencies=[Depends(auth)])\nasync def prompt_to_choose_meal_tree(request_data: Payload) -> dict:\n    json_payload = request_data.payload\n    agent = Agent()\n\n\n    user_defaults = str_to_bool(json_payload.get(\"user_defaults\", \"True\"))\n    assistant_category = json_payload.get(\"assistant_category\", \"food\")\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n    output = agent.prompt_to_choose_tree(\n        json_payload[\"prompt\"],\n        model_speed=json_payload[\"model_speed\"],\n        assistant_category=assistant_category,\n        load_defaults = user_defaults\n    )\n    return JSONResponse(content=json.loads(output))\n\n\n# def create_endpoint_with_resources(category: str, solution_type: str, prompt: str, json_example: str, *args, **kwargs):\n#     class Payload(BaseModel):\n#         payload: Dict[str, Any]\n#\n#     @app.post(f\"/chatbot/{category}\", response_model=dict,dependencies=[Depends(auth)])\n#     async def prompt_to_choose_tree(request_data: Payload) -> dict:\n#         json_payload = request_data.payload\n#         from bots.bot_extension import AppAgent\n#         agent =  AppAgent()\n#         agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#         output = agent.query(\n#             json_payload[\"prompt\"]\n#         )\n#         logging.info(\"HERE IS THE CHAIN RESULT %s\", output)\n#         return JSONResponse(content={\"response\": output})\n\n\n\n#\ndef create_endpoint(category: str, solution_type: str, prompt: str, json_example: str, *args, **kwargs):\n    class Payload(BaseModel):\n        payload: Dict[str, Any]\n\n\n\n    @app.post(f\"/{category}/prompt-to-decompose-categories\", response_model=dict)\n    async def prompt_to_decompose_categories(request_data: Payload) -> dict:\n        json_payload = request_data.payload\n        agent = Agent()\n        agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n        output = await agent.prompt_decompose_to_tree_categories(\n            json_payload[\"prompt_struct\"],\n            assistant_category=category,\n            model_speed=json_payload[\"model_speed\"],\n        )\n        return JSONResponse(content={\"response\": output})\n\n    @app.post(f\"/{category}/update-agent-summary/{solution_type}\", response_model=dict,dependencies=[Depends(auth)])\n    async def update_agent_summary(request_data: Payload) -> dict:\n        json_payload = request_data.payload\n        agent = Agent()\n        agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n        output = await agent.update_agent_summary(\n            model_speed=json_payload[\"model_speed\"]\n        )\n\n        return {\"response\": output}\n\n    @app.post(f\"/{category}/prompt-to-update-tree\", response_model=dict,dependencies=[Depends(auth)])\n    async def prompt_to_update_tree(request_data: Payload) -> dict:\n        json_payload = request_data.payload\n        agent = Agent()\n        agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n        output = agent.prompt_to_update_meal_tree(\n            json_payload[\"category\"],\n            json_payload[\"from\"],\n            json_payload[\"to\"],\n            model_speed=json_payload[\"model_speed\"],\n        )\n\n        print(\"HERE IS THE OUTPUT\", output)\n        return JSONResponse(content={\"response\": output})\n\n    @app.post(f\"/{category}/fetch-user-summary/{solution_type}\", response_model=dict,dependencies=[Depends(auth)])\n    async def fetch_user_summary(request_data: Payload) -> dict:\n        json_payload = request_data.payload\n        agent = Agent()\n        agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n        output = agent.fetch_user_summary(model_speed=json_payload[\"model_speed\"])\n\n        return {\"response\": output}\n\n    @app.post(f\"/{category}/request/{solution_type}\", response_model=dict,dependencies=[Depends(auth)])\n    async def solution_request(request_data: Payload) -> dict:\n        json_payload = request_data.payload\n        agent = Agent()\n        agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n        # method_to_call = getattr(agent, f\"{solution_type}_generation\")\n        output = await agent.solution_generation(json_payload[\"prompt\"], prompt_template=prompt, json_example=json_example, model_speed=\"slow\")\n        output = output.replace(\"'\", '\"')\n        return JSONResponse(content={\"response\": json.loads(output)})\n\n\n# Load categories from a yaml file\nwith open('assistant_templates.yaml', 'r') as file:\n    data = yaml.safe_load(file)\n\n\n# Create an endpoint for each category and solution type\n\nfor role in ['assistant', 'chatbot']:\n    # If the role is 'assistant'\n    if role == 'assistant':\n        # Iterate through the categories and solution_types\n        for category in data[role]['categories']:\n            for solution_type in category['solution_types']:\n                create_endpoint(category['name'], solution_type['name'], solution_type['prompt'], json.loads(solution_type['json_example']))\n#     # If the role is 'chatbot'\n#     elif role == 'chatbot':\n#         # Iterate through the categories and resources\n\n#         for category in data[role]['categories']:\n#             create_endpoint_with_resources(category['name'], solution_type=\"\", prompt=\"\", json_example=\"\")\n\n\n#         # for category in data[role]['categories']:\n#         #         create_endpoint_with_resources(category['name'])\n@app.post(\"/prompt-to-decompose-meal-tree-categories\", response_model=dict,dependencies=[Depends(auth)])\nasync def prompt_to_decompose_meal_tree_categories(request_data: Payload) -> dict:\n    json_payload = request_data.payload\n    agent = Agent()\n    import time\n\n    # Wait for 0.5 seconds\n    time.sleep(1.1)\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n\n\n    user_defaults = str_to_bool(json_payload.get(\"user_defaults\", \"False\"))\n    assistant_category = json_payload.get(\"assistant_category\", \"food\")\n    output = await agent.prompt_decompose_to_tree_categories(\n        json_payload[\"prompt_struct\"],\n        assistant_category=assistant_category,\n        model_speed=json_payload[\"model_speed\"],\n        load_defaults=user_defaults\n    )\n    logging.info(\"Prompt to decompose meal tree categories %s\", str(output))\n    if user_defaults:\n        return  output\n    else:\n        return JSONResponse(content={\"response\": output})\n\n\n@app.post(\"/correct-prompt-grammar\", response_model=dict,dependencies=[Depends(auth)])\nasync def prompt_to_correct_grammar(request_data: Payload) -> dict:\n    json_payload = request_data.payload\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n    logging.info(\"Correcting grammar %s\", json_payload[\"prompt_source\"])\n\n    output = agent.prompt_correction(json_payload[\"prompt_source\"], model_speed= json_payload[\"model_speed\"])\n    return JSONResponse(content={\"response\": {\"result\": json.loads(output)}})\n\n\n\n@app.post(\"/fetch-user-summary\", response_model=dict,dependencies=[Depends(auth)])\nasync def fetch_user_summary(request_data: Payload) -> dict:\n    json_payload = request_data.payload\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n    output = agent.fetch_user_summary(model_speed=json_payload[\"model_speed\"])\n    print(\"HERE IS THE OUTPUT\", output)\n    return JSONResponse(content={\"response\": output})\n\n\n@app.post(\"/recipe-request\", response_model=dict,dependencies=[Depends(auth)])\nasync def recipe_request(request_data: Payload) -> dict:\n    if CANNED_RESPONSES:\n        with open(\"fixtures/recipe_response.json\", \"r\") as f:\n            json_data = json.load(f)\n            stripped_string_dict = {\"response\": json_data}\n            return JSONResponse(content=stripped_string_dict)\n\n    json_payload = request_data.payload\n    # factors_dict = {factor['name']: factor['amount'] for factor in json_payload['factors']}\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n\n    output = await agent.solution_generation(json_payload[\"prompt\"], model_speed=\"slow\", prompt_template=None, json_example=None)\n\n    return JSONResponse(content={\"response\": output})\n\n\n@app.post(\"/food/solution-name-request\", response_model=dict,dependencies=[Depends(auth)])\nasync def solution_name_request(request_data: Payload) -> dict:\n\n    json_payload = request_data.payload\n    # factors_dict = {factor['name']: factor['amount'] for factor in json_payload['factors']}\n    agent = Agent()\n    agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n\n    output = await agent.solution_name_generation(json_payload[\"prompt\"], model_speed=\"slow\", prompt_template=None, json_example=None)\n\n    return JSONResponse(content={\"response\": output})\n\n\n# @app.post(\"/restaurant-request\", response_model=dict)\n# async def restaurant_request(request_data: Payload) -> dict:\n#     json_payload = request_data.payload\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     output = agent.restaurant_generation(json_payload[\"prompt\"], model_speed=\"slow\")\n#     return JSONResponse(content={\"response\": {\"restaurants\": output}})\n\n\n# @app.post(\"/delivery-request\", response_model=dict)\n# async def delivery_request(request_data: Payload) -> dict:\n#     json_payload = request_data.payload\n#     # factors_dict = {factor['name']: factor['amount'] for factor in json_payload['factors']}\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     output = await agent.delivery_generation( json_payload[\"prompt\"], zipcode=json_payload[\"zipcode\"], model_speed=\"slow\")\n#     print(\"HERE IS THE OUTPUT\", output)\n#     return JSONResponse(content={\"response\": {\"url\": output}})\n\n\n\n\n\n\ndef start_api_server(host: str = \"0.0.0.0\", port: int = 8000):\n    \"\"\"\n    Start the API server using uvicorn.\n\n    Parameters:\n    host (str): The host for the server.\n    port (int): The port for the server.\n    \"\"\"\n    try:\n        logger.info(f\"Starting server at {host}:{port}\")\n        uvicorn.run(app, host=host, port=port)\n    except Exception as e:\n        logger.exception(f\"Failed to start server: {e}\")\n        # Here you could add any cleanup code or error recovery code.\n\n\nif __name__ == \"__main__\":\n    start_api_server()\n"
  },
  {
    "path": "assistant_templates.yaml",
    "content": "assistant:\n  categories:\n    - name: food\n      solution_types:\n        - name: recipe\n          prompt: |-\n            Create a food recipe based on the following prompt: '{{prompt}}'. Instructions and ingredients should have medium detail.\n            Answer a condensed valid JSON in this format: {{ json_example}}  Do not explain or write anything else.\n          json_example: '{\"recipes\":[{\"title\":\"value\",\"rating\":\"value\",\"prep_time\":\"value\",\"cook_time\":\"value\",\"description\":\"value\",\"ingredients\":[\"value\"],\"instructions\":[\"value\"]}]}'\n        - name: restaurant\n          prompt: |-\n            Create a detailed weekly workout routine based on the following '{{prompt}}': I want to gain muscle mass in the next six month . Instructions  should have medium detail.\n            Answer a condensed valid JSON in this format: {{ json_example}}  Do not explain or write anything else.\n          json_example: '{\"plans\":[{\"day\":\"Monday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Tuesday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Wednesday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Thursday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Friday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Saturday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Sunday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]}]}'\n    - name: fitness\n      solution_types:\n        - name: exercise\n          prompt: |-\n                Create a detailed weekly workout routine based on the following '{{prompt}}': I want to gain muscle mass in the next six month . Instructions  should have medium detail.\n                Answer a condensed valid JSON in this format: {{ json_example}}  Do not explain or write anything else.\n          json_example: '{\"plans\":[{\"day\":\"Monday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Tuesday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Wednesday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Thursday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Friday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Saturday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]} ,{\"day\":\"Sunday\",\"workouts\":[{\"title\":\"example workout\",\"instructions\":[\"example instruction\"]}]}]}'\nchatbot:\n  categories:\n    - name: nutrition_chatbot\n      resources:\n        - type: 'pdf_file'\n          url: 'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf'\n        - type: 'pdf_file'\n          url: 'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf'"
  },
  {
    "path": "auth/auth.py",
    "content": "import os\n\nimport requests\nfrom dotenv import load_dotenv\nfrom fastapi import Depends, HTTPException\nfrom starlette.status import HTTP_403_FORBIDDEN\n\nfrom auth.cognito.JWTBearer import JWKS, JWTBearer, JWTAuthorizationCredentials\n\nload_dotenv()  # Automatically load environment variables from a '.env' file.\n\n# jwks = JWKS.parse_obj(\n#     requests.get(\n#         f\"https://cognito-idp.{os.environ.get('eu-west-1:46372257029')}.amazonaws.com/\"\n#         f\"{os.environ.get('eu-west-1_3VUqKzMgj')}/.well-known/jwks.json\"\n#     ).json()\n# )\n# Construct the Cognito User Pool URL using the correct syntax\nregion = \"eu-west-1\"\nuser_pool_id = \"eu-west-1_viUyNCqKp\"\ncognito_url = f\"https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json\"\n\n# Fetch the JWKS using the updated URL\njwks = JWKS.parse_obj(requests.get(cognito_url).json())\n\nauth = JWTBearer(jwks)\n\n\nasync def get_current_user(\n    credentials: JWTAuthorizationCredentials = Depends(auth)\n) -> str:\n    try:\n        return credentials.claims[\"username\"]\n    except KeyError:\n        HTTPException(status_code=HTTP_403_FORBIDDEN, detail=\"Username missing\")\n"
  },
  {
    "path": "auth/auth_utils.py",
    "content": "\nfrom cognito.JWTBearer import JWKS, JWTBearer, JWTAuthorizationCredentials\n\nimport requests\n\nregion = \"eu-west-1\"\nuser_pool_id = \"\" #needed\ncognito_url = f\"https://cognito-idp.{region}.amazonaws.com/{user_pool_id}/.well-known/jwks.json\"\n\n# Fetch the JWKS using the updated URL\njwks = JWKS.parse_obj(requests.get(cognito_url).json())\nprint(jwks)\n\nauth = JWTBearer(jwks)\n\n\nimport requests\n\n# Set the Cognito authentication endpoint URL\n\nauth = JWTBearer(jwks)\n\n# Set the user credentials\n\nusername = \"\" #needed\npassword = \"\" #needed\n\n# Create the authentication payload\npayload = {\n    \"username\": username,\n    \"password\": password\n}\n\n# Set the Cognito authentication endpoint URL\n# Set the Cognito token endpoint URL\ntoken_endpoint = f\"https://your-cognito-domain.auth.{region}.amazoncognito.com/oauth2/token\"\n\n# Set the client credentials\nclient_id = \"\" #needed\nclient_secret = \"\"\n\nimport boto3\ndef authenticate_and_get_token(username: str, password: str,\n                               user_pool_id: str, app_client_id: str) -> None:\n    client = boto3.client('cognito-idp')\n\n    resp = client.admin_initiate_auth(\n        UserPoolId=user_pool_id,\n        ClientId=app_client_id,\n        AuthFlow='ADMIN_NO_SRP_AUTH',\n        AuthParameters={\n            \"USERNAME\": username,\n            \"PASSWORD\": password\n        }\n    )\n\n    print(\"Log in success\")\n    print(\"Access token:\", resp['AuthenticationResult']['AccessToken'])\n    print(\"ID token:\", resp['AuthenticationResult']['IdToken'])\n\n\nauthenticate_and_get_token(username, password, user_pool_id, client_id)"
  },
  {
    "path": "auth/cognito/JWTBearer.py",
    "content": "from typing import Dict, Optional, List\n\nfrom fastapi import HTTPException\nfrom fastapi.security import HTTPBearer, HTTPAuthorizationCredentials\nfrom jose import jwt, jwk, JWTError\nfrom jose.utils import base64url_decode\nfrom pydantic import BaseModel\nfrom starlette.requests import Request\nfrom starlette.status import HTTP_403_FORBIDDEN\n\nJWK = Dict[str, str]\n\n\nclass JWKS(BaseModel):\n    keys: List[JWK]\n\n\nclass JWTAuthorizationCredentials(BaseModel):\n    jwt_token: str\n    header: Dict[str, str]\n    claims: Dict[str, str]\n    signature: str\n    message: str\n\n\nclass JWTBearer(HTTPBearer):\n    def __init__(self, jwks: JWKS, auto_error: bool = True):\n        super().__init__(auto_error=auto_error)\n\n        self.kid_to_jwk = {jwk[\"kid\"]: jwk for jwk in jwks.keys}\n\n    def verify_jwk_token(self, jwt_credentials: JWTAuthorizationCredentials) -> bool:\n        try:\n            public_key = self.kid_to_jwk[jwt_credentials.header[\"kid\"]]\n        except KeyError:\n            raise HTTPException(\n                status_code=HTTP_403_FORBIDDEN, detail=\"JWK public key not found\"\n            )\n\n        key = jwk.construct(public_key)\n        decoded_signature = base64url_decode(jwt_credentials.signature.encode())\n\n        return key.verify(jwt_credentials.message.encode(), decoded_signature)\n\n    async def __call__(self, request: Request) -> Optional[JWTAuthorizationCredentials]:\n        credentials: HTTPAuthorizationCredentials = await super().__call__(request)\n\n        if credentials:\n            if not credentials.scheme == \"Bearer\":\n                raise HTTPException(\n                    status_code=HTTP_403_FORBIDDEN, detail=\"Wrong authentication method\"\n                )\n\n            jwt_token = credentials.credentials\n\n            message, signature = jwt_token.rsplit(\".\", 1)\n\n            try:\n                jwt_credentials = JWTAuthorizationCredentials(\n                    jwt_token=jwt_token,\n                    header=jwt.get_unverified_header(jwt_token),\n                    claims=jwt.get_unverified_claims(jwt_token),\n                    signature=signature,\n                    message=message,\n                )\n            except JWTError:\n                raise HTTPException(status_code=HTTP_403_FORBIDDEN, detail=\"JWK invalid\")\n\n            if not self.verify_jwk_token(jwt_credentials):\n                raise HTTPException(status_code=HTTP_403_FORBIDDEN, detail=\"JWK invalid\")\n\n            return jwt_credentials"
  },
  {
    "path": "bin/dockerize",
    "content": "set -euo pipefail\n\nAWS_REGION=${region:-eu-west-1}\nAWS_DEPLOYMENT_ACCOUNT=${account:-463722570299}\nAWS_REPOSITORY=${repo:-\"${AWS_DEPLOYMENT_ACCOUNT}.dkr.ecr.${AWS_REGION}.amazonaws.com\"}\n\nSTAGE=${stage:-\"dev\"}\nSHA_SHORT=\"$(git rev-parse --short HEAD)\"\nCUR_DATE=\"$(date +%Y%m%d%H%M%S)\"\nVERSION=\"$STAGE-$CUR_DATE-$SHA_SHORT\"\nIMAGE_NAME=${image_name:-promethai-${STAGE}-promethai-backend}\n\nREPO_NAME=\"${AWS_REPOSITORY}/${IMAGE_NAME}\"\nFULL_IMAGE_NAME=\"${REPO_NAME}:${VERSION}\"\nAPP_DIR=${app_dir:-\".\"}\n\nPUBLISH=${publish:-false}\n\necho \"Building docker image ${FULL_IMAGE_NAME} located in dir ${app_dir}\"\n\npushd \"${APP_DIR}\" &&\n  docker buildx build --platform linux/amd64 \\\n    --build-arg STAGE=${STAGE} \\\n    -t \"${FULL_IMAGE_NAME}\" . &&\n  echo \"${VERSION}\" >/tmp/.DOCKER_IMAGE_VERSION &&\n  echo \"Successfully built docker image ${FULL_IMAGE_NAME}\"\n\nif [ \"${PUBLISH}\" = true ]; then\n  echo \"Pushing docker image ${FULL_IMAGE_NAME} to ECR repository to AWS account ${AWS_DEPLOYMENT_ACCOUNT}\"\n  if [ \"${PUBLISH}\" = true ]; then\n    echo \"logging in\"\n    aws ecr get-login-password --region \"${AWS_REGION}\" | docker login --username AWS --password-stdin \"${AWS_REPOSITORY}\"\n  fi\n  docker push \"${FULL_IMAGE_NAME}\" &&\n    echo \"Successfully pushed docker image ${FULL_IMAGE_NAME} to ECR repository\"\nfi"
  },
  {
    "path": "bots/__init__.py",
    "content": ""
  },
  {
    "path": "bots/bot_extension.py",
    "content": "import sys\nfrom typing import Optional\n\nsys.path.append('../llm_chains')\n# from embedchain import EmbedChain\n\nfrom llm_chains.chains import Agent\nfrom embedchain import App\n\nclass AppAgent(App, Agent):\n    def __init__(self, db=None, ef=None, table_name=None, user_id: Optional[str] = \"676\", session_id: Optional[str] = None):\n        Agent.__init__(self, table_name, user_id, session_id)\n        App.__init__(self, db)\n\n# naval_chat_bot= AppAgent()\n#\n# naval_chat_bot.add(\"web_page\", \"https://nav.al/agi\")\n#\n# # Embed Local Resources\n# naval_chat_bot.add_local(\"qna_pair\", (\n# \"Who is Naval Ravikant?\", \"Naval Ravikant is an Indian-American entrepreneur and investor.\"))\n#\n# naval_chat_bot.query(\n#     \"What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?\")\n\n"
  },
  {
    "path": "bots/bot_loading_util.py",
    "content": "from bot_extension import AppAgent\nimport  yaml\nimport sys\nsys.path.append('../')\nwith open('../assistant_templates.yaml', 'r') as file:\n    data = yaml.safe_load(file)\n\ndef _load_extension( object_type:str, object_value:str):\n    naval_chat_bot = AppAgent()\n    naval_chat_bot.add(object_type, object_value)\n\n# Directly access the 'chatbot' role\nchatbot_categories = data['chatbot']['categories']\n\n# Iterate through the categories and resources\nfor category in chatbot_categories:\n    for resource in category['resources']:\n        resource_type = resource['type']\n        resource_url = resource['url']\n        _load_extension(resource_type, resource_url)\n\n"
  },
  {
    "path": "bots/ff.yaml",
    "content": "Resources:\n  ChromaInstance:\n    Type: 'AWS::AccessAnalyzer::Analyzer'\n    Properties:\n      ImageId: !FindInMap\n        - Region2AMI\n        - !Ref 'AWS::Region'\n        - AMI\n      InstanceType: \"t3.small\"\n      UserData: !Base64\n        'Fn::Join':\n          - ''\n          - - |\n              Content-Type: multipart/mixed; boundary=\"//\"\n            - |\n              MIME-Version: 1.0\n            - |+\n\n            - |\n              --//\n            - |\n              Content-Type: text/cloud-config; charset=\"us-ascii\"\n            - |\n              MIME-Version: 1.0\n            - |\n              Content-Transfer-Encoding: 7bit\n            - |\n              Content-Disposition: attachment; filename=\"cloud-config.txt\"\n            - |+\n\n            - |+\n\n            - |\n              #cloud-config\n            - |\n              cloud_final_modules:\n            - |\n              - [scripts-user, always]\n            - |+\n\n            - |+\n\n            - |\n              --//\n            - |\n              Content-Type: text/x-shellscript; charset=\"us-ascii\"\n            - |\n              MIME-Version: 1.0\n            - |\n              Content-Transfer-Encoding: 7bit\n            - |\n              Content-Disposition: attachment; filename=\"userdata.txt\"\n            - |+\n\n            - |+\n\n            - |\n              #!/bin/bash\n            - |\n              amazon-linux-extras install docker\n            - |\n              usermod -a -G docker ec2-user\n            - >\n              curl -L\n              https://github.com/docker/compose/releases/latest/download/docker-compose-$(uname\n              -s)-$(uname -m) -o /usr/local/bin/docker-compose\n            - |\n              chmod +x /usr/local/bin/docker-compose\n            - |\n              ln -s /usr/local/bin/docker-compose /usr/bin/docker-compose\n            - |\n              systemctl enable docker\n            - |\n              systemctl start docker\n            - |+\n\n            - |\n              cat << EOF > /home/ec2-user/docker-compose.yml\n            - |\n              version: '3.9'\n            - |+\n\n            - |\n              networks:\n            - |2\n                net:\n            - |2\n                  driver: bridge\n            - |+\n\n            - |\n              services:\n            - |2\n                server:\n            - !Sub |2\n                  image: ghcr.io/chroma-core/chroma:${ChromaVersion}\n            - |2\n                  volumes:\n            - |2\n                    - index_data:/index_data\n            - |2\n                  environment:\n            - |2\n                    - CHROMA_DB_IMPL=clickhouse\n            - |2\n                    - CLICKHOUSE_HOST=clickhouse\n            - |2\n                    - CLICKHOUSE_PORT=8123\n            - |2\n                  ports:\n            - |2\n                    - 8000:8000\n            - |2\n                  depends_on:\n            - |2\n                    - clickhouse\n            - |2\n                  networks:\n            - |2\n                    - net\n            - |+\n\n            - |2\n                clickhouse:\n            - |2\n                  image: clickhouse/clickhouse-server:22.9-alpine\n            - |2\n                  environment:\n            - |2\n                    - ALLOW_EMPTY_PASSWORD=yes\n            - |2\n                    - CLICKHOUSE_TCP_PORT=9000\n            - |2\n                    - CLICKHOUSE_HTTP_PORT=8123\n            - |2\n                  ports:\n            - |2\n                    - '8123:8123'\n            - |2\n                    - '9000:9000'\n            - |2\n                  volumes:\n            - |2\n                    - clickhouse_data:/bitnami/clickhouse\n            - |2\n                    - backups:/backups\n            - |2\n                    - ./config/backup_disk.xml:/etc/clickhouse-server/config.d/backup_disk.xml\n            - |2\n                    - ./config/chroma_users.xml:/etc/clickhouse-server/users.d/chroma.xml\n            - |2\n                  networks:\n            - |2\n                    - net\n            - |+\n\n            - |\n              volumes:\n            - |2\n                clickhouse_data:\n            - |2\n                  driver: local\n            - |2\n                index_data:\n            - |2\n                  driver: local\n            - |2\n                backups:\n            - |2\n                  driver: local\n            - |+\n\n            - |\n              EOF\n            - |+\n\n            - |\n              mkdir /home/ec2-user/config\n            - |+\n\n            - |\n              cat << EOF > /home/ec2-user/config/backup_disk.xml\n            - |\n              <clickhouse>\n            - |2\n                  <storage_configuration>\n            - |2\n                      <disks>\n            - |2\n                          <backups>\n            - |2\n                              <type>local</type>\n            - |2\n                              <path>/etc/clickhouse-server/</path>\n            - |2\n                          </backups>\n            - |2\n                      </disks>\n            - |2\n                  </storage_configuration>\n            - |2\n                  <backups>\n            - |2\n                      <allowed_disk>backups</allowed_disk>\n            - |2\n                      <allowed_path>/etc/clickhouse-server/</allowed_path>\n            - |2\n                  </backups>\n            - |\n              </clickhouse>\n            - |+\n\n            - |\n              EOF\n            - |+\n\n            - |\n              cat << EOF > /home/ec2-user/config/chroma_users.xml\n            - |\n              <clickhouse>\n            - |2\n                  <profiles>\n            - |2\n                    <default>\n            - |2\n                          <allow_experimental_lightweight_delete>1</allow_experimental_lightweight_delete>\n            - |2\n                          <mutations_sync>1</mutations_sync>\n            - |2\n                      </default>\n            - |2\n                  </profiles>\n            - |\n              </clickhouse>\n            - |+\n\n            - |\n              EOF\n            - |+\n\n            - |\n              docker-compose -f /home/ec2-user/docker-compose.yml up -d\n            - |+\n\n            - |\n              --//--\n      SecurityGroupIds:\n        - !Ref ChromaInstanceSecurityGroup\n      KeyName: !If\n        - HasKeyName\n        - !Ref KeyName\n        - !Ref 'AWS::NoValue'\n      BlockDeviceMappings:\n        - DeviceName: !FindInMap\n            - Region2AMI\n            - !Ref 'AWS::Region'\n            - RootDeviceName\n          Ebs:\n            VolumeSize: 24\n"
  },
  {
    "path": "bots/mam.tf",
    "content": "// Existing Terraform src code found at /var/folders/d_/1x0yyl7n5g5cc8vlgchdr06m0000gn/T/terraform_src.\n"
  },
  {
    "path": "docker-compose.yml",
    "content": "version: \"3.9\"\n\nservices:\n  promethai:\n    networks:\n      - agi_backend\n    depends_on:\n      - db_agi\n      - redis\n    build:\n      context: ./\n    volumes:\n      - \"./:/app\"\n    environment:\n      - HOST=0.0.0.0\n    profiles: [\"exclude-from-up\"] # Use `docker-compose run teenage-agi` to get an attached container\n    ports:\n      - 8000:8000\n      - 443:443\n\n  db_agi:\n    image: postgres:14-alpine\n    container_name: \"agi_db\"\n    networks:\n      - agi_backend\n    ports:\n      - \"65432:5432\"\n    environment:\n      POSTGRES_USER: master\n      POSTGRES_PASSWORD: supersecreto\n      POSTGRES_DB: agi_db\n    volumes:\n      - ./initdb:/docker-entrypoint-initdb.d\n\n  redis:\n    image: redis/redis-stack\n    container_name: \"redis\"\n    networks:\n      - agi_backend\n    ports:\n      - \"6379:6379\"\n\nnetworks:\n  agi_backend:\n    name: agi_backend\n"
  },
  {
    "path": "entrypoint.sh",
    "content": "#!/bin/bash\nexport ENVIRONMENT\npython fetch_secret.py\n\n# Start Gunicorn\ngunicorn -w 2 -k uvicorn.workers.UvicornWorker -t 120 --bind=0.0.0.0:8000 --bind=0.0.0.0:443 --log-level debug  api:app"
  },
  {
    "path": "examples/level_1/level_1_pdf_vectorstore_dlt_etl.py",
    "content": "#Make sure to install the following packages: dlt, langchain, duckdb, python-dotenv, openai, weaviate-client\n\nimport dlt\nfrom langchain import PromptTemplate, LLMChain\nfrom langchain.chains.openai_functions import create_structured_output_chain\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.document_loaders import PyPDFLoader\nimport weaviate\nimport os\nimport json\n\nimport argparse\n\nfrom langchain.embeddings import OpenAIEmbeddings\nfrom langchain.prompts import HumanMessagePromptTemplate, ChatPromptTemplate\nfrom langchain.retrievers import WeaviateHybridSearchRetriever\nfrom langchain.schema import Document, SystemMessage, HumanMessage\nfrom langchain.vectorstores import Weaviate\nimport uuid\nfrom dotenv import load_dotenv\nload_dotenv()\nfrom pathlib import Path\nfrom langchain import OpenAI, LLMMathChain\n\nimport os\n\nembeddings = OpenAIEmbeddings()\n\nfrom deep_translator import (GoogleTranslator)\n\ndef _convert_pdf_to_document(path: str = None):\n\n    \"\"\"Convert a PDF document to a Document object\"\"\"\n    if path is None:\n        raise ValueError(\"A valid path to the document must be provided.\")\n\n    loader = PyPDFLoader(path)\n    pages = loader.load_and_split()\n\n    print(\"PAGES\", pages[0])\n\n    # Parse metadata from the folder path\n    path_parts = Path(path).parts\n    personal_receipts_index = path_parts.index(\"personal_receipts\")\n    metadata_parts = path_parts[personal_receipts_index+1:]\n\n    documents = []\n    for page in pages:\n        translation = GoogleTranslator(source='auto', target='en').translate(text=page.page_content)\n        documents.append(\n            Document(\n                metadata={\n                    \"title\": \"Personal Receipt\",\n                    \"country\": metadata_parts[1],\n                    \"year\": metadata_parts[0],\n                    \"author\": str(uuid.uuid4()),\n                    \"source\": \"/\".join(metadata_parts),\n                },\n                page_content=translation,\n            )\n        )\n    print(documents)\n\n    return documents\n\n\n\ndef _init_weaviate():\n    \"\"\"Initialize weaviate client and retriever\"\"\"\n    auth_config = weaviate.auth.AuthApiKey(api_key=os.environ.get('WEAVIATE_API_KEY'))\n    client = weaviate.Client(\n        url='https://my-vev-index-o4qitptw.weaviate.network',\n        auth_client_secret=auth_config,\n\n        additional_headers={\n            \"X-OpenAI-Api-Key\": os.environ.get('OPENAI_API_KEY')\n        }\n    )\n    retriever = WeaviateHybridSearchRetriever(\n        client=client,\n        index_name=\"PDFloader\",\n        text_key=\"text\",\n        attributes=[],\n        embedding=embeddings,\n        create_schema_if_missing=True,\n    )\n\n    return retriever\ndef load_to_weaviate(document_path=None):\n    \"\"\"Load documents to weaviate\"\"\"\n    retriever =_init_weaviate()\n\n    docs = _convert_pdf_to_document(document_path)\n\n    return retriever.add_documents(docs)\n\n\ndef get_from_weaviate(query=None, path=None, operator=None, valueText=None):\n    \"\"\"\n    Get documents from weaviate.\n\n    Args:\n        query (str): The query string.\n        path (list): The path for filtering, e.g., ['year'].\n        operator (str): The operator for filtering, e.g., 'Equal'.\n        valueText (str): The value for filtering, e.g., '2017*'.\n\n    Example:\n        get_from_weaviate(query=\"some query\", path=['year'], operator='Equal', valueText='2017*')\n    \"\"\"\n    retriever = _init_weaviate()\n\n    # Initial retrieval without filters\n    output = retriever.get_relevant_documents(\n        query,\n        score=True,\n    )\n\n    # Apply filters if provided\n    if path or operator or valueText:\n        # Create the where_filter based on provided parameters\n        where_filter = {\n            'path': path if path else [],\n            'operator': operator if operator else '',\n            'valueText': valueText if valueText else ''\n        }\n\n        # Retrieve documents with filters applied\n        output = retriever.get_relevant_documents(\n            query,\n            score=True,\n            where_filter=where_filter\n        )\n\n    return output\n\n\ndef delete_from_weaviate(query=None, filters=None):\n    \"\"\"Delete documents from weaviate, pass dict as filters\"\"\"\n    \"\"\"  {\n        'path': ['year'],\n        'operator': 'Equal',\n        'valueText': '2017*'     }\"\"\"\n    auth_config = weaviate.auth.AuthApiKey(api_key=os.environ.get('WEAVIATE_API_KEY'))\n    client = weaviate.Client(\n        url='https://my-vev-index-o4qitptw.weaviate.network',\n        auth_client_secret=auth_config,\n\n        additional_headers={\n            \"X-OpenAI-Api-Key\": os.environ.get('OPENAI_API_KEY')\n        }\n    )\n    client.batch.delete_objects(\n        class_name='PDFloader',\n        # Same `where` filter as in the GraphQL API\n        where={\n            'path': ['year'],\n            'operator': 'Equal',\n            'valueText': '2017*'\n        },\n    )\n\n    return \"Success\"\n\n\nllm = ChatOpenAI(\n            temperature=0.0,\n            max_tokens=1200,\n            openai_api_key=os.environ.get('OPENAI_API_KEY'),\n            model_name=\"gpt-4-0613\",\n        )\n\n\n\ndef infer_schema_from_text(text: str):\n    \"\"\"Infer schema from text\"\"\"\n\n    prompt_ = \"\"\" You are a json schema master. Create a JSON schema based on the following data and don't write anything else: {prompt} \"\"\"\n\n    complete_query = PromptTemplate(\n    input_variables=[\"prompt\"],\n    template=prompt_,\n)\n\n    chain = LLMChain(\n        llm=llm, prompt=complete_query, verbose=True\n    )\n    chain_result = chain.run(prompt=text).strip()\n\n    json_data = json.dumps(chain_result)\n    return json_data\n\n\ndef set_data_contract(data, version, date, agreement_id=None, privacy_policy=None, terms_of_service=None, format=None, schema_version=None, checksum=None, owner=None, license=None, validity_start=None, validity_end=None):\n    # Creating the generic data contract\n\n    data_contract = {\n        \"version\": version or \"\",\n        \"date\": date or \"\",\n        \"agreement_id\": agreement_id or \"\",\n        \"privacy_policy\": privacy_policy or \"\",\n        \"terms_of_service\": terms_of_service or \"\",\n        \"format\": format or \"\",\n        \"schema_version\": schema_version or \"\",\n        \"checksum\": checksum or \"\",\n        \"owner\": owner or \"\",\n        \"license\": license or \"\",\n        \"validity_start\": validity_start or \"\",\n        \"validity_end\": validity_end or \"\",\n        \"properties\": data  # Adding the given data under the \"properties\" field\n    }\n\n\n\n    return data_contract\n\ndef create_id_dict(memory_id=None, st_memory_id=None, buffer_id=None):\n    \"\"\"\n    Create a dictionary containing IDs for memory, st_memory, and buffer.\n\n    Args:\n        memory_id (str): The Memory ID.\n        st_memory_id (str): The St_memory ID.\n        buffer_id (str): The Buffer ID.\n\n    Returns:\n        dict: A dictionary containing the IDs.\n    \"\"\"\n    id_dict = {\n        \"memoryID\": memory_id or \"\",\n        \"st_MemoryID\": st_memory_id or \"\",\n        \"bufferID\": buffer_id or \"\"\n    }\n    return id_dict\n\n\n\ndef init_buffer(data, version, date, memory_id=None, st_memory_id=None, buffer_id=None, agreement_id=None, privacy_policy=None, terms_of_service=None, format=None, schema_version=None, checksum=None, owner=None, license=None, validity_start=None, validity_end=None, text=None, process=None):\n    # Create ID dictionary\n    id_dict = create_id_dict(memory_id, st_memory_id, buffer_id)\n\n    # Set data contract\n    data_contract = set_data_contract(data, version, date, agreement_id, privacy_policy, terms_of_service, format, schema_version, checksum, owner, license, validity_start, validity_end)\n\n    # Add ID dictionary to properties\n    data_contract[\"properties\"][\"relations\"] = id_dict\n\n    # Infer schema from text and add to properties\n    if text:\n        schema = infer_schema_from_text(text)\n        data_contract[\"properties\"][\"schema\"] = schema\n\n    if process:\n        data_contract[\"properties\"][\"process\"] = process\n\n\n    return data_contract\n\n\ndef infer_properties_from_text(text: str):\n    \"\"\"Infer schema properties from text\"\"\"\n\n    prompt_ = \"\"\" You are a json index master. Create a short JSON index containing the most important data and don't write anything else: {prompt} \"\"\"\n\n    complete_query = PromptTemplate(\n    input_variables=[\"prompt\"],\n    template=prompt_,\n)\n\n    chain = LLMChain(\n        llm=llm, prompt=complete_query, verbose=True\n    )\n    chain_result = chain.run(prompt=text).strip()\n    # json_data = json.dumps(chain_result)\n    return chain_result\n#\n#\n# # print(infer_schema_from_text(output[0].page_content))\n\n\ndef load_json_or_infer_schema(file_path, document_path):\n    \"\"\"Load JSON schema from file or infer schema from text\"\"\"\n    try:\n        # Attempt to load the JSON file\n        with open(file_path, 'r') as file:\n            json_schema = json.load(file)\n        return json_schema\n    except FileNotFoundError:\n        # If the file doesn't exist, run the specified function\n        output = _convert_pdf_to_document(path=document_path)\n        json_schema = infer_schema_from_text(output[0].page_content)\n        return json_schema\n\n\n\n\ndef ai_function(prompt=None, json_schema=None):\n    \"\"\"AI function to convert unstructured data to structured data\"\"\"\n    # Here we define the user prompt and the structure of the output we desire\n    # prompt = output[0].page_content\n\n    prompt_msgs = [\n        SystemMessage(\n            content=\"You are a world class algorithm converting unstructured data into structured data.\"\n        ),\n        HumanMessage(content=\"Convert unstructured data to structured data:\"),\n        HumanMessagePromptTemplate.from_template(\"{input}\"),\n        HumanMessage(content=\"Tips: Make sure to answer in the correct format\"),\n    ]\n    prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n    chain = create_structured_output_chain(json_schema , prompt=prompt_, llm=llm, verbose=True)\n    output = chain.run(input = prompt, llm=llm)\n    yield output\n\n\n# Define a base directory if you have one; this could be the directory where your script is located\nBASE_DIR = os.path.dirname(os.path.abspath(__file__))\n\n\n\ndef higher_level_thinking():\n    \"\"\"Higher level thinking function to calculate the sum of the price of the tickets from these documents\"\"\"\n\n    docs_data = get_from_weaviate(query=\"Train\", path=['year'], operator='Equal', valueText='2017*')\n    str_docs_data = str(docs_data)\n\n    llm_math = LLMMathChain.from_llm(llm, verbose=True)\n    output = llm_math.run(f\"Calculate the sum of the price of the tickets from these documents: {str_docs_data}\")\n\n    # data_format = init_buffer(data=output, version=\"0.0.1\", date=\"2021-09-01\")\n    yield output\nresult_higher_level_thinking = higher_level_thinking()\ndef process_higher_level_thinking(result=None):\n    data_format = init_buffer(data=result, version=\"0.0.1\", date=\"2021-09-01\")\n    import json\n    data_format=json.dumps(data_format)\n    yield data_format\n\ndocument_paths = [\n    os.path.join(BASE_DIR, \"personal_receipts\", \"2017\", \"de\", \"public_transport\", \"3ZCCCW.pdf\"),\n    os.path.join(BASE_DIR, \"personal_receipts\", \"2017\", \"de\", \"public_transport\", \"4GBEC9.pdf\")\n]\n\n\n\ndef main(raw_loading, processed_loading,document_paths):\n    BASE_DIR = os.getcwd()  # Assuming the current working directory is where the data_processing_script.py is located\n\n    def format_document_paths(base_dir, path):\n        # Split the input path and extract the elements\n        elements = path.strip(\"/\").split(\"/\")\n\n        # Construct the document_paths list\n        document_paths = [os.path.join(base_dir, *elements)]\n\n        return document_paths\n\n    document_paths_ =[format_document_paths(BASE_DIR, path) for path in document_paths][0]\n    print(document_paths)\n\n    if raw_loading:\n        for document in document_paths_:\n            file_path = os.path.join(BASE_DIR, \"ticket_schema.json\")\n            json_schema = load_json_or_infer_schema(file_path, document)\n            output = _convert_pdf_to_document(path=document)\n            find_data_in_store = get_from_weaviate(query=\"Train\", path=['year'], operator='Equal', valueText='2017*')\n\n            if find_data_in_store:\n                output = find_data_in_store\n                print(output[1])\n            else:\n                load_to_weaviate(document)\n\n            pipeline = dlt.pipeline(pipeline_name=\"train_ticket\", destination='duckdb', dataset_name='train_ticket_data')\n            info = pipeline.run(data=ai_function(output[0].page_content, json_schema))\n            print(info)\n\n    elif processed_loading:\n        pipeline_processed = dlt.pipeline(pipeline_name=\"train_ticket_processed\", destination='duckdb',\n                                          dataset_name='train_ticket_processed_data')\n        info = pipeline_processed.run(data=higher_level_thinking())\n        print(info)\n\n    else:\n        print(\"Please specify either '--raw_loading' or '--processed_loading' option.\")\n\n\n\n\nif __name__ == \"__main__\":\n    parser = argparse.ArgumentParser(description=\"Data Processing Script\")\n    parser.add_argument(\"--raw_loading\", action=\"store_true\", help=\"Load raw document data and perform AI tasks\")\n    parser.add_argument(\"--processed_loading\", action=\"store_true\",\n                        help=\"Load processed data and run higher-level thinking AI function\")\n    parser.add_argument(\"document_paths\", nargs=\"*\", help=\"Paths to the documents to process\")\n\n    args = parser.parse_args()\n\n    main(args.raw_loading, args.processed_loading, args.document_paths)\n\n\n#to run:  python3 level_1_pdf_vectorstore_dlt_etl.py --raw_loading \"/personal_receipts/2017/de/public_transport/3ZCCCW.pdf\"\n\n"
  },
  {
    "path": "examples/level_1/ticket_schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"ticketType\": {\n      \"type\": \"string\",\n      \"enum\": [\"online ticket\", \"ICE ticket\"]\n    },\n    \"departureDate\": {\n      \"type\": \"string\",\n      \"format\": \"date\"\n    },\n    \"priceType\": {\n      \"type\": \"string\",\n      \"enum\": [\"Flex price (single journey)\"]\n    },\n    \"class\": {\n      \"type\": \"integer\",\n      \"enum\": [1]\n    },\n    \"adult\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"quantity\": {\n          \"type\": \"integer\"\n        },\n        \"BC50\": {\n          \"type\": \"integer\"\n        }\n      },\n      \"required\": [\"quantity\", \"BC50\"]\n    },\n    \"journey\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"from\": {\n          \"type\": \"string\"\n        },\n        \"to\": {\n          \"type\": \"string\"\n        },\n        \"via\": {\n          \"type\": \"string\"\n        },\n        \"train\": {\n          \"type\": \"string\",\n          \"enum\": [\"ICE\"]\n        }\n      },\n      \"required\": [\"from\", \"to\", \"via\", \"train\"]\n    },\n    \"refundPolicy\": {\n      \"type\": \"string\"\n    },\n    \"payment\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"items\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"name\": {\n                \"type\": \"string\"\n              },\n              \"quantity\": {\n                \"type\": \"integer\"\n              },\n              \"price\": {\n                \"type\": \"number\"\n              },\n              \"vat19\": {\n                \"type\": \"number\"\n              },\n              \"vat7\": {\n                \"type\": \"number\"\n              }\n            },\n            \"required\": [\"name\", \"quantity\", \"price\", \"vat19\", \"vat7\"]\n          }\n        },\n        \"total\": {\n          \"type\": \"number\"\n        },\n        \"method\": {\n          \"type\": \"string\",\n          \"enum\": [\"credit card\"]\n        },\n        \"transactionDetails\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"amount\": {\n              \"type\": \"number\"\n            },\n            \"VUNumber\": {\n              \"type\": \"integer\"\n            },\n            \"transactionNumber\": {\n              \"type\": \"integer\"\n            },\n            \"date\": {\n              \"type\": \"string\",\n              \"format\": \"date\"\n            },\n            \"genNumber\": {\n              \"type\": \"string\"\n            }\n          },\n          \"required\": [\"amount\", \"VUNumber\", \"transactionNumber\", \"date\", \"genNumber\"]\n        }\n      },\n      \"required\": [\"items\", \"total\", \"method\", \"transactionDetails\"]\n    },\n    \"bookingDetails\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"bookingDate\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\"\n        },\n        \"bookingAddress\": {\n          \"type\": \"string\"\n        },\n        \"taxNumber\": {\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\"bookingDate\", \"bookingAddress\", \"taxNumber\"]\n    },\n    \"journeyDetails\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"validFrom\": {\n          \"type\": \"string\",\n          \"format\": \"date\"\n        },\n        \"passengerName\": {\n          \"type\": \"string\"\n        },\n        \"orderNumber\": {\n          \"type\": \"string\"\n        },\n        \"stops\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"stop\": {\n                \"type\": \"string\"\n              },\n              \"date\": {\n                \"type\": \"string\",\n                \"format\": \"date\"\n              },\n              \"time\": {\n                \"type\": \"string\",\n                \"format\": \"time\"\n              },\n              \"track\": {\n                \"type\": \"integer\"\n              },\n              \"product\": {\n                \"type\": \"string\"\n              },\n              \"reservation\": {\n                \"type\": \"string\"\n              }\n            },\n            \"required\": [\"stop\", \"date\", \"time\", \"track\", \"product\", \"reservation\"]\n          }\n        }\n      },\n      \"required\": [\"validFrom\", \"passengerName\", \"orderNumber\", \"stops\"]\n    },\n    \"usageNotes\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"ticketType\", \"departureDate\", \"priceType\", \"class\", \"adult\", \"journey\", \"refundPolicy\", \"payment\", \"bookingDetails\", \"journeyDetails\", \"usageNotes\"]\n}"
  },
  {
    "path": "examples/level_2/Dockerfile",
    "content": "\nFROM python:3.11-slim\n\n# Set build argument\nARG API_ENABLED\n\n# Set environment variable based on the build argument\nENV API_ENABLED=${API_ENABLED} \\\n    PIP_NO_CACHE_DIR=true\nENV PATH=\"${PATH}:/root/.poetry/bin\"\nRUN pip install poetry\n\nWORKDIR /app\nCOPY pyproject.toml poetry.lock /app/\n\n# Install the dependencies\nRUN poetry config virtualenvs.create false && \\\n    poetry install --no-root --no-dev\n\nRUN apt-get update -q && \\\n    apt-get install curl zip jq netcat-traditional -y -q\nRUN curl \"https://awscli.amazonaws.com/awscli-exe-linux-x86_64.zip\" -o \"awscliv2.zip\" && \\\n    unzip -qq awscliv2.zip && ./aws/install && \\\n    apt-get clean && \\\n    rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*\n\n\n#RUN playwright install\n#RUN playwright install-deps\n\nWORKDIR /app\nCOPY . /app\nCOPY entrypoint.sh /app/entrypoint.sh\nRUN chmod +x /app/entrypoint.sh\n\nENTRYPOINT [\"/app/entrypoint.sh\"]"
  },
  {
    "path": "examples/level_2/Readme.md",
    "content": "## PromethAI Memory Manager\n\n\n\n### Description\n\n\nInitial code lets you do three operations:\n\n1. Add to memory\n2. Retrieve from memory\n3. Structure the data to schema and load to duckdb\n\n#How to use\n\n## Installation\n\n```docker compose build promethai_mem   ```\n\n## Run\n\n```docker compose up promethai_mem   ```\n\n\n## Usage\n\nThe fast API endpoint accepts prompts and PDF files and returns a JSON object with the generated text.\n\n```curl                                                                    \n    -X POST                                                                                             \n    -F \"prompt=The quick brown fox\"                                                                     \n    -F \"file=@/path/to/file.pdf\"                                                                       \n    http://localhost:8000/generate/                                                                    \n```"
  },
  {
    "path": "examples/level_2/api.py",
    "content": "from langchain.document_loaders import PyPDFLoader\n\nfrom level_2_pdf_vectorstore__dlt_contracts import ShortTermMemory\nfrom fastapi import FastAPI\nfrom fastapi.responses import JSONResponse\nfrom pydantic import BaseModel\nfrom typing import Dict, Any\nimport re\nimport json\nimport logging\nimport os\nimport uvicorn\nfrom fastapi import Request\nimport yaml\nfrom fastapi import HTTPException\nfrom fastapi import FastAPI, UploadFile, File\nfrom typing import List\nfrom level_2_pdf_vectorstore__dlt_contracts import ShortTermMemory\n\n# Set up logging\nlogging.basicConfig(\n    level=logging.INFO,  # Set the logging level (e.g., DEBUG, INFO, WARNING, ERROR, CRITICAL)\n    format=\"%(asctime)s [%(levelname)s] %(message)s\",  # Set the log message format\n)\n\nlogger = logging.getLogger(__name__)\nfrom dotenv import load_dotenv\n\n\nload_dotenv()\n\n\napp = FastAPI(debug=True)\n\n\nfrom fastapi import Depends\n\n\nclass Payload(BaseModel):\n    payload: str\nclass ImageResponse(BaseModel):\n    success: bool\n    message: str\n\n\n\n\n@app.get(\"/\", )\nasync def root():\n    \"\"\"\n    Root endpoint that returns a welcome message.\n    \"\"\"\n    return {\"message\": \"Hello, World, I am alive!\"}\n\n@app.get(\"/health\")\ndef health_check():\n    \"\"\"\n    Health check endpoint that returns the server status.\n    \"\"\"\n    return {\"status\": \"OK\"}\n\n\n\n\n\n\n#curl -X POST -H \"Content-Type: application/json\" -d '{\"data\": \"YourPayload\"}' -F \"files=@/path/to/your/pdf/file.pdf\" http://127.0.0.1:8000/upload/\n\n@app.post(\"/upload/\")\nasync def upload_pdf_and_payload(\n        payload: Payload,\n        files: List[UploadFile] = File(...),\n):\n    try:\n        # Process the payload\n        payload_data = payload.payload\n\n        decoded_payload = json.loads(payload_data)\n        # Process each uploaded PDF file\n        results = []\n        for file in files:\n            contents = await file.read()\n            tmp_location = os.path.join('/tmp', \"tmp.pdf\")\n            with open(tmp_location, 'wb') as tmp_file:\n                tmp_file.write(contents)\n            loader = PyPDFLoader(tmp_location)\n            pages = loader.load_and_split()\n\n            stm = ShortTermMemory( user_id=decoded_payload['user_id'])\n            stm.episodic_buffer.main_buffer(prompt=decoded_payload['prompt'], pages=pages)\n            # Here you can perform your processing on the PDF contents\n            results.append({\"filename\": file.filename, \"size\": len(contents)})\n\n        return {\"message\": \"Upload successful\", \"results\": results}\n\n    except Exception as e:\n        return {\"error\": str(e)}\n\n\n\n\n\n\n# @app.post(\"/clear-cache\", response_model=dict)\n# async def clear_cache(request_data: Payload) -> dict:\n#     \"\"\"\n#     Endpoint to clear the cache.\n#\n#     Parameters:\n#     request_data (Payload): The request data containing the user and session IDs.\n#\n#     Returns:\n#     dict: A dictionary with a message indicating the cache was cleared.\n#     \"\"\"\n#     json_payload = request_data.payload\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     try:\n#         agent.clear_cache()\n#         return JSONResponse(content={\"response\": \"Cache cleared\"}, status_code=200)\n#     except Exception as e:\n#         raise HTTPException(status_code=500, detail=str(e))\n#\n# @app.post(\"/correct-prompt-grammar\", response_model=dict)\n# async def prompt_to_correct_grammar(request_data: Payload) -> dict:\n#     json_payload = request_data.payload\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     logging.info(\"Correcting grammar %s\", json_payload[\"prompt_source\"])\n#\n#     output = agent.prompt_correction(json_payload[\"prompt_source\"], model_speed= json_payload[\"model_speed\"])\n#     return JSONResponse(content={\"response\": {\"result\": json.loads(output)}})\n\n\n# @app.post(\"/action-add-zapier-calendar-action\", response_model=dict,dependencies=[Depends(auth)])\n# async def action_add_zapier_calendar_action(\n#     request: Request, request_data: Payload\n# ) -> dict:\n#     json_payload = request_data.payload\n#     agent = Agent()\n#     agent.set_user_session(json_payload[\"user_id\"], json_payload[\"session_id\"])\n#     # Extract the bearer token from the header\n#     auth_header = request.headers.get(\"Authorization\")\n#     if auth_header:\n#         bearer_token = auth_header.replace(\"Bearer \", \"\")\n#     else:\n#         bearer_token = None\n#     outcome = agent.add_zapier_calendar_action(\n#         prompt_base=json_payload[\"prompt_base\"],\n#         token=bearer_token,\n#         model_speed=json_payload[\"model_speed\"],\n#     )\n#     return JSONResponse(content={\"response\": outcome})\n\n\n\ndef start_api_server(host: str = \"0.0.0.0\", port: int = 8000):\n    \"\"\"\n    Start the API server using uvicorn.\n\n    Parameters:\n    host (str): The host for the server.\n    port (int): The port for the server.\n    \"\"\"\n    try:\n        logger.info(f\"Starting server at {host}:{port}\")\n        uvicorn.run(app, host=host, port=port)\n    except Exception as e:\n        logger.exception(f\"Failed to start server: {e}\")\n        # Here you could add any cleanup code or error recovery code.\n\n\nif __name__ == \"__main__\":\n    start_api_server()\n"
  },
  {
    "path": "examples/level_2/docker-compose.yml",
    "content": "version: \"3.9\"\n\nservices:\n  promethai_mem:\n    networks:\n      - promethai_mem_backend\n    build:\n      context: ./\n    volumes:\n      - \"./:/app\"\n    environment:\n      - HOST=0.0.0.0\n    profiles: [\"exclude-from-up\"] # Use `docker-compose run teenage-agi` to get an attached container\n    ports:\n      - 8000:8000\n      - 443:443\n\n\n\nnetworks:\n  promethai_mem_backend:\n    name: promethai_mem_backend\n"
  },
  {
    "path": "examples/level_2/entrypoint.sh",
    "content": "#!/bin/bash\nexport ENVIRONMENT\n#python fetch_secret.py\n\n# Start Gunicorn\ngunicorn -w 2 -k uvicorn.workers.UvicornWorker -t 120 --bind=0.0.0.0:8000 --bind=0.0.0.0:443 --log-level debug  api:app"
  },
  {
    "path": "examples/level_2/level_2_pdf_vectorstore__dlt_contracts.py",
    "content": "#Make sure to install the following packages: dlt, langchain, duckdb, python-dotenv, openai, weaviate-client\n\nimport dlt\nfrom langchain import PromptTemplate, LLMChain\nfrom langchain.agents import initialize_agent, AgentType\nfrom langchain.chains.openai_functions import create_structured_output_chain\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.document_loaders import PyPDFLoader\nimport weaviate\nimport os\nimport json\nfrom marvin import ai_classifier\nfrom enum import Enum\nimport marvin\nimport asyncio\nfrom langchain.embeddings import OpenAIEmbeddings\nfrom langchain.prompts import HumanMessagePromptTemplate, ChatPromptTemplate\nfrom langchain.retrievers import WeaviateHybridSearchRetriever\nfrom langchain.schema import Document, SystemMessage, HumanMessage\nfrom langchain.tools import tool\nfrom langchain.vectorstores import Weaviate\nimport uuid\nfrom dotenv import load_dotenv\nload_dotenv()\nfrom pathlib import Path\nfrom langchain import OpenAI, LLMMathChain\n\nimport os\n\nfrom datetime import datetime\nimport os\nfrom datetime import datetime\nfrom jinja2 import Template\nfrom langchain import PromptTemplate, LLMChain\nfrom langchain.chains.openai_functions import create_structured_output_chain\nfrom langchain.prompts import HumanMessagePromptTemplate, ChatPromptTemplate\nfrom langchain.text_splitter import RecursiveCharacterTextSplitter\nimport pinecone\nfrom langchain.vectorstores import Pinecone\nfrom langchain.embeddings.openai import OpenAIEmbeddings\nfrom pydantic import BaseModel, Field\nfrom dotenv import load_dotenv\nfrom langchain.schema import Document, SystemMessage, HumanMessage\nfrom langchain.vectorstores import Weaviate\nimport weaviate\nimport uuid\nload_dotenv()\n\nclass VectorDB:\n    def __init__(self, user_id: str, index_name: str, memory_id:str, ltm_memory_id:str='00000', st_memory_id:str='0000', buffer_id:str='0000', db_type: str = \"pinecone\",  namespace:str = None):\n        self.user_id = user_id\n        self.index_name = index_name\n        self.db_type = db_type\n        self.namespace=namespace\n        self.memory_id = memory_id\n        self.ltm_memory_id = ltm_memory_id\n        self.st_memory_id = st_memory_id\n        self.buffer_id = buffer_id\n        # if self.db_type == \"pinecone\":\n        #     self.vectorstore = self.init_pinecone(self.index_name)\n        if self.db_type == \"weaviate\":\n            self.init_weaviate(namespace=self.namespace)\n        else:\n            raise ValueError(f\"Unsupported database type: {db_type}\")\n\n    def init_pinecone(self, index_name):\n        load_dotenv()\n        PINECONE_API_KEY = os.getenv(\"PINECONE_API_KEY\", \"\")\n        PINECONE_API_ENV = os.getenv(\"PINECONE_API_ENV\", \"\")\n        pinecone.init(api_key=PINECONE_API_KEY, environment=PINECONE_API_ENV)\n        pinecone.Index(index_name)\n        vectorstore: Pinecone = Pinecone.from_existing_index(\n\n            index_name=self.index_name,\n            embedding=OpenAIEmbeddings(),\n            namespace='RESULT'\n        )\n        return vectorstore\n\n    def init_weaviate(self, namespace:str):\n        embeddings = OpenAIEmbeddings()\n        auth_config = weaviate.auth.AuthApiKey(api_key=os.environ.get('WEAVIATE_API_KEY'))\n        client = weaviate.Client(\n            url=os.environ.get('WEAVIATE_URL'),\n            auth_client_secret=auth_config,\n\n            additional_headers={\n                \"X-OpenAI-Api-Key\": os.environ.get('OPENAI_API_KEY')\n            }\n        )\n        retriever = WeaviateHybridSearchRetriever(\n            client=client,\n            index_name=namespace,\n            text_key=\"text\",\n            attributes=[],\n            embedding=embeddings,\n            create_schema_if_missing=True,\n        )\n        return retriever\n\n    def add_memories(self, observation: str,  page: str = \"\", source: str = \"\"):\n        if self.db_type == \"pinecone\":\n            # Update Pinecone memories here\n            vectorstore: Pinecone = Pinecone.from_existing_index(\n                index_name=self.index_name, embedding=OpenAIEmbeddings(), namespace=self.namespace\n            )\n\n\n            retriever = vectorstore.as_retriever()\n            retriever.add_documents(\n                [\n                    Document(\n                        page_content=observation,\n                        metadata={\n                            \"inserted_at\": datetime.now(),\n                            \"text\": observation,\n                            \"user_id\": self.user_id,\n                            \"page\": page,\n                            \"source\": source\n                        },\n                        namespace=self.namespace,\n                    )\n                ]\n            )\n        elif self.db_type == \"weaviate\":\n            # Update Weaviate memories here\n            retriever = self.init_weaviate( self.namespace)\n\n\n            return retriever.add_documents([\n                Document(\n                    metadata={\n                        \"inserted_at\": str(datetime.now()),\n                        \"text\": observation,\n                        \"user_id\": str(self.user_id),\n                        \"memory_id\": str(self.memory_id),\n                        \"ltm_memory_id\": str(self.ltm_memory_id),\n                        \"st_memory_id\": str(self.st_memory_id),\n                        \"buffer_id\": str(self.buffer_id),\n\n                        # **source_metadata,\n                    },\n                    page_content=observation,\n                )]\n            )\n    # def get_pinecone_vectorstore(self, namespace: str) -> pinecone.VectorStore:\n    #     return Pinecone.from_existing_index(\n    #         index_name=self.index, embedding=OpenAIEmbeddings(), namespace=namespace\n    #     )\n\n    def fetch_memories(self, observation: str, params = None):\n        if self.db_type == \"pinecone\":\n            # Fetch Pinecone memories here\n            pass\n        elif self.db_type == \"weaviate\":\n            # Fetch Weaviate memories here\n            \"\"\"\n            Get documents from weaviate.\n\n            Args a json containing:\n                query (str): The query string.\n                path (list): The path for filtering, e.g., ['year'].\n                operator (str): The operator for filtering, e.g., 'Equal'.\n                valueText (str): The value for filtering, e.g., '2017*'.\n\n            Example:\n                get_from_weaviate(query=\"some query\", path=['year'], operator='Equal', valueText='2017*')\n            \"\"\"\n            retriever = self.init_weaviate(self.namespace)\n\n            print(self.namespace)\n            print(str(datetime.now()))\n\n            # Retrieve documents with filters applied\n            output = retriever.get_relevant_documents(\n                observation,\n                score=True,\n                where_filter=params\n            )\n\n            return output\n\n    def delete_memories(self, params: None):\n        auth_config = weaviate.auth.AuthApiKey(api_key=os.environ.get('WEAVIATE_API_KEY'))\n        client = weaviate.Client(\n            url=os.environ.get('WEAVIATE_API_KEY'),\n            auth_client_secret=auth_config,\n\n            additional_headers={\n                \"X-OpenAI-Api-Key\": os.environ.get('OPENAI_API_KEY')\n            }\n        )\n        client.batch.delete_objects(\n            class_name=self.namespace,\n            # Same `where` filter as in the GraphQL API\n            where=params,\n        )\n\n    def update_memories(self):\n        pass\n\n\n\nclass SemanticMemory:\n    def __init__(self, user_id: str, memory_id:str, ltm_memory_id:str, index_name: str, db_type:str=\"weaviate\", namespace:str=\"SEMANTICMEMORY\"):\n        # Add any semantic memory-related attributes or setup here\n        self.user_id=user_id\n        self.index_name = index_name\n        self.namespace = namespace\n        self.semantic_memory_id = str(uuid.uuid4())\n        self.memory_id = memory_id\n        self.ltm_memory_id = ltm_memory_id\n        self.vector_db = VectorDB(user_id=user_id, memory_id= self.memory_id, ltm_memory_id = self.ltm_memory_id, index_name=index_name, db_type=db_type, namespace=self.namespace)\n        self.db_type = db_type\n\n\n\n    def _update_memories(self ,memory_id:str=\"None\", semantic_memory: str=\"None\") -> None:\n        \"\"\"Update semantic memory for the user\"\"\"\n\n        if self.db_type == \"weaviate\":\n            self.vector_db.add_memories( observation = semantic_memory)\n\n        elif self.db_type == \"pinecone\":\n            pass\n\n\n    def _fetch_memories(self, observation: str,params) -> dict[str, str] | str:\n        \"\"\"Fetch related characteristics, preferences or dislikes for a user.\"\"\"\n        # self.init_pinecone(index_name=self.index)\n\n        if self.db_type == \"weaviate\":\n\n            return self.vector_db.fetch_memories(observation, params)\n\n        elif self.db_type == \"pinecone\":\n            pass\n\n\nclass LongTermMemory:\n    def __init__(self, user_id: str = \"676\", memory_id:str=None, index_name: str = None, namespace:str=None, db_type:str=\"weaviate\"):\n        self.user_id = user_id\n        self.memory_id = memory_id\n        self.ltm_memory_id = str(uuid.uuid4())\n        self.index_name = index_name\n        self.namespace = namespace\n        self.db_type = db_type\n        # self.episodic_memory = EpisodicMemory()\n        self.semantic_memory = SemanticMemory(user_id = self.user_id, memory_id=self.memory_id, ltm_memory_id = self.ltm_memory_id, index_name=self.index_name, db_type=self.db_type)\n\nclass ShortTermMemory:\n    def __init__(self, user_id: str = \"676\", memory_id:str=None, index_name: str = None, namespace:str=None, db_type:str=\"weaviate\"):\n        # Add any short-term memory-related attributes or setup here\n        self.user_id = user_id\n        self.memory_id = memory_id\n        self.namespace = namespace\n        self.db_type = db_type\n        self.stm_memory_id = str(uuid.uuid4())\n        self.index_name = index_name\n        self.episodic_buffer = EpisodicBuffer(user_id=self.user_id, memory_id=self.memory_id, index_name=self.index_name, db_type=self.db_type)\n\n\n\nclass EpisodicBuffer:\n    def __init__(self, user_id: str = \"676\", memory_id:str=None, index_name: str = None, namespace:str='EPISODICBUFFER', db_type:str=\"weaviate\"):\n        # Add any short-term memory-related attributes or setup here\n        self.user_id = user_id\n        self.memory_id = memory_id\n        self.namespace = namespace\n        self.db_type = db_type\n        self.st_memory_id = \"blah\"\n        self.index_name = index_name\n        self.llm= ChatOpenAI(\n            temperature=0.0,\n            max_tokens=1200,\n            openai_api_key=os.environ.get('OPENAI_API_KEY'),\n            model_name=\"gpt-4-0613\",\n        )\n        # self.vector_db = VectorDB(user_id=user_id, memory_id= self.memory_id, st_memory_id = self.st_memory_id, index_name=index_name, db_type=db_type, namespace=self.namespace)\n\n\n        def _context_filter(self, context: str):\n            \"\"\"Filters the context for the buffer\"\"\"\n\n            prompt = PromptTemplate.from_template(\n                \"\"\" Based on the {CONTEXT} of {user_id} choose events that are relevant\"\"\"\n            )\n\n            return\n\n\n        def _compute_weights(self, context: str):\n            \"\"\"Computes the weights for the buffer\"\"\"\n            pass\n\n        def _temporal_weighting(self, context: str):\n            \"\"\"Computes the temporal weighting for the buffer\"\"\"\n            pass\n\n    async def infer_schema_from_text(self, text: str):\n        \"\"\"Infer schema from text\"\"\"\n\n        prompt_ = \"\"\" You are a json schema master. Create a JSON schema based on the following data and don't write anything else: {prompt} \"\"\"\n\n        complete_query = PromptTemplate(\n            input_variables=[\"prompt\"],\n            template=prompt_,\n        )\n\n        chain = LLMChain(\n            llm=self.llm, prompt=complete_query, verbose=True\n        )\n        chain_result = chain.run(prompt=text).strip()\n\n        json_data = json.dumps(chain_result)\n        return json_data\n\n    def main_buffer(self, user_input=None):\n        \"\"\"AI function to convert unstructured data to structured data\"\"\"\n        # Here we define the user prompt and the structure of the output we desire\n        # prompt = output[0].page_content\n        class PromptWrapper(BaseModel):\n            observation: str = Field(\n                description=\"observation we want to fetch from vectordb\"\n            )\\\n                # ,\n            # json_schema: str = Field(description=\"json schema we want to infer\")\n        @tool(\"convert_to_structured\", args_schema=PromptWrapper, return_direct=True)\n        def convert_to_structured( observation=None, json_schema=None):\n            \"\"\"Convert unstructured data to structured data\"\"\"\n            BASE_DIR = os.getcwd()\n            json_path = os.path.join(BASE_DIR, \"schema_registry\", \"ticket_schema.json\")\n\n            def load_json_or_infer_schema(file_path, document_path):\n                \"\"\"Load JSON schema from file or infer schema from text\"\"\"\n\n                # Attempt to load the JSON file\n                with open(file_path, 'r') as file:\n                    json_schema = json.load(file)\n                return json_schema\n\n            json_schema =load_json_or_infer_schema(json_path, None)\n            def run_open_ai_mapper(observation=None, json_schema=None):\n                \"\"\"Convert unstructured data to structured data\"\"\"\n\n                prompt_msgs = [\n                    SystemMessage(\n                        content=\"You are a world class algorithm converting unstructured data into structured data.\"\n                    ),\n                    HumanMessage(content=\"Convert unstructured data to structured data:\"),\n                    HumanMessagePromptTemplate.from_template(\"{input}\"),\n                    HumanMessage(content=\"Tips: Make sure to answer in the correct format\"),\n                ]\n                prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n                chain_funct = create_structured_output_chain(json_schema, prompt=prompt_, llm=self.llm, verbose=True)\n                output = chain_funct.run(input=observation, llm=self.llm)\n                yield output\n            pipeline = dlt.pipeline(pipeline_name=\"train_ticket\", destination='duckdb', dataset_name='train_ticket_data')\n            info = pipeline.run(data=run_open_ai_mapper(prompt, json_schema))\n            return print(info)\n\n\n        class GoalWrapper(BaseModel):\n            observation: str = Field(\n                description=\"observation we want to fetch from vectordb\"\n            )\n\n        @tool(\"fetch_memory_wrapper\", args_schema=GoalWrapper, return_direct=True)\n        def fetch_memory_wrapper(observation, args_schema=GoalWrapper):\n            \"\"\"Fetches data from the VectorDB and returns it as a python dictionary.\"\"\"\n            print(\"HELLO, HERE IS THE OBSERVATION: \", observation)\n\n            marvin.settings.openai.api_key = os.environ.get('OPENAI_API_KEY')\n            @ai_classifier\n            class MemoryRoute(Enum):\n                \"\"\"Represents distinct routes  for  different memory types.\"\"\"\n\n                storage_of_documents_and_knowledge_to_memory = \"SEMANTICMEMORY\"\n                raw_information_currently_processed_in_short_term_memory = \"EPISODICBUFFER\"\n                raw_information_kept_in_short_term_memory = \"SHORTTERMMEMORY\"\n                long_term_recollections_of_past_events_and_emotions = \"EPISODICMEMORY\"\n\n            namespace= MemoryRoute(observation)\n            vector_db = VectorDB(user_id=self.user_id, memory_id=self.memory_id, st_memory_id=self.st_memory_id,\n                                 index_name=self.index_name, db_type=self.db_type, namespace=namespace.value)\n\n\n            query = vector_db.fetch_memories(observation)\n\n            return query\n\n        class UpdatePreferences(BaseModel):\n            observation: str = Field(\n                description=\"observation we want to fetch from vectordb\"\n            )\n\n        @tool(\"add_memories_wrapper\", args_schema=UpdatePreferences, return_direct=True)\n        def add_memories_wrapper(observation, args_schema=UpdatePreferences):\n            \"\"\"Updates user preferences in the VectorDB.\"\"\"\n            @ai_classifier\n            class MemoryRoute(Enum):\n                \"\"\"Represents distinct routes  for  different memory types.\"\"\"\n\n                storage_of_documents_and_knowledge_to_memory = \"SEMANTICMEMORY\"\n                raw_information_currently_processed_in_short_term_memory = \"EPISODICBUFFER\"\n                raw_information_kept_in_short_term_memory = \"SHORTTERMMEMORY\"\n                long_term_recollections_of_past_events_and_emotions = \"EPISODICMEMORY\"\n\n            namespace= MemoryRoute(observation)\n            print(\"HELLO, HERE IS THE OBSERVATION 2: \")\n            vector_db = VectorDB(user_id=self.user_id, memory_id=self.memory_id, st_memory_id=self.st_memory_id,\n                                 index_name=self.index_name, db_type=self.db_type, namespace=namespace.value)\n            return vector_db.add_memories(observation)\n\n        agent = initialize_agent(\n            llm=self.llm,\n            tools=[convert_to_structured,fetch_memory_wrapper, add_memories_wrapper],\n            agent=AgentType.OPENAI_FUNCTIONS,\n            verbose=True,\n        )\n\n        prompt = \"\"\"\n\n            Based on all the history and information of this user, decide based on user query query: {query} which of the following tasks needs to be done:\n            1. Memory retrieval , 2. Memory update,  3. Convert data to structured   If the query is not any of these, then classify it as 'Other'\n            Return the result in format:  'Result_type': 'Goal', \"Original_query\": \"Original query\"\n            \"\"\"\n\n        # template = Template(prompt)\n        # output = template.render(query=user_input)\n        # complete_query = output\n        complete_query = PromptTemplate(\n            input_variables=[\"query\"], template=prompt\n        )\n        summary_chain = LLMChain(\n            llm=self.llm, prompt=complete_query, verbose=True\n        )\n        from langchain.chains import SimpleSequentialChain\n\n        overall_chain = SimpleSequentialChain(\n            chains=[summary_chain, agent], verbose=True\n        )\n        output = overall_chain.run(user_input)\n        return output\n\n\n\n\n#DEFINE STM\n#DEFINE LTM\n\nclass Memory:\n    load_dotenv()\n\n    def __init__(self, user_id: str = \"676\", index_name: str = None, knowledge_source: str = None,\n                 knowledge_type: str = None, db_type:str=\"weaviate\", namespace:str=None) -> None:\n        self.user_id = user_id\n        self.index_name = index_name\n        self.db_type = db_type\n        self.knowledge_source = knowledge_source\n        self.knowledge_type = knowledge_type\n        self.memory_id = str(uuid.uuid4())\n        self.long_term_memory = LongTermMemory(user_id=self.user_id, memory_id=self.memory_id, index_name=index_name,\n                                                namespace=namespace, db_type=self.db_type)\n        self.short_term_memory = ShortTermMemory(user_id=self.user_id, memory_id=self.memory_id, index_name=index_name, db_type=self.db_type)\n\n\n    def _update_semantic_memory(self, semantic_memory:str):\n        return self.long_term_memory.semantic_memory._update_memories(\n            memory_id=self.memory_id,\n            semantic_memory=semantic_memory\n\n        )\n\n    def _fetch_semantic_memory(self, observation, params):\n        return self.long_term_memory.semantic_memory._fetch_memories(\n            observation=observation, params=params\n\n\n\n        )\n\n    def _run_buffer(self, user_input:str):\n        return self.short_term_memory.episodic_buffer.main_buffer(user_input=user_input)\n\nif __name__ == \"__main__\":\n    namespace = \"gggg\"\n    agent = Memory(index_name=\"my-agent\", user_id='555' )\n    #bb = agent._update_semantic_memory(semantic_memory=\"Users core summary\")\n    # bb = agent._fetch_semantic_memory(observation= \"Users core summary\", params =    {\n    #     \"path\": [\"inserted_at\"],\n    #     \"operator\": \"Equal\",\n    #     \"valueText\": \"*2023*\"\n    # })\n    buffer = agent._run_buffer(user_input=\"I want to get a schema for my data\")\n    # print(bb)\n    # rrr = {\n    #     \"path\": [\"year\"],\n    #     \"operator\": \"Equal\",\n    #     \"valueText\": \"2017*\"\n    # }\n\n"
  },
  {
    "path": "examples/level_2/pyproject.toml",
    "content": "[tool.poetry]\nname = \"PromethAI_memory\"\nversion = \"0.1.0\"\ndescription = \"PromethAI memory manager\"\nauthors = [\"Vasilije Markovic\"]\nreadme = \"README.md\"\n\n[tool.poetry.dependencies]\npython = \"^3.10\"\n#langchain = {git = \"https://github.com/topoteretes/langchain.git\" , tag = \"v0.0.209\"}\nlangchain = \"v0.0.250\"\n\nnltk = \"3.8.1\"\nopenai = \"0.27.8\"\npinecone-client = \"2.2.2\"\npython-dotenv = \"1.0.0\"\npyyaml = \"6.0\"\nfastapi = \"0.98.0\"\nuvicorn = \"0.22.0\"\ngooglemaps = \"4.10.0\"\njinja2 = \"3.1.2\"\nreplicate = \"^0.8.4\"\npexpect = \"^4.8.0\"\nselenium = \"^4.9.0\"\nplaywright = \"^1.32.1\"\npytest-playwright = \"^0.3.3\"\nboto3 = \"^1.26.125\"\ngptcache = \"^0.1.22\"\nredis = \"^4.5.5\"\ngunicorn = \"^20.1.0\"\ntiktoken = \"^0.4.0\"\ngoogle-search-results = \"^2.4.2\"\nspacy = \"^3.5.3\"\npython-jose = \"^3.3.0\"\npypdf = \"^3.12.0\"\nfastjsonschema = \"^2.18.0\"\nmarvin = \"^1.3.0\"\ndlt = \"^0.3.8\"\nweaviate-client = \"^3.22.1\"\npython-multipart = \"^0.0.6\"\n\n\n\n\n\n[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n"
  },
  {
    "path": "examples/level_2/schema_registry/ticket_schema.json",
    "content": "{\n  \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n  \"type\": \"object\",\n  \"properties\": {\n    \"ticketType\": {\n      \"type\": \"string\",\n      \"enum\": [\"online ticket\", \"ICE ticket\"]\n    },\n    \"departureDate\": {\n      \"type\": \"string\",\n      \"format\": \"date\"\n    },\n    \"priceType\": {\n      \"type\": \"string\",\n      \"enum\": [\"Flex price (single journey)\"]\n    },\n    \"class\": {\n      \"type\": \"integer\",\n      \"enum\": [1]\n    },\n    \"adult\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"quantity\": {\n          \"type\": \"integer\"\n        },\n        \"BC50\": {\n          \"type\": \"integer\"\n        }\n      },\n      \"required\": [\"quantity\", \"BC50\"]\n    },\n    \"journey\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"from\": {\n          \"type\": \"string\"\n        },\n        \"to\": {\n          \"type\": \"string\"\n        },\n        \"via\": {\n          \"type\": \"string\"\n        },\n        \"train\": {\n          \"type\": \"string\",\n          \"enum\": [\"ICE\"]\n        }\n      },\n      \"required\": [\"from\", \"to\", \"via\", \"train\"]\n    },\n    \"refundPolicy\": {\n      \"type\": \"string\"\n    },\n    \"payment\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"items\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"name\": {\n                \"type\": \"string\"\n              },\n              \"quantity\": {\n                \"type\": \"integer\"\n              },\n              \"price\": {\n                \"type\": \"number\"\n              },\n              \"vat19\": {\n                \"type\": \"number\"\n              },\n              \"vat7\": {\n                \"type\": \"number\"\n              }\n            },\n            \"required\": [\"name\", \"quantity\", \"price\", \"vat19\", \"vat7\"]\n          }\n        },\n        \"total\": {\n          \"type\": \"number\"\n        },\n        \"method\": {\n          \"type\": \"string\",\n          \"enum\": [\"credit card\"]\n        },\n        \"transactionDetails\": {\n          \"type\": \"object\",\n          \"properties\": {\n            \"amount\": {\n              \"type\": \"number\"\n            },\n            \"VUNumber\": {\n              \"type\": \"integer\"\n            },\n            \"transactionNumber\": {\n              \"type\": \"integer\"\n            },\n            \"date\": {\n              \"type\": \"string\",\n              \"format\": \"date\"\n            },\n            \"genNumber\": {\n              \"type\": \"string\"\n            }\n          },\n          \"required\": [\"amount\", \"VUNumber\", \"transactionNumber\", \"date\", \"genNumber\"]\n        }\n      },\n      \"required\": [\"items\", \"total\", \"method\", \"transactionDetails\"]\n    },\n    \"bookingDetails\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"bookingDate\": {\n          \"type\": \"string\",\n          \"format\": \"date-time\"\n        },\n        \"bookingAddress\": {\n          \"type\": \"string\"\n        },\n        \"taxNumber\": {\n          \"type\": \"string\"\n        }\n      },\n      \"required\": [\"bookingDate\", \"bookingAddress\", \"taxNumber\"]\n    },\n    \"journeyDetails\": {\n      \"type\": \"object\",\n      \"properties\": {\n        \"validFrom\": {\n          \"type\": \"string\",\n          \"format\": \"date\"\n        },\n        \"passengerName\": {\n          \"type\": \"string\"\n        },\n        \"orderNumber\": {\n          \"type\": \"string\"\n        },\n        \"stops\": {\n          \"type\": \"array\",\n          \"items\": {\n            \"type\": \"object\",\n            \"properties\": {\n              \"stop\": {\n                \"type\": \"string\"\n              },\n              \"date\": {\n                \"type\": \"string\",\n                \"format\": \"date\"\n              },\n              \"time\": {\n                \"type\": \"string\",\n                \"format\": \"time\"\n              },\n              \"track\": {\n                \"type\": \"integer\"\n              },\n              \"product\": {\n                \"type\": \"string\"\n              },\n              \"reservation\": {\n                \"type\": \"string\"\n              }\n            },\n            \"required\": [\"stop\", \"date\", \"time\", \"track\", \"product\", \"reservation\"]\n          }\n        }\n      },\n      \"required\": [\"validFrom\", \"passengerName\", \"orderNumber\", \"stops\"]\n    },\n    \"usageNotes\": {\n      \"type\": \"string\"\n    }\n  },\n  \"required\": [\"ticketType\", \"departureDate\", \"priceType\", \"class\", \"adult\", \"journey\", \"refundPolicy\", \"payment\", \"bookingDetails\", \"journeyDetails\", \"usageNotes\"]\n}"
  },
  {
    "path": "examples/simple_ETLs.py",
    "content": "#note, you need to install dlt, langchain, and duckdb\n#pip install dlt\n#pip install langchain\n#pip install duckdb\n#pip install python-dotenv\n#pip install openai\n#you also need a .env file with your openai api key\n\nfrom langchain.chains.openai_functions import create_structured_output_chain\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.prompts import HumanMessagePromptTemplate, ChatPromptTemplate\nfrom langchain.schema import SystemMessage, HumanMessage\nimport os\nimport dlt\nfrom dotenv import load_dotenv\nload_dotenv()\n\nOPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\", \"\")\nllm = ChatOpenAI(\n            temperature=0.0,\n            max_tokens=1200,\n            openai_api_key=OPENAI_API_KEY,\n            model_name=\"gpt-4-0613\",\n        )\n@dlt.resource(name='output', write_disposition='replace')\ndef ai_function():\n    # Here we define the user prompt and the structure of the output we desire\n    prompt = \"I want to eat something very healthy and tasty.\"\n    json_schema = {\n        \"title\": \"Recipe name\",\n        \"description\": \"Recipe description\",\n        \"type\": \"object\",\n        \"properties\": {\n            \"ingredients\": {\"title\": \"Ingredients\", \"description\": \"Detailed ingredients\", \"type\": \"string\"},\n            \"steps\": {\"title\": \"Cooking steps\", \"description\": \"Detailed cooking steps\", \"type\": \"string\"}\n        },\n        \"required\": [\"ingredients\", \"steps\"],\n    }\n    prompt_msgs = [\n        SystemMessage(\n            content=\"You are a world class algorithm for creating recipes\"\n        ),\n        HumanMessage(content=\"Create a food recipe based on the following prompt:\"),\n        HumanMessagePromptTemplate.from_template(\"{input}\"),\n        HumanMessage(content=\"Tips: Make sure to answer in the correct format\"),\n    ]\n    prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n    chain = create_structured_output_chain(json_schema, prompt=prompt_, llm=llm, verbose=True)\n    output = chain.run(input = prompt, llm=llm)\n    yield output\n\n# Here we initialize DLT pipeline and export the data to duckdb\npipeline = dlt.pipeline(pipeline_name =\"recipe\", destination='duckdb',  dataset_name='recipe_data')\ninfo = pipeline.run(data =ai_function())\nprint(info)\n"
  },
  {
    "path": "extensions/__init__.py",
    "content": ""
  },
  {
    "path": "extensions/argparseext.py",
    "content": "import os\nimport sys\nimport argparse\n\n\n# Extract the env filenames in the -e flag only\n# Ignore any other arguments\ndef parse_dotenv_extensions(argv):\n    env_argv = []\n    if \"-e\" in argv:\n        tmp_argv = argv[argv.index(\"-e\") + 1 :]\n        parsed_args = []\n        for arg in tmp_argv:\n            if arg.startswith(\"-\"):\n                break\n            parsed_args.append(arg)\n        env_argv = [\"-e\"] + parsed_args\n\n    parser = argparse.ArgumentParser()\n    parser.add_argument(\n        \"-e\",\n        \"--env\",\n        nargs=\"+\",\n        help=\"\"\"\n    filenames for additional env variables to load\n    \"\"\",\n        default=os.getenv(\"DOTENV_EXTENSIONS\", \"\").split(\" \"),\n    )\n\n    return parser.parse_args(env_argv).env\n\n\ndef parse_arguments():\n    dotenv_extensions = parse_dotenv_extensions(sys.argv)\n    # Check if we need to load any additional env files\n    # This allows us to override the default .env file\n    # and update the default values for any command line arguments\n    if dotenv_extensions:\n        from extensions.dotenvext import load_dotenv_extensions\n\n        load_dotenv_extensions(parse_dotenv_extensions(sys.argv))\n\n    # Now parse the full command line arguments\n    parser = argparse.ArgumentParser(\n        add_help=False,\n    )\n    parser.add_argument(\n        \"objective\",\n        nargs=\"*\",\n        metavar=\"<objective>\",\n        help=\"\"\"\n    main objective description. Doesn\\'t need to be quoted.\n    if not specified, get objective from environment.\n    \"\"\",\n        default=[os.getenv(\"OBJECTIVE\", \"\")],\n    )\n    parser.add_argument(\n        \"-t\",\n        \"--task\",\n        metavar=\"<initial task>\",\n        help=\"\"\"\n    initial task description. must be quoted.\n    if not specified, get initial_task from environment.\n    \"\"\",\n        default=os.getenv(\"INITIAL_TASK\", os.getenv(\"FIRST_TASK\", \"\")),\n    )\n    group = parser.add_mutually_exclusive_group()\n    group.add_argument(\n        \"-4\",\n        \"--gpt-4\",\n        dest=\"openai_api_model\",\n        action=\"store_const\",\n        const=\"gpt-4\",\n        help=\"\"\"\n    use GPT-4 instead of the default model.\n    \"\"\",\n        default=os.getenv(\"OPENAI_API_MODEL\", \"gpt-3.5-turbo\"),\n    )\n    group.add_argument(\n        \"-l\",\n        \"--llama\",\n        dest=\"openai_api_model\",\n        action=\"store_const\",\n        const=\"llama\",\n        help=\"\"\"\n    use LLaMa instead of the default model. Requires llama.cpp.\n    \"\"\",\n    )\n    # This will parse -e again, which we want, because we need\n    # to load those in the main file later as well\n    parser.add_argument(\n        \"-e\",\n        \"--env\",\n        nargs=\"+\",\n        help=\"\"\"\n    filenames for additional env variables to load\n    \"\"\",\n        default=os.getenv(\"DOTENV_EXTENSIONS\", \"\").split(\" \"),\n    )\n    parser.add_argument(\n        \"-h\",\n        \"-?\",\n        \"--help\",\n        action=\"help\",\n        help=\"\"\"\n    show this help message and exit\n    \"\"\",\n    )\n\n    args = parser.parse_args()\n\n    openai_api_model = args.openai_api_model\n\n    dotenv_extensions = args.env\n\n    objective = \" \".join(args.objective).strip()\n    if not objective:\n        print(\n            \"\\033[91m\\033[1m\"\n            + \"No objective specified or found in environment.\\n\"\n            + \"\\033[0m\\033[0m\"\n        )\n        parser.print_help()\n        parser.exit()\n\n    initial_task = args.task\n    if not initial_task:\n        print(\n            \"\\033[91m\\033[1m\"\n            + \"No initial task specified or found in environment.\\n\"\n            + \"\\033[0m\\033[0m\"\n        )\n        parser.print_help()\n        parser.exit()\n\n    return objective, initial_task, openai_api_model, dotenv_extensions\n"
  },
  {
    "path": "extensions/dotenvext.py",
    "content": "from dotenv import load_dotenv\n\n\ndef load_dotenv_extensions(dotenv_files):\n    for dotenv_file in dotenv_files:\n        load_dotenv(dotenv_file)\n"
  },
  {
    "path": "fetch_secret.py",
    "content": "import os\nfrom dotenv import load_dotenv\nfrom api import start_api_server\n\n# API_ENABLED = os.environ.get(\"API_ENABLED\", \"False\").lower() == \"true\"\nimport boto3\n\nenvironment = os.getenv(\"AWS_ENV\", \"dev\")\n\n\n\ndef fetch_secret(secret_name, region_name, env_file_path):\n    session = boto3.session.Session()\n    client = session.client(service_name=\"secretsmanager\", region_name=region_name)\n\n    try:\n        response = client.get_secret_value(SecretId=secret_name)\n    except Exception as e:\n        print(f\"Error retrieving secret: {e}\")\n        return None\n\n    if \"SecretString\" in response:\n        secret = response[\"SecretString\"]\n    else:\n        secret = response[\"SecretBinary\"]\n\n    with open(env_file_path, \"w\") as env_file:\n        env_file.write(secret)\n\n    if os.path.exists(env_file_path):\n        print(f\"The .env file is located at: {os.path.abspath(env_file_path)}\")\n        load_dotenv()\n        PINECONE_API_KEY = os.getenv(\"PINECONE_API_KEY\", \"\")\n\n        print(\"LEN OF PINECONE_API_KEY\", len(PINECONE_API_KEY))\n    else:\n        print(\"The .env file was not found.\")\n    return \"Success in loading env files\"\n\n\nenv_file = \".env\"\nif os.path.exists(env_file):\n    # Load default environment variables (.env)\n    load_dotenv()\n    print(\"Talk to the AI!\")\n\n\nelse:\n    secrets = fetch_secret(\n        f\"promethai-{environment}-backend-secretso-promethaijs-dotenv\",\n        \"eu-west-1\",\n        \".env\",\n    )\n    if secrets:\n        print(secrets)\n    load_dotenv()\n\n\n# Check if \"dev\" is present in the task ARN\nif \"dev\" in environment:\n    # Fetch the secret\n    secrets = fetch_secret(\n        f\"promethai-dev-backend-secretso-promethaijs-dotenv\",\n        \"eu-west-1\",\n        \".env\",\n    )\n    load_dotenv()\nelif \"prd\" in environment:\n    # Fetch the secret\n    secrets = fetch_secret(\n        f\"promethai-prd-backend-secretso-promethaijs-dotenv\",\n        \"eu-west-1\",\n        \".env\",\n    )\n    load_dotenv()\n"
  },
  {
    "path": "fixtures/choose_meal_tree_response.json",
    "content": "{\n     \"prompt\": \"I’d like a quick veggie meal under $25 near me. No peanuts, I’m allergic.\",\n     \"tree\": [\n          {\n               \"category\": \"price\",\n               \"options\": [\n                    {\n                         \"category\": \"under $25\",\n                         \"options\": [\n                              {\n                                   \"category\": \"$10\"\n                              },\n                              {\n                                   \"category\": \"$15\"\n                              },\n                              {\n                                   \"category\": \"$20\"\n                              }\n                         ],\n                         \"preference\": []\n                    },\n                    {\n                         \"category\": \"over $25\",\n                         \"options\": [\n                              {\n                                   \"category\": \"$30\"\n                              },\n                              {\n                                   \"category\": \"$35\"\n                              },\n                              {\n                                   \"category\": \"$40\"\n                              }\n                         ],\n                         \"preference\": []\n                    }\n               ],\n               \"preference\": [\n                    \"under $25\"\n               ]\n          },\n          {\n               \"category\": \"location\",\n               \"options\": [\n                    {\n                         \"category\": \"near me\",\n                         \"options\": [\n                              {\n                                   \"category\": \"1 mile\"\n                              },\n                              {\n                                   \"category\": \"5 miles\"\n                              },\n                              {\n                                   \"category\": \"10 miles\"\n                              }\n                         ],\n                         \"preference\": []\n                    },\n                    {\n                         \"category\": \"far away\",\n                         \"options\": [\n                              {\n                                   \"category\": \"20 miles\"\n                              },\n                              {\n                                   \"category\": \"50 miles\"\n                              },\n                              {\n                                   \"category\": \"100 miles\"\n                              }\n                         ],\n                         \"preference\": []\n                    }\n               ],\n               \"preference\": [\n                    \"near me\"\n               ]\n          },\n          {\n               \"category\": \"diet\",\n               \"options\": [\n                    {\n                         \"category\": \"veggie\",\n                         \"options\": [\n                              {\n                                   \"category\": \"vegan\"\n                              },\n                              {\n                                   \"category\": \"vegetarian\"\n                              },\n                              {\n                                   \"category\": \"plant-based\"\n                              }\n                         ],\n                         \"preference\": []\n                    },\n                    {\n                         \"category\": \"non-veggie\",\n                         \"options\": [\n                              {\n                                   \"category\": \"meat\"\n                              },\n                              {\n                                   \"category\": \"dairy\"\n                              },\n                              {\n                                   \"category\": \"seafood\"\n                              }\n                         ],\n                         \"preference\": []\n                    }\n               ],\n               \"preference\": [\n                    \"veggie\"\n               ]\n          },\n          {\n               \"category\": \"allergies\",\n               \"options\": [\n                    {\n                         \"category\": \"peanuts\"\n                    },\n                    {\n                         \"category\": \"berries\",\n                         \"options\": [\n                              {\n                                   \"category\": \"cranberry\"\n                              },\n                              {\n                                   \"category\": \"blackberry\"\n                              },\n                              {\n                                   \"category\": \"blueberry\"\n                              }\n                         ]\n                    }\n               ],\n               \"preference\": [\n                    \"peanuts\"\n               ]\n          }\n     ]\n}"
  },
  {
    "path": "fixtures/goal_response.json",
    "content": "{\n    \"goals\": [\n        \"Cuisine\",\n        \"Healthy\",\n        \"Budget\",\n        \"Taste\"\n    ]\n}"
  },
  {
    "path": "fixtures/recipe_response.json",
    "content": "{\n    \"recipes\": [\n        {\n            \"title\": \"Vegetable Stir Fry\",\n            \"rating\": 90,\n            \"prep_time\": 15,\n            \"cook_time\": 20,\n            \"description\": \"A delicious and healthy vegetable stir fry\",\n            \"ingredients\": [\n                \"1 onion\",\n                \"2 cloves garlic\",\n                \"1 red pepper\",\n                \"1 green pepper\",\n                \"1 cup mushrooms\",\n                \"1 cup broccoli\",\n                \"1 tablespoon olive oil\",\n                \"1 tablespoon soy sauce\",\n                \"1 teaspoon sesame oil\",\n                \"Salt and pepper to taste\"\n            ],\n            \"instructions\": [\n                \"Chop the onion, garlic, red pepper, green pepper, mushrooms, and broccoli.\",\n                \"Heat the olive oil in a large skillet over medium-high heat.\",\n                \"Add the onion, garlic, red pepper, green pepper, mushrooms, and broccoli to the skillet and cook for 5 minutes, stirring occasionally.\",\n                \"Add the soy sauce, sesame oil, salt, and pepper and cook for an additional 5 minutes, stirring occasionally.\",\n                \"Serve hot.\"\n            ]\n        },\n        {\n            \"title\": \"Veggie Burger\",\n            \"rating\": 95,\n            \"prep_time\": 10,\n            \"cook_time\": 15,\n            \"description\": \"A delicious and healthy veggie burger\",\n            \"ingredients\": [\n                \"1/2 cup cooked quinoa\",\n                \"1/2 cup cooked black beans\",\n                \"1/4 cup diced onion\",\n                \"1/4 cup diced bell pepper\",\n                \"1/4 cup diced mushrooms\",\n                \"1/4 cup breadcrumbs\",\n                \"1 tablespoon olive oil\",\n                \"1 teaspoon garlic powder\",\n                \"1 teaspoon cumin\",\n                \"1 teaspoon chili powder\",\n                \"Salt and pepper to taste\"\n            ],\n            \"instructions\": [\n                \"In a large bowl, combine the quinoa, black beans, onion, bell pepper, mushrooms, breadcrumbs, olive oil, garlic powder, cumin, chili powder, salt, and pepper.\",\n                \"Form the mixture into 4 patties.\",\n                \"Heat a large skillet over medium-high heat and add the patties.\",\n                \"Cook for 5 minutes on each side, or until golden brown and cooked through.\",\n                \"Serve hot.\"\n            ]\n        }\n    ]\n}"
  },
  {
    "path": "fixtures/subgoal_response.json",
    "content": "{\n  \"sub_goals\": [\n    {\n      \"goal_name\": \"Budget\",\n      \"sub_goals\": [\n        {\n          \"name\": \"Cheap\",\n          \"amount\": 80\n        },\n        {\n          \"name\": \"Moderate\",\n          \"amount\": 20\n        },\n        {\n          \"name\": \"Expensive\",\n          \"amount\": 0\n        },\n        {\n          \"name\": \"Splurge\",\n          \"amount\": 0\n        }\n      ]\n    },\n    {\n      \"goal_name\": \"Cuisine\",\n      \"sub_goals\": [\n        {\n          \"name\": \"Italian\",\n          \"amount\": 50\n        },\n        {\n          \"name\": \"Mexican\",\n          \"amount\": 30\n        },\n        {\n          \"name\": \"Chinese\",\n          \"amount\": 20\n        },\n        {\n          \"name\": \"Indian\",\n          \"amount\": 0\n        }\n      ]\n    },\n    {\n      \"goal_name\": \"Healthy\",\n      \"sub_goals\": [\n        {\n          \"name\": \"Low-Calorie\",\n          \"amount\": 50\n        },\n        {\n          \"name\": \"Low-Carb\",\n          \"amount\": 30\n        },\n        {\n          \"name\": \"Low-Fat\",\n          \"amount\": 20\n        },\n        {\n          \"name\": \"Vegetarian\",\n          \"amount\": 0\n        }\n      ]\n    },\n    {\n      \"goal_name\": \"Taste\",\n      \"sub_goals\": [\n        {\n          \"name\": \"Spicy\",\n          \"amount\": 50\n        },\n        {\n          \"name\": \"Salty\",\n          \"amount\": 30\n        },\n        {\n          \"name\": \"Sweet\",\n          \"amount\": 20\n        },\n        {\n          \"name\": \"Sour\",\n          \"amount\": 0\n        }\n      ]\n    }\n  ]\n}"
  },
  {
    "path": "fixtures/update_meal_tree_response.json",
    "content": "\"{'prompt': 'I would like a quick veggie meal under 25$ near me.', 'tree': [{'category': 'price', 'options': [{'category': 'under 25$', 'options': [{'category': 'under 10$'}, {'category': '10-15$'}, {'category': '15-20$'}, {'category': '20-25$'}], 'preference': []}, {'category': 'over 25$', 'options': [{'category': '25-30$'}, {'category': '30-35$'}, {'category': '35-40$'}, {'category': 'over 40$'}], 'preference': []}], 'preference': ['under 25$']}, {'category': 'location', 'options': [{'category': 'near me', 'options': [{'category': 'walking distance'}, {'category': 'driving distance'}, {'category': 'public transport'}], 'preference': []}, {'category': 'far away', 'options': [{'category': '1 hour away'}, {'category': '2 hours away'}, {'category': '3 hours away'}], 'preference': []}], 'preference': ['near me']}, {'category': 'type', 'options': [{'category': 'veggie', 'options': [{'category': 'vegan'}, {'category': 'vegetarian'}, {'category': 'plant-based'}], 'preference': []}, {'category': 'non-veggie', 'options': [{'category': 'meat'}, {'category': 'fish'}, {'category': 'dairy'}], 'preference': []}], 'preference': ['veggie']}, {'category': 'time', 'options': [{'category': 'quick', 'options': [{'category': '1 min'}, {'category': '10 mins'}, {'category': '30 mins'}], 'preference': []}, {'category': 'slow', 'options': [{'category': '60 mins'}, {'category': '120 mins'}, {'category': '180 mins'}], 'preference': []}], 'preference': ['quick']}]}\""
  },
  {
    "path": "food_scrapers/wolt_tool.py",
    "content": "from playwright.async_api import async_playwright, Playwright\n\n\nasync def find_and_click_by_attributes(page, attributes):\n    selector = \"button\"\n    for attr, value in attributes.items():\n        selector += f'[{attr}=\"{value}\"]'\n    element = page.locator(selector)\n    await element.click()\n\n\nasync def enter_zipcode_and_press_enter(page, zipcode):\n    input_selector = 'input[data-test-id=\"FrontpageAddressQueryInput\"]'\n    element = page.locator(input_selector)\n    await element.fill(zipcode)\n    await element.press(\"Enter\")\n\n\nasync def run(playwright, zipcode: str, prompt: str):\n    browser = await playwright.chromium.launch(headless=True)\n    context = await browser.new_context()\n    page = await context.new_page()\n\n    # Navigate to wolt.com\n    await page.goto(\"https://wolt.com\")\n    button_attributes = {\n        \"aria-disabled\": \"false\",\n        \"role\": \"button\",\n        \"type\": \"button\",\n        \"data-localization-key\": \"gdpr-consents.banner.accept-button\",\n    }\n    await find_and_click_by_attributes(page, button_attributes)\n\n    await enter_zipcode_and_press_enter(page, zipcode)\n    await page.wait_for_load_state(\"networkidle\")\n    await page.press('input[data-test-id=\"FrontpageAddressQueryInput\"]', \"Enter\")\n    await page.wait_for_load_state(\"networkidle\")\n    await page.wait_for_selector('[data-test-id=\"VenuesOnlySearchInput\"]')\n    await page.wait_for_load_state(\"networkidle\")\n    search_input_selector = '[data-test-id=\"VenuesOnlySearchInput\"]'\n    await page.wait_for_load_state(\"networkidle\")\n    element = page.locator(search_input_selector)\n    await element.fill(prompt)\n    await page.press('input[data-test-id=\"VenuesOnlySearchInput\"]', \"Enter\")\n    await page.wait_for_load_state(\"networkidle\")\n\n    resulting_url = page.url\n    await browser.close()\n\n    return resulting_url\n\n\nasync def main(prompt: str, zipcode: str):\n    async with async_playwright() as playwright:\n        result = await run(playwright, zipcode=zipcode, prompt=prompt)\n        print(result)\n        return result\n\n\nimport asyncio\n\n# asyncio.run(main(prompt=\"pizza\", zipcode=\"10005\"))\n"
  },
  {
    "path": "heuristic_experience_orchestrator/README.md",
    "content": "# Heuristic Orchestration Chain\n\nThe chain is meant to operate various agents that have a predetermined set of goals they can change based on their operation, and information gathered about the user and his experiences\n\n## HOC\n\nHOC or heuristic orchestration chain has as a goal to implement a goal given, by choosing one of the various methods available and then optimise the goal itself after the result is produced and assesed\n\nThis type of a system requires: \nBased on Newell and Simon (1958) - Report on a general problem-solving program\n\n1. Problem Identification\n    Methods: \n    Decomposition\n    Analogies\n    Root cause analysis\n    Goal clarification\n    Constraint identification\n    SWOT analysis\n    Expert consultation\n    Visualization\n2. Problem Definition\n3. Strategy selection\n4. Information collection\n5. Resource distribution\n6. Process monitoring\n7. Solution evaluation\n\n`objective` (mandatory) - The overarching objective you want the task orchestration system to converge to\n`first_task` (optional) - The prompt it gets for its \"first task\", which is usually some form of creating a task list. The default is \"Make a todo list\".\n\nThe `from_llm` method that constructs the chain takes in the following arguments that may be of interest:\n\n`llm` - The LLM model you want to the chain to use. Note: Using a model like GPT-4 add up costs extremely quickly. Use with caution.\n`vectorstore` - The vectorstore you want the chain to use\n`max_iterations` - The maximum number of iterations, i.e. number of tasks that BabyAGI will output a result for and iterate on. If this number is not provided, the chain WILL run forever. "
  },
  {
    "path": "heuristic_experience_orchestrator/task_identification.py",
    "content": "from langchain import LLMChain, PromptTemplate\nfrom langchain.llms import BaseLLM\n\n\nclass TaskIdentificationChain(LLMChain):\n    \"\"\"Chain to generate tasks.\"\"\"\n\n    @classmethod\n    def from_llm(\n        cls, llm: BaseLLM, verbose: bool = True, value: str = None\n    ) -> LLMChain:\n        \"\"\"Get the response parser.\"\"\"\n\n        def get_template_by_value(self, value):\n            if value == \"Decomposition\":\n                template = \"\"\" Hey ChatGPT, I need your help in decomposing the following task into a series of manageable steps for the purpose of task identification based on \n                    Newell and Simon paper. Return the result as a json with the result type 'Identification' and 'Value': 'Decomposition'  : {task_description}\"\"\"\n            elif value == \"Analogy\":\n                template = \"\"\" Hey ChatGPT, I need your help in creating an analogy for the purpose of task identification based on \n                    Newell and Simon paper. Return the result as a json with the result type 'Identification' and 'Value': 'Analogy'  : {task_description}\"\"\"\n\n            elif value == \"Template\":\n                template = \"Template B content\"\n\n            elif value == \"Templatetest\":\n                template = \"Template B content\"\n            else:\n                template = \" Return the tasks as an array.\"\n            return template\n\n        if value:\n            task_creation_template = get_template_by_value(value)\n        else:\n            task_creation_template = \"Default template content\"\n\n        prompt = PromptTemplate(\n            template=task_creation_template,\n            input_variables=[\"task_description\"],\n        )\n\n        return cls(prompt=prompt, llm=llm, verbose=verbose)\n"
  },
  {
    "path": "initdb/init.sql",
    "content": "CREATE TABLE pinecone_id (\n  id SERIAL PRIMARY KEY,\n  user_id INTEGER NOT NULL\n);"
  },
  {
    "path": "llm_chains/__init__.py",
    "content": ""
  },
  {
    "path": "llm_chains/chains.py",
    "content": "from langchain.document_loaders import PyPDFLoader\n\n\nimport pinecone\nfrom datetime import datetime, timedelta\nfrom typing import List, Optional, Tuple, Dict\nfrom langchain.agents import initialize_agent\nfrom langchain.tools import  tool\nfrom langchain.vectorstores import Pinecone\nfrom langchain.embeddings.openai import OpenAIEmbeddings\nimport openai\nfrom pydantic import BaseModel, Field,  parse_obj_as\nimport re\nfrom jinja2 import Template\nfrom dotenv import load_dotenv\nfrom langchain import LLMChain\nfrom langchain.schema import Document\nfrom langchain.chains import SimpleSequentialChain\nfrom langchain.chains.openai_functions import (\n    create_openai_fn_chain, create_structured_output_chain\n)\nfrom langchain.schema import HumanMessage, SystemMessage\nimport os\nimport fastjsonschema\n\nimport json\nfrom langchain.tools import GooglePlacesTool\nimport tiktoken\nimport asyncio\nimport logging\nfrom langchain.chat_models import ChatOpenAI\nfrom langchain.agents.agent_toolkits import ZapierToolkit\nfrom langchain.agents import AgentType\nfrom langchain.utilities.zapier import ZapierNLAWrapper\nfrom langchain.prompts import PromptTemplate, ChatPromptTemplate, HumanMessagePromptTemplate\nfrom typing import Optional\n\n# redis imports for cache\nimport langchain\nfrom langchain.callbacks import get_openai_callback\n\nload_dotenv()\nOPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\", \"\")\nfrom langchain.llms import Replicate\nfrom redis import Redis\nfrom langchain.cache import RedisCache\nimport os\n\n\n\nlogging.basicConfig(level=logging.INFO)\n# from langchain import llm_cache\n\n\n# langchain.llm_cache = RedisCache(redis_=Redis(host=\"redis\", port=6379, db=0))\n# logging.info(\"Using redis cache\")\n\n\nif os.getenv(\"AWS_ENV\", \"\") == \"dev\":\n    REDIS_HOST = os.getenv(\n        \"REDIS_HOST\",\n        \"promethai-dev-backend-redis-repl-gr.60qtmk.ng.0001.euw1.cache.amazonaws.com\",\n    )\n    langchain.llm_cache = RedisCache(\n        redis_=Redis(host=\"promethai-dev-backend-redis-repl-gr.60qtmk.ng.0001.euw1.cache.amazonaws.com\", port=6379,\n                     db=0))\n    logging.info(\"Using redis cache for DEV\")\nelif os.getenv(\"AWS_ENV\", \"\") == \"prd\":\n    REDIS_HOST = os.getenv(\n        \"REDIS_HOST\",\n        \"promethai-prd-backend-redis-repl-gr.60qtmk.ng.0001.euw1.cache.amazonaws.com\",\n    )\n    langchain.llm_cache = RedisCache(\n        redis_=Redis(host=\"promethai-prd-backend-redis-repl-gr.60qtmk.ng.0001.euw1.cache.amazonaws.com\", port=6379,\n                     db=0))\n    logging.info(\"Using redis cache for PRD\")\nelse:\n    pass\n\n\nclass Agent:\n    load_dotenv()\n    OPENAI_MODEL = os.getenv(\"OPENAI_MODEL\") or \"gpt-4\"\n    GPLACES_API_KEY = os.getenv(\"GPLACES_API_KEY\", \"\")\n    ZAPIER_NLA_API_KEY = os.environ[\"ZAPIER_NLA_API_KEY\"] = os.environ.get(\n        \"ZAPIER_NLA_API_KEY\", \"\"\n    )\n    OPENAI_TEMPERATURE = float(os.getenv(\"OPENAI_TEMPERATURE\", 0.0))\n    OPENAI_API_KEY = os.getenv(\"OPENAI_API_KEY\", \"\")\n    PINECONE_API_KEY = os.getenv(\"PINECONE_API_KEY\", \"\")\n    PINECONE_API_ENV = os.getenv(\"PINECONE_API_ENV\", \"\")\n    REPLICATE_API_TOKEN = os.getenv(\"REPLICATE_API_TOKEN\", \"\")\n\n    def __init__(\n            self,\n            table_name=None,\n            user_id: Optional[str] = \"676\",\n            session_id: Optional[str] = None,\n    ) -> None:\n        self.table_name = table_name\n        self.user_id = user_id\n        self.session_id = session_id\n        # self.memory = None\n        self.thought_id_timestamp = datetime.now().strftime(\"%Y%m%d%H%M%S%f\")[\n                                    :-3\n                                    ]  # Timestamp with millisecond precision\n        self.last_message = \"\"\n        self.openai_model35 = \"gpt-3.5-turbo-16k-0613\"\n        self.openai_model4 = \"gpt-4-0613\"\n        self.llm = ChatOpenAI(\n            temperature=0.0,\n            max_tokens=1500,\n            openai_api_key=self.OPENAI_API_KEY,\n            model_name=self.openai_model35,\n            cache=False,\n        )\n        self.llm35_fast = ChatOpenAI(\n            temperature=0.2,\n            max_tokens=550,\n            openai_api_key=self.OPENAI_API_KEY,\n            model_name=self.openai_model35,\n            cache=False,\n        )\n        self.llm_fast = ChatOpenAI(\n            temperature=0.0,\n            max_tokens=700,\n            openai_api_key=self.OPENAI_API_KEY,\n            model_name=self.openai_model4,\n            cache=False,\n        )\n        self.llm35 = ChatOpenAI(\n            temperature=0.0,\n            max_tokens=1200,\n            openai_api_key=self.OPENAI_API_KEY,\n            model_name=self.openai_model35,\n            cache=False,\n        )\n        # self.llm = ChatOpenAI(temperature=0.0,max_tokens = 1500, openai_api_key = self.OPENAI_API_KEY, model_name=\"gpt-4\")\n        self.replicate_llm = Replicate(\n            model=\"replicate/vicuna-13b:a68b84083b703ab3d5fbf31b6e25f16be2988e4c3e21fe79c2ff1c18b99e61c1\",\n            api_token=self.REPLICATE_API_TOKEN,\n        )\n        self.verbose: bool = True\n        self.openai_temperature = 0.0\n        self.index = \"my-agent\"\n\n    def clear_cache(self):\n        langchain.llm_cache.clear()\n\n    def set_user_session(self, user_id: str, session_id: str) -> None:\n        self.user_id = user_id\n        self.session_id = session_id\n\n    def get_ada_embedding(self, text):\n        text = text.replace(\"\\n\", \" \")\n        return openai.Embedding.create(\n            input=[text], model=\"text-embedding-ada-002\", api_key=OPENAI_API_KEY\n        )[\"data\"][0][\"embedding\"]\n\n    def init_pinecone(self, index_name):\n        load_dotenv()\n        PINECONE_API_KEY = os.getenv(\"PINECONE_API_KEY\", \"\")\n        PINECONE_API_ENV = os.getenv(\"PINECONE_API_ENV\", \"\")\n        pinecone.init(api_key=PINECONE_API_KEY, environment=PINECONE_API_ENV)\n        return pinecone.Index(index_name)\n\n    def _simple_test(self):\n        # langchain.llm_cache = RedisCache(redis_=Redis(host='0.0.0.0', port=6379, db=0))\n        with get_openai_callback() as cb:\n            # langchain.llm_cache = RedisCache(redis_=Redis(host='0.0.0.0', port=6379, db=0))\n            prompt = \"\"\" How long does it take to go to the moon on foot \"\"\"\n            prompt = PromptTemplate.from_template(prompt)\n            chain = LLMChain(llm=self.llm, prompt=prompt, verbose=self.verbose)\n            chain_result = chain.run(prompt=prompt, name=self.user_id).strip()\n            print(cb)\n\n            return chain_result\n\n    # create the length function\n    def tiktoken_len(self, text):\n        tokenizer = tiktoken.get_encoding(\"cl100k_base\")\n        tokens = tokenizer.encode(text, disallowed_special=())\n        return len(tokens)\n\n    # class VectorDBInput(BaseModel):\n    #     observation: str = Field(description=\"should be what we are inserting into the memory\")\n    #     namespace: str = Field(description=\"should be the namespace of the VectorDB\")\n    # @tool(\"_update_memories\", return_direct=True, args_schema = VectorDBInput)\n\n    # def insert_documents(self, documents, namespace):\n    #     from datetime import datetime\n    #\n    #     retriever = vectorstore.as_retriever()\n    #     retriever.add_documents(\n    #         [\n    #             Document(\n    #                 page_content=observation,\n    #                 metadata={\n    #                     \"inserted_at\": datetime.now(),\n    #                     \"text\": observation,\n    #                     \"user_id\": self.user_id,\n    #                 },\n    #                 namespace=namespace,\n    #             )\n    #         ]\n    #     )\n    def _update_memories(self, observation: str, namespace: str, page: str = \"\", source: str = \"\") -> None:\n        \"\"\"Update related characteristics, preferences or dislikes for a user.\"\"\"\n        from langchain.text_splitter import RecursiveCharacterTextSplitter\n\n        self.init_pinecone(index_name=self.index)\n        vectorstore: Pinecone = Pinecone.from_existing_index(\n            index_name=self.index, embedding=OpenAIEmbeddings(), namespace=namespace\n        )\n        from datetime import datetime\n\n        retriever = vectorstore.as_retriever()\n        retriever.add_documents(\n            [\n                Document(\n                    page_content=observation,\n                    metadata={\n                        \"inserted_at\": datetime.now(),\n                        \"text\": observation,\n                        \"user_id\": self.user_id,\n                        \"page\": page,\n                        \"source\": source,\n                    },\n                    namespace=namespace,\n                )\n            ]\n        )\n\n    class FetchMemories(BaseModel):\n        observation: str = Field(\n            description=\"observation we want to fetch from vectordb\"\n        )\n\n    def _fetch_memories(self, observation: str, namespace: str) -> dict[str, str] | str:\n        \"\"\"Fetch related characteristics, preferences or dislikes for a user.\"\"\"\n\n        self.init_pinecone(index_name=self.index)\n        vectorstore: Pinecone = Pinecone.from_existing_index(\n            index_name=self.index, embedding=OpenAIEmbeddings(), namespace=namespace\n        )\n        retriever = vectorstore.as_retriever()\n        retriever.search_kwargs = {\"filter\": {\"user_id\": {\"$eq\": self.user_id}}}\n        answer_response = retriever.get_relevant_documents(observation)\n\n        answer_response.sort(\n            key=lambda doc: doc.metadata.get(\"inserted_at\")\n            if \"inserted_at\" in doc.metadata\n            else datetime.min,\n            reverse=True,\n        )\n        try:\n            answer_response = answer_response[0]\n        except IndexError:\n            return {\n                \"error\": \"No document found for this user. Make sure that a query is appropriate\"\n            }\n        return answer_response.page_content\n\n    def _compute_agent_summary(self, model_speed: str):\n        \"\"\"Computes summary for a person\"\"\"\n        prompt = PromptTemplate.from_template(\n            \"How would you summarize {name}'s core characteristics given the\"\n            + \" following statements:\\n\"\n            + \"{relevant_preferences}\"\n            + \"{relevant_dislikes}\"\n            + \"Do not embellish.\"\n            + \"\\n\\nSummary: \"\n        )\n        print(\"Computing Agent Summary\")\n        self.init_pinecone(index_name=self.index)\n        # The agent seeks to think about their core characteristics.\n\n        relevant_preferences = self._fetch_memories(\n            f\"Users core preferences\", namespace=\"PREFERENCES\"\n        )\n        relevant_dislikes = self._fetch_memories(\n            f\"Users core dislikes\", namespace=\"PREFERENCES\"\n        )\n        print(relevant_dislikes)\n        print(relevant_preferences)\n\n        if model_speed == \"fast\":\n            output = self.replicate_llm(prompt)\n            return output\n\n        else:\n            chain = LLMChain(llm=self.llm, prompt=prompt, verbose=self.verbose)\n            chain_results = chain.run(\n                name=self.user_id,\n                relevant_preferences=relevant_preferences,\n                relevant_dislikes=relevant_dislikes,\n            ).strip()\n            print(chain_results)\n            return chain_results\n\n    def update_agent_preferences(self, preferences: str):\n        \"\"\"Serves to update agents preferences so that they can be used in summary\"\"\"\n\n        prompt = \"\"\" The {name} has following {past_preference} and the new {preferences}\n                Update user preferences and return a list of preferences\n            Do not embellish.\n            Summary: \"\"\"\n        self.init_pinecone(index_name=self.index)\n        past_preference = self._fetch_memories(\n            f\"Users core preferences\", namespace=\"PREFERENCE\"\n        )\n        prompt = PromptTemplate(\n            input_variables=[\"name\", \"past_preference\", \"preferences\"], template=prompt\n        )\n\n        # prompt = prompt.format(name=self.user_id, past_preference= past_preference, preferences=preferences)\n        chain = LLMChain(llm=self.llm, prompt=prompt, verbose=self.verbose)\n        chain_result = chain.run(\n            prompt=prompt,\n            past_preference=past_preference,\n            preferences=preferences,\n            name=self.user_id,\n        ).strip()\n        print(chain_result)\n        return self._update_memories(chain_result, namespace=\"PREFERENCES\")\n\n    def update_agent_taboos(self, dislikes: str):\n        \"\"\"Serves to update agents taboos so that they can be used in summary\"\"\"\n        prompt = \"\"\" The {name} has following {past_dislikes} and the new {dislikes}\n                Update user taboos and return a list of dislikes\n            Do not embellish.\n            Summary: \"\"\"\n        self.init_pinecone(index_name=self.index)\n        past_dislikes = self._fetch_memories(\n            f\"Users core dislikes\", namespace=\"PREFERENCES\"\n        )\n        prompt = PromptTemplate(\n            input_variables=[\"name\", \"past_dislikes\", \"dislikes\"], template=prompt\n        )\n        # prompt = prompt.format(name=self.user_id, past_dislikes= past_dislikes, dislikes=dislikes)\n        chain = LLMChain(llm=self.llm, prompt=prompt, verbose=self.verbose)\n        chain_result = chain.run(\n            prompt=prompt,\n            name=self.user_id,\n            past_dislikes=past_dislikes,\n            dislikes=dislikes,\n        ).strip()\n        return self._update_memories(chain_result, namespace=\"PREFERENCES\")\n\n    def update_agent_traits(self, traits: str):\n        \"\"\"Serves to update agent traits so that they can be used in summary\"\"\"\n        prompt = \"\"\" The {name} has following {past_traits} and the new {traits}\n                Update user traits and return a list of traits\n            Do not embellish.\n            Summary: \"\"\"\n        self.init_pinecone(index_name=self.index)\n\n        past_traits = self._fetch_memories(\n            f\"Users core dislikes\", namespace=\"PREFERENCES\"\n        )\n        prompt = PromptTemplate(\n            input_variables=[\"name\", \"past_traits\", \"traits\"], template=prompt\n        )\n        chain = LLMChain(llm=self.llm, prompt=prompt, verbose=self.verbose)\n        chain_result = chain.run(\n            prompt=prompt, past_traits=past_traits, traits=traits, name=self.user_id\n        ).strip()\n        return self._update_memories(chain_result, namespace=\"PREFERENCES\")\n\n    def update_agent_summary(self, model_speed):\n        \"\"\"Serves to update agent traits so that they can be used in summary\"\"\"\n        summary = self._compute_agent_summary(model_speed=model_speed)\n        return self._update_memories(summary, namespace=\"SUMMARY\")\n\n    def prompt_correction(self, prompt_source: str, model_speed: str):\n        \"\"\"Makes the prompt gramatically correct\"\"\"\n\n        prompt = \"\"\" Gramatically and logically correct sentence: {{prompt_source}} . Return only the corrected sentence, no abbreviations, using same words if it is logical. Do not mention explicitly rules given in prompt. \"\"\"\n        template = Template(prompt)\n        output = template.render(prompt_source=prompt_source)\n        complete_query = PromptTemplate.from_template(output)\n\n        chain = LLMChain(\n            llm=self.llm, prompt=complete_query, verbose=self.verbose\n        )\n        chain_result = chain.run(prompt=complete_query, name=self.user_id).strip()\n        json_data = json.dumps(chain_result)\n        return json_data\n\n    async def solution_generation(self, prompt: str, prompt_template: str = None, json_example: str = None,\n                                  model_speed: str = None):\n        \"\"\"Generates a recipe solution in json\"\"\"\n\n        if prompt_template is None:\n            prompt_base = \"\"\" Create a food recipe based on the following prompt: '{{prompt}}'. Instructions and ingredients should have medium detail.\n                Answer a condensed valid JSON in this format: {{ json_example}}  Do not explain or write anything else.\"\"\"\n        else:\n            prompt_base = prompt_template\n\n        if json_example is None:\n            json_example = \"\"\"{\"recipes\":[{\"title\":\"value\",\"rating\":\"value\",\"prep_time\":\"value\",\"cook_time\":\"value\",\"description\":\"value\",\"ingredients\":[\"value\"],\"instructions\":[\"value\"]}]}\"\"\"\n        else:\n            json_example = json_example\n\n        # json_example = str(json_example).replace(\"{\", \"{{\").replace(\"}\", \"}}\")\n        # template = Template(prompt_base)\n        # output = template.render(prompt=prompt\n        #                          , json_example=json_example)\n        # complete_query = output\n        # complete_query = PromptTemplate.from_template(complete_query)\n\n        # Define the response schema\n        class Recipe(BaseModel):\n            \"\"\"Schema for an individual recipe.\"\"\"\n            title: str = Field(..., description=\"Title of the recipe\")\n            rating: str = Field(None, description=\"Recipe rating\")\n            prep_time: str = Field(None, description=\"Time to prepare recipe\")\n            cook_time: str = Field(None, description=\"Time to cook recipe\")\n            description: str = Field(None, description=\"Description of recipe\")\n            ingredients: List[str] = Field(None, description=\"All recipe ingredients\")\n            instructions: List[str] = Field(None, description=\"All recipe instructions for making a recipe\")\n\n        class RecordRecipe(BaseModel):\n            \"\"\"Schema for the record containing a list of recipes.\"\"\"\n            recipes: List[Recipe] = Field(..., description=\"List of recipes\")\n\n        prompt_msgs = [\n            SystemMessage(\n                content=\"You are a world class algorithm for creating recipes\"\n            ),\n            HumanMessage(content=\"Create a food recipe based on the following prompt:\"),\n            HumanMessagePromptTemplate.from_template(\"{input}\"),\n            HumanMessage(content=\"Tips: Make sure to answer in the correct format\"),\n        ]\n        prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n        chain = create_structured_output_chain(RecordRecipe, self.llm35, prompt_, verbose=True)\n        from langchain.callbacks import get_openai_callback\n        with get_openai_callback() as cb:\n            output = await chain.arun(input=prompt)\n            print(cb)\n        # output = json.dumps(output)\n        my_object = parse_obj_as(RecordRecipe, output)\n        return my_object.dict()\n\n\n\n    async def solution_name_generation(self, prompt: str, prompt_template: str = None, json_example: str = None,\n                                       model_speed: str = None):\n        \"\"\"Generates a single recipe solution and returns the recipe title as a string.\"\"\"\n\n        prompt_ = \"\"\"Create a food recipe based on the following prompt: {{prompt}} Return just a concise recipe title. Do not explain or write anything else.\"\"\"\n\n        template = Template(prompt_)\n        output = template.render(prompt=prompt)\n        complete_query = PromptTemplate.from_template(output)\n\n        chain = LLMChain(\n            llm=self.llm35_fast, prompt=complete_query, verbose=self.verbose\n        )\n        chain_result = await chain.arun(prompt=complete_query, name=self.user_id)\n        logging.info(\"Here is the chain result \",chain_result)\n        # json_data = json.dumps(chain_result)\n        return str(chain_result)\n\n        # if model_speed == \"fast\":\n        #     output = self.replicate_llm(output)\n        #     return output\n        # else:\n        #     chain = LLMChain(\n        #         llm=self.llm, prompt=complete_query, verbose=self.verbose\n        #     )\n        #     chain_result = chain.run(prompt=complete_query, name=self.user_id).strip()\n        #     #\n        #     # vectorstore: Pinecone = Pinecone.from_existing_index(\n        #     #     index_name=self.index,\n        #     #     embedding=OpenAIEmbeddings(),\n        #     #     namespace='RESULT'\n        #     # )\n        #     # from datetime import datetime\n        #     # retriever = vectorstore.as_retriever()\n        #     # retriever.add_documents([Document(page_content=chain_result,\n        #     #                                   metadata={'inserted_at': datetime.now(), \"text\": chain_result,\n        #     #                                             'user_id': self.user_id}, namespace=\"RESULT\")])\n        #     logging.info(\"HERE IS THE CHAIN RESULT\", chain_result)\n        #     return chain_result\n\n    def extract_json(self, data):\n        json_start = data.find(\"{\")\n        json_end = data.rfind(\"}\") + 1\n        json_data = data[json_start:json_end]\n        try:\n            return json.loads(json_data)  # if successful, return Python dict\n        except json.JSONDecodeError:\n            return None  # if unsuccessful, return None\n\n    async def async_generate(\n            self,\n            prompt_template_base,\n            base_category,\n            base_value,\n            list_of_items,\n            assistant_category,\n    ):\n        \"\"\"Generates an individual solution choice\"\"\"\n        json_example = \"\"\" {\"category\":\"time\",\"options\":[{\"category\":\"quick\",\"options\":[{\"category\":\"1 min\"},{\"category\":\"10 mins\"},{\"category\":\"30 mins\"}]},{\"category\":\"slow\",\"options\":[{\"category\":\"60 mins\"},{\"category\":\"120 mins\"},{\"category\":\"180 mins\"}]}]}\"\"\"\n        #\n        list_of_items = [\n            item for item in list_of_items if item != [base_category, base_value]\n        ]\n        # logging.info(\"list of items\", list_of_items)\n        # try:\n        #     list_as_string = str(list_of_items[0]).strip(\"[]\")\n        # except:\n        #     list_as_string = str(list_of_items)\n        # # agent_summary = agent_summary.split('.', 1)[0]\n        json_example = json_example.replace(\"{\", \"{{\").replace(\"}\", \"}}\")\n        # template = Template(prompt_template_base)\n        # output = template.render(\n        #     base_category=base_category,\n        #     base_value=base_value,\n        #     json_example=json_example,\n        #     assistant_category=assistant_category,\n        #     exclusion_categories=list_as_string,\n        # )\n        # complete_query = PromptTemplate.from_template(output)\n        #\n        # chain = LLMChain(llm=self.llm_fast, prompt=complete_query, verbose=self.verbose)\n        # chain_result = await chain.arun(prompt=complete_query, name=self.user_id)\n        # json_o = json.loads(chain_result)\n        # value_list = [{\"category\": value} for value in base_value.split(\",\")]\n        # # json_o[\"options\"].append({\"category\": \"Your preferences\", \"options\": value_list})\n        # chain_result = json.dumps(json_o)\n        # print(\"FINAL CHAIN\", chain_result)\n        # return chain_result\n        list_of_items = str(list_of_items)\n        #\n        #\n        class FoodOption(BaseModel):\n            category: str = Field(...,\n                                  description=\"Specific food option category, e.g., 'Italian', 'Gluten-free', 'Outdoor seating'\")\n\n        class CategoryOption(BaseModel):\n            category: str = Field(...,\n                                  description=\"Main category, e.g., 'Cuisine', 'Dietary Restrictions', 'Atmosphere'\")\n            options: List[FoodOption] = Field([], description=\"List of possible options for this main category\")\n\n        class Response(BaseModel):\n            category: str = Field(..., description=\"Main classification, e.g., 'Location', 'Price Range'\")\n            options: List[CategoryOption] = Field([], description=\"An array of category option objects.\")\n        #\n        system_message = f\"You are a world class algorithm for decomposing human \" \\\n                         f\"thoughts into decision trees on {assistant_category}. \"\n        guidance_query = f\"The request:\"\n        prompt_msgs = [\n            SystemMessage(\n                content=system_message\n            ),\n            HumanMessage(content=guidance_query),\n            HumanMessagePromptTemplate.from_template(\"{input}\"),\n            HumanMessage(content=f\"Tips: Make sure to answer in the correct format\"),\n            HumanMessage(content=f\"Tips: Must include the following as a category: {base_value} and exclude {list_of_items}\"),\n            HumanMessage(content=f\" Tips: Look at this json as example: {json_example}\"),\n            HumanMessage(content=f\"Tips: Escape possesive apostrophes with a backslash, e.g., 'John\\\\'s' \"),\n            # HumanMessage(content=f\"Tips: Exclude the following categories: {list_of_items}\"),\n        ]\n        prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n        chain = create_structured_output_chain(Response, self.llm35, prompt_, verbose=True)\n        output = await chain.arun(input=f\"\"\"Decompose decision point '{ base_category }' into three categories with the same or lower granularity and must include '{base_value}'.\n        Provide three sub-categories that specify the decision point better.\"\"\" )\n        # from pydantic import BaseModel, parse_raw\n        # Convert the dictionary to a Pydantic object\n        my_object = parse_obj_as(Response, output)\n        data = my_object.dict()\n        return str(data).replace(\"'\", '\"')\n\n    async def generate_concurrently(self, base_prompt, assistant_category,load_defaults=True):\n        \"\"\"Generates an async solution group\"\"\"\n\n\n        list_of_items = [item.split(\"=\") for item in base_prompt.split(\";\")]\n        prompt_template_base = \"\"\" Decompose decision point '{{ base_category }}' into three categories the same level as value '{{base_value}}'  definitely including '{{base_value}} ' but not including  {{exclusion_categories}}. Make sure choices further specify the  '{{ base_category }}' category  where AI is helping person in choosing {{ assistant_category }}.\n        Provide three sub-options that further specify the particular category better. Generate very short json, do not write anything besides json, follow this json property structure : {{json_example}}\"\"\"\n        list_of_items = base_prompt.split(\";\")\n\n        # If there is no ';', split on '=' instead\n        if len(list_of_items) == 1:\n            list_of_items = [list_of_items[0].split(\"=\")]\n        else:\n            list_of_items = [item.split(\"=\") for item in list_of_items]\n            # Remove  value\n            print(\"LIST OF ITEMS\", list_of_items)\n            logging.info(\"LIST OF ITEMS\", str(list_of_items))\n        tasks = [\n            self.async_generate(\n                prompt_template_base,\n                base_category,\n                base_value,\n                list_of_items,\n                assistant_category,\n            )\n            for base_category, base_value in list_of_items\n        ]\n        results = await asyncio.gather(*tasks)\n\n        def replace_underscores(data):\n            if isinstance(data, dict):\n                for key, value in data.items():\n                    if key == \"category\" and isinstance(value, str):\n                        data[key] = value.replace(\"_\", \" \")\n                    else:\n                        replace_underscores(value)\n            elif isinstance(data, list):\n                for item in data:\n                    replace_underscores(item)\n\n\n\n\n        if len(results) == 1:\n            logging.info(\"HERE ARE THE valid RESULTS %s\", str(results))\n            results_list = [json.loads(results[0])]\n\n        else:\n            logging.info(\"HERE ARE THE valid RESULTS %s\", len(results))\n            print(\"HERE ARE THE valid RESULTS %s\", len(results))\n            # Parse each JSON string and add it to a list\n            results = [\n                result[result.find(\"{\"): result.rfind(\"}\") + 1] for result in results\n            ]\n            results_list = [json.loads(result) for result in results]\n\n        replace_underscores(results_list)\n        combined_json = {\"results\": results_list}\n\n        def load_schema(filepath):\n            with open(filepath, 'r') as f:\n                return json.load(f)\n\n\n        try:\n            schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'schema',\n                                       'decompose_categories.json')\n            primary_schema = load_schema(schema_path)\n            validate = fastjsonschema.compile(primary_schema)\n            logging.info(\"HERE SOME RESULTS %s\", str({\"response\":combined_json}))\n            validate({\"response\":combined_json})\n            return combined_json\n        except fastjsonschema.exceptions.JsonSchemaException as e:\n            logging.info(\"HERE ARE THE  ERRORS %s\", str(e))\n            schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'defaults',\n                                       'categories_defaults.json')\n            combined_json = load_schema(schema_path)\n            return combined_json\n\n\n\n    def _loader(self, path: str, namespace: str):\n\n        loader = PyPDFLoader(\"../document_store/nutrition/Human_Nutrition.pdf\")\n        pages = loader.load_and_split()\n\n        print(\"PAGES\", pages[0])\n\n        for page in pages:\n            self._update_memories(page.page_content, namespace, page.metadata[\"page\"], page.metadata[\"source\"])\n        return \"Success\"\n        # print(type(pages))\n\n    def _process_pref(self, data):\n        for result in data[\"response\"][\"results\"]:\n            # Check if preference is empty and options exist\n            if not result[\"preference\"] and result[\"options\"]:\n                # Get the second nested category value\n                second_category = result[\"options\"][0][\"category\"]\n                # Assign it to the preference\n                result[\"preference\"] = [second_category]\n\n        # Assuming data is a dictionary with the structure you described\n        def remove_second_subnested_category(categories):\n            for category_data in categories:\n                if \"options\" in category_data:\n                    # If there are options in the current category, check if there is a second subnested category and remove it if it exists\n                    try:\n                        category_data[\"options\"].pop(1)\n                    except IndexError:\n                        pass\n\n                    # Recursively iterate over all subcategories, if any\n                    remove_second_subnested_category(category_data[\"options\"])\n\n        remove_second_subnested_category(data[\"response\"][\"results\"])\n        print(\"UPDATED OUTPUT\", data)\n        return data\n\n        # Assuming you have the JSON data in the \"data\" variable\n\n    def prompt_to_choose_tree(self, prompt: str, model_speed: str, assistant_category: str, load_defaults: bool = True):\n        \"\"\"Serves to generate agent goals and subgoals based on a prompt\"\"\"\n\n\n        def load_schema(filepath):\n            with open(filepath, 'r') as f:\n                return json.load(f)\n\n        if load_defaults:\n            schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'defaults',\n                                       'categories_input_defaults.json')\n            combined_json = json.dumps(load_schema(schema_path))\n            return combined_json\n        else:\n            json_example = \"\"\" <category1>=<decision1>;<category2>=<decision2>...\"\"\"\n            prompt_template = \"\"\"\n               Decompose {{ prompt_str }} statement into decision tree that take into account user summary information and related to {{ assistant_category }}. There should be three categories and one decision for each.  \n               Categories should be logical and user friendly. Do not include budget, meal type, intake, personality, user summary, personal preferences.\n               Decision should be one user can make in regards to {{ assistant_category }}. Present answer in one line and in property structure : {{json_example}}\"\"\"\n            bb =  \"\"\"Do not include budget, meal type, intake, personality, user summary, personal preferences, or update time to categories.  \"\"\"\n\n                # self.init_pinecone(index_name=self.index)\n                # try:\n                #     agent_summary = self._fetch_memories(\n                #         f\"Users core summary\", namespace=\"SUMMARY\"\n                #     )\n                #     print(\"HERE IS THE AGENT SUMMARY\", agent_summary)\n                #     agent_summary = str(agent_summary)\n                #\n                #     if (\n                #             str(agent_summary)\n                #             == \"{'error': 'No document found for this user. Make sure that a query is appropriate'}\"\n                #     ):\n                #         agent_summary = \"None.\"\n                # except:\n                #     agent_summary = \"None.\"\n                #\n                # import time\n                # start_time = time.time()\n\n                # agent_summary = agent_summary.split(\".\", 1)[0]\n            template = Template(prompt_template)\n            output = template.render(\n                prompt_str=prompt,\n                json_example=json_example,\n                # user_summary=agent_summary,\n                assistant_category=assistant_category,\n                # nutritional_context=test_output['answer']\n            )\n            complete_query = output\n            print(\"HERE IS THE COMPLETE QUERY\", complete_query)\n            complete_query = PromptTemplate.from_template(complete_query)\n\n\n            chain = LLMChain(llm=self.llm_fast, prompt=complete_query, verbose=False)\n            chain_result = chain.run(prompt=complete_query, name=self.user_id).strip()\n\n            import re\n\n            def add_space_to_camel_case(s):\n                # Check if the string contains any uppercase letters\n                if any(c.isupper() for c in s[1:]):  # We exclude the first character from the check\n                    s = re.sub(r'([a-z])([A-Z])', r'\\1 \\2', s)\n\n                # Convert each word to title case\n                return ' '.join([word.capitalize() for word in s.split()])\n\n            chain_result= add_space_to_camel_case(chain_result)\n            class Option(BaseModel):\n                category: str = Field(..., description=\" Each should have a 'category' (a specific choice like 'Under $25' or 'Red')\")\n                options: Optional[List] = Field([], description=\"Empty list\")\n            class Result(BaseModel):\n                category: str = Field(None, description=\" Specify the main classification (e.g., Price Range, Color, Size) in the 'category' field.\")\n                options: List[Option] = Field(None, description=\"An array of option objects.\")\n                preference: Optional[List] = Field([], description=\"Value of the first category\")\n            class Response(BaseModel):\n                results: List[Result] = Field(None, description=\"List of the results of the decision tree\")\n\n            class Main(BaseModel):\n                response: Response = Field(None, description=\"Complete decision tree response\")\n\n            system_message = f\"You are a world class algorithm applying raw output to a schema \" \\\n                             # f\" into decision trees on {assistant_category}. \"\n            # guidance_query = f\"Decompose sentences into decision trees on {assistant_category}. \" \\\n            #                  f\"Decompose the following statement:\"\n\n            guidance_query = f\"Apply output and change it to a schema\"\n            prompt_msgs = [\n                SystemMessage(\n                    content=system_message\n                ),\n                HumanMessage(content=guidance_query),\n                HumanMessagePromptTemplate.from_template(\"{input}\"),\n                HumanMessage(content=f\"Tips: Make sure to answer in the correct format\"),\n                HumanMessage(content=f\"Tips: Make sure lowest level options are an empty list \"),\n                HumanMessage(content=f\"Tips: Make sure results have multiple categories on the same level \")\n            ]\n            prompt_ = ChatPromptTemplate(messages=prompt_msgs)\n            chain = create_structured_output_chain(Main, self.llm35, prompt_, verbose=True)\n            output = chain.run(input=chain_result)\n            # from pydantic import BaseModel, parse_raw\n            # Convert the dictionary to a Pydantic object\n            my_object = parse_obj_as(Main, output)\n            data = my_object.dict()\n            logging.info(\"HERE IS THE inter RESULT\", str(data).replace(\"'\", '\"'))\n            print(\"HERE IS THE DICT\", data)\n            data_pr = self._process_pref(data)\n            logging.info(\"HERE IS THE FINAL RESULT\", str(data_pr).replace(\"'\", '\"'))\n            combined_json = data_pr\n            # combined_json = str(data_pr).replace(\"'\", '\"')\n\n\n            try:\n\n                schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'schema',\n                                           'decompose_categories_input.json')\n                primary_schema = load_schema(schema_path)\n                validate = fastjsonschema.compile(primary_schema)\n                logging.info(\"HERE SOME RESULTS %s\", str(combined_json))\n                try:\n                    validate(combined_json)\n                except:\n                    validate(json.loads(combined_json))\n                return str(combined_json).replace(\"'\", '\"')\n            except:\n                # logging.info(\"HERE ARE THE  ERRORS %s\", str(e))\n                schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'defaults',\n                                           'categories_input_defaults.json')\n                combined_json = json.dumps(load_schema(schema_path))\n                return combined_json\n\n    # def prompt_to_choose_tree(self, prompt: str, model_speed: str, assistant_category: str):\n    #     \"\"\"Serves to generate agent goals and subgoals based on a prompt\"\"\"\n    #\n    #     self.init_pinecone(index_name=self.index)\n    #     vectorstore: Pinecone = Pinecone.from_existing_index(\n    #         index_name=self.index, embedding=OpenAIEmbeddings(), namespace=\"NUTRITION_RESOURCE\"\n    #     )\n    #     retriever = vectorstore.as_retriever()\n    #     #\n    #     # template = \"\"\"\n    #     #    {summaries}\n    #     #    {question}\n    #     #    \"\"\"\n    #     #\n    #     # chain = RetrievalQAWithSourcesChain.from_chain_type(\n    #     #     llm=OpenAI(temperature=0),\n    #     #     chain_type=\"stuff\",\n    #     #     retriever=retriever,\n    #     #     chain_type_kwargs={\n    #     #         \"prompt\": PromptTemplate(\n    #     #             template=template,\n    #     #             input_variables=[\"summaries\", \"question\"],\n    #     #         ),\n    #     #     },\n    #     # )\n    #     # test_output = chain(\n    #     #     \"Retireve and summarize releavant information from the following document. Turn it into into decision tree that take into account user summary information and related to food. Present answer in one line summary\")\n    #     # print(\"TEST OUTPUT\", test_output['answer'])\n    #\n    #     # prompt_template = \"\"\"Retireve and summarize releavant information from the following document\n    #     #\n    #     #\n    #     # {text}\n    #     #\n    #     #\n    #     # Turn it into into decision tree that take into account user summary information and related to {{ assistant_category }}.\n    #     # Do not include budget, personality, user summary, personal preferences, or update time to categories. Do not include information about publisher or details. \"\"\"\n    #     # prompt_template = Template(prompt_template)\n    #     #\n    #     # prompt_template = prompt_template.render(\n    #     #     original_prompt=prompt,\n    #     #     assistant_category=assistant_category)\n    #     # PROMPT = PromptTemplate(template=prompt_template, input_variables=[\"text\"])\n    #     # chain_summary = load_summarize_chain(OpenAI(temperature=0), chain_type=\"map_reduce\", return_intermediate_steps=True,\n    #     #                              map_prompt=PROMPT, combine_prompt=PROMPT)\n    #     # test_output = chain_summary({\"input_documents\": pages[1:20]},   return_only_outputs=True)\n    #     #\n    #     # print(\"TEST OUTPUT\", test_output)\n    #\n    #     json_example = \"\"\" <category1>=<decision1>;<category2>=<decision2>...\"\"\"\n    #     prompt_template = \"\"\"Known user summary: '{{ user_summary }} '.\n    #        Decompose {{ prompt_str }} statement into decision tree that take into account user summary information and related to {{ assistant_category }}.\n    #        Do not include budget, meal type, intake, personality, user summary, personal preferences, or update time to categories.  Use the information to correct any major mistakes: {{nutritional_context}}\n    #        Decision should be one user can make. Present answer in one line and in property structure : {{json_example}}\"\"\"\n    #\n    #     self.init_pinecone(index_name=self.index)\n    #     try:\n    #         agent_summary = self._fetch_memories(\n    #             f\"Users core summary\", namespace=\"SUMMARY\"\n    #         )\n    #         print(\"HERE IS THE AGENT SUMMARY\", agent_summary)\n    #         agent_summary = str(agent_summary)\n    #\n    #         if (\n    #                 str(agent_summary)\n    #                 == \"{'error': 'No document found for this user. Make sure that a query is appropriate'}\"\n    #         ):\n    #             agent_summary = \"None.\"\n    #     except:\n    #         agent_summary = \"None.\"\n    #\n    #     import time\n    #     start_time = time.time()\n    #\n    #     agent_summary = agent_summary.split(\".\", 1)[0]\n    #     template = Template(prompt_template)\n    #     output = template.render(\n    #         prompt_str=prompt,\n    #         json_example=json_example,\n    #         user_summary=agent_summary,\n    #         assistant_category=assistant_category,\n    #         # nutritional_context=test_output['answer']\n    #     )\n    #     complete_query = output\n    #     print(\"HERE IS THE COMPLETE QUERY\", complete_query)\n    #     complete_query = PromptTemplate.from_template(complete_query)\n    #     if model_speed == \"fast\":\n    #         output = self.replicate_llm(output)\n    #         json_data = json.dumps(output)\n    #         return json_data\n    #     else:\n    #         chain = LLMChain(llm=self.llm_fast, prompt=complete_query, verbose=False)\n    #         chain_result = chain.run(prompt=complete_query, name=self.user_id).strip()\n    #         vectorstore: Pinecone = Pinecone.from_existing_index(\n    #             index_name=self.index,\n    #             embedding=OpenAIEmbeddings(),\n    #             namespace=\"GOAL\",\n    #         )\n    #         from datetime import datetime\n    #         retriever = vectorstore.as_retriever()\n    #         logging.info(str(chain_result))\n    #         print(\"HERE IS THE CHAIN RESULT\", chain_result)\n    #         retriever.add_documents(\n    #             [\n    #                 Document(\n    #                     page_content=chain_result,\n    #                     metadata={\n    #                         \"inserted_at\": datetime.now(),\n    #                         \"text\": chain_result,\n    #                         \"user_id\": self.user_id,\n    #                     },\n    #                     namespace=\"GOAL\",\n    #                 )\n    #             ]\n    #         )\n    #     return chain_result.replace(\"'\", '\"')\n\n    async def prompt_decompose_to_tree_categories(\n            self, prompt: str, assistant_category, model_speed: str, load_defaults: bool=True\n    ):\n        \"\"\"Serves to generate agent goals and subgoals based on a prompt\"\"\"\n        def load_schema(filepath):\n            with open(filepath, 'r') as f:\n                return json.load(f)\n\n        if load_defaults:\n            schema_path = os.path.join(os.path.dirname(__file__), '..', 'validations', 'defaults',\n                                       'categories_defaults.json')\n            combined_json = load_schema(schema_path)\n            return combined_json\n        else:\n            combined_json = await self.generate_concurrently(prompt, assistant_category, load_defaults=load_defaults)\n            return combined_json\n        # async for result in self.generate_concurrently(prompt):\n        #     yield result\n\n    def prompt_to_update_meal_tree(\n            self, category: str, from_: str, to_: str, model_speed: str\n    ):\n        self.init_pinecone(index_name=self.index)\n        vectorstore: Pinecone = Pinecone.from_existing_index(\n            index_name=self.index, embedding=OpenAIEmbeddings(), namespace=\"GOAL\"\n        )\n\n        retriever = vectorstore.as_retriever()\n        retriever.search_kwargs = {\n            \"filter\": {\"user_id\": {\"$eq\": self.user_id}}\n        }  # filter by user_id\n        answer_response = retriever.get_relevant_documents(\"prompt\")\n        answer_response.sort(\n            key=lambda doc: doc.metadata.get(\"inserted_at\")\n            if \"inserted_at\" in doc.metadata\n            else datetime.min,\n            reverse=True,\n        )\n\n        # The most recent document is now the first element of the list.\n        try:\n            most_recent_document = answer_response[0]\n        except IndexError:\n            return {\n                \"error\": \"No document found for this user. Make sure that a query is appropriate\"\n            }\n        doc = most_recent_document.page_content\n        json_str = doc.replace(\"'\", '\"')\n        document = json.loads(json_str)\n        matching_items = [\n            item for item in document[\"tree\"] if item[\"category\"] == category\n        ]\n        sub_tree = matching_items[0] if matching_items else None\n        sub_tree = json.dumps(sub_tree)\n        escaped_content = sub_tree.replace(\"{\", \"{{\").replace(\"}\", \"}}\")\n        logging.info(escaped_content)\n\n        optimization_prompt = \"\"\"Change the category: {{category}} based on {{from_}} to {{to_}}  change and update appropriate of the following original inluding the preference: {{results}}\n         \"\"\"\n\n        optimization_prompt = Template(optimization_prompt)\n        optimization_output = optimization_prompt.render(\n            category=category, from_=from_, to_=to_, results=escaped_content\n        )\n        complete_query = PromptTemplate.from_template(optimization_output)\n        # prompt_template = PromptTemplate(input_variables=[\"query\"], template=optimization_output)\n        review_chain = LLMChain(llm=self.llm, prompt=complete_query)\n        review_chain_result = review_chain.run(\n            prompt=complete_query, name=self.user_id\n        ).strip()\n        return review_chain_result.replace(\"'\", '\"')\n\n    def extract_info(self, s: str):\n        lines = s.split(\"\\n\")\n        name = lines[0]\n        address = lines[1].replace(\"Address: \", \"\")\n        phone = lines[2].replace(\"Phone: \", \"\")\n        website = lines[3].replace(\"Website: \", \"\")\n        return {\n            \"name\": name,\n            \"address\": address,\n            \"phone\": phone,\n            \"website\": website,\n        }\n\n    async def restaurant_generation(self, prompt: str, prompt_template: str, json_example: str, model_speed: str):\n        \"\"\"Serves to suggest a restaurant to the agent\"\"\"\n\n        if prompt:\n            prompt = prompt\n        else:\n            prompt = \"\"\"\n              Based on the following prompt {{prompt}} and all the history and information of this user,\n                Determine the type of restaurant you should offer to a customer. Make the recomendation very short and to a point, as if it is something you would type on google maps\n            \"\"\"\n\n        self.init_pinecone(index_name=self.index)\n        agent_summary = self._fetch_memories(f\"Users core summary\", namespace=\"SUMMARY\")\n        template = Template(prompt)\n        output = template.render(prompt=prompt)\n        complete_query = str(agent_summary) + output\n        complete_query = PromptTemplate.from_template(complete_query)\n        chain = LLMChain(llm=self.llm, prompt=complete_query, verbose=self.verbose)\n        chain_result = chain.run(prompt=complete_query).strip()\n        GPLACES_API_KEY = self.GPLACES_API_KEY\n        places = GooglePlacesTool()\n        output = places.run(chain_result)\n        restaurants = re.split(r\"\\d+\\.\", output)[1:3]\n        # Create a list of dictionaries for each restaurant\n        restaurant_list = [self.extract_info(r) for r in restaurants]\n        print(\"HERE IS THE OUTPUT\", restaurant_list)\n        return restaurant_list\n\n    # async def run_wolt_tool(self, zipcode, chain_result):\n    #     from food_scrapers import  wolt_tool\n    #     return wolt_tool.main(zipcode, chain_result)\n    async def delivery_generation(self, prompt: str, zipcode: str, model_speed: str):\n        \"\"\"Serves to optimize agent delivery recommendations\"\"\"\n\n        prompt = \"\"\"\n              Based on the following prompt {{prompt}}\n                Determine the type of food you would want to recommend to the user, that is commonly ordered online. It should of type of food offered on a delivery app similar to burger or pizza, but it doesn't have to be that.\n                The response should be very short\n            \"\"\"\n\n        self.init_pinecone(index_name=self.index)\n        agent_summary = self._fetch_memories(f\"Users core summary\", namespace=\"SUMMARY\")\n        template = Template(prompt)\n        output = template.render(prompt=prompt)\n        complete_query = str(agent_summary) + output\n        complete_query = PromptTemplate.from_template(complete_query)\n        chain = LLMChain(llm=self.llm, prompt=complete_query, verbose=self.verbose)\n        chain_result = chain.run(prompt=complete_query).strip()\n        from food_scrapers import wolt_tool\n\n        output = await wolt_tool.main(zipcode=zipcode, prompt=chain_result)\n        return output\n\n    def add_zapier_calendar_action(self, prompt_base, token, model_speed: str):\n        \"\"\"Serves to add a calendar action to the user's Google Calendar account\"\"\"\n\n        # try:\n        ZAPIER_NLA_OAUTH_ACCESS_TOKEN = token\n        zapier = ZapierNLAWrapper(\n            zapier_nla_oauth_access_token=ZAPIER_NLA_OAUTH_ACCESS_TOKEN\n        )\n        toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)\n        agent = initialize_agent(\n            toolkit.get_tools(),\n            self.llm_fast,\n            agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n            verbose=True,\n        )\n        # except:\n        #     zapier = ZapierNLAWrapper()\n        #     toolkit = ZapierToolkit.from_zapier_nla_wrapper(zapier)\n        #     agent = initialize_agent(toolkit.get_tools(), self.llm_fast, agent=AgentType.ZERO_SHOT_REACT_DESCRIPTION,\n        #                              verbose=True)\n\n        template = \"\"\" Formulate the following statement into a calendar request containing time, title, details of the meeting: {prompt} \"\"\"\n        prompt_template = PromptTemplate(input_variables=[\"prompt\"], template=template)\n        # complete_query = PromptTemplate.from_template(output)\n        chain = LLMChain(llm=self.llm, prompt=prompt_template, verbose=self.verbose)\n        overall_chain = SimpleSequentialChain(chains=[chain, agent], verbose=True)\n        outcome = overall_chain.run(prompt_base)\n        print(\"HERE IS THE OUTCOME\", outcome)\n        return outcome\n\n    def voice_text_input(self, query: str, model_speed: str):\n        \"\"\"Serves to generate sub goals for the user and or update the user's preferences\"\"\"\n\n        class GoalWrapper(BaseModel):\n            observation: str = Field(\n                description=\"observation we want to fetch from vectordb\"\n            )\n\n        @tool(\"goal_update_wrapper\", args_schema=GoalWrapper, return_direct=True)\n        def goal_update_wrapper(observation, args_schema=GoalWrapper):\n            \"\"\"Fetches data from the VectorDB and returns it as a python dictionary.\"\"\"\n            query = self._fetch_memories(observation, \"GOAL\")\n            loop = asyncio.get_event_loop()\n            res = loop.run_until_complete(\n                self.prompt_decompose_to_meal_tree_categories(query, \"slow\")\n            )\n            loop.close()\n            return res\n\n        class UpdatePreferences(BaseModel):\n            observation: str = Field(\n                description=\"observation we want to fetch from vectordb\"\n            )\n\n        @tool(\"preferences_wrapper\", args_schema=UpdatePreferences, return_direct=True)\n        def preferences_wrapper(observation, args_schema=UpdatePreferences):\n            \"\"\"Updates user preferences in the VectorDB.\"\"\"\n            return self._update_memories(observation, \"PREFERENCES\")\n\n        agent = initialize_agent(\n            llm=self.llm_fast,\n            tools=[goal_update_wrapper, preferences_wrapper],\n            agent=AgentType.OPENAI_FUNCTIONS,\n            verbose=self.verbose,\n        )\n\n        prompt = \"\"\"\n\n            Based on all the history and information of this user, classify the following query: {query} into one of the following categories:\n            1. Goal update , 2. Preference change,  3. Result change 4. Subgoal update  If the query is not any of these, then classify it as 'Other'\n            Return the classification and a very short summary of the query as a python dictionary. Update or replace or remove the original factors with the new factors if it is specified.\n            with following python dictionary format 'Result_type': 'Goal', \"Result_action\": \"Goal changed\", \"value\": \"Diet added\", \"summary\": \"The user is updating their goal to lose weight\"\n            Make sure to include the factors in the summary if they are provided\n            \"\"\"\n\n        template = Template(prompt)\n        output = template.render(query=query)\n        complete_query = output\n        complete_query = PromptTemplate(\n            input_variables=[\"query\"], template=complete_query\n        )\n        summary_chain = LLMChain(\n            llm=self.llm, prompt=complete_query, verbose=self.verbose\n        )\n        from langchain.chains import SimpleSequentialChain\n\n        overall_chain = SimpleSequentialChain(\n            chains=[summary_chain, agent], verbose=True\n        )\n        output = overall_chain.run(query)\n        return output\n\n    def fetch_user_summary(self, model_speed: str):\n        \"\"\"Serves to retrieve agent summary\"\"\"\n        self.init_pinecone(index_name=self.index)\n        agent_summary = self._fetch_memories(f\"Users core summary\", namespace=\"SUMMARY\")\n        return agent_summary\n\n    def _retrieve_summary(self):\n        \"\"\"Serves to retrieve agent summary\"\"\"\n        self.init_pinecone(index_name=self.index)\n        result = self._fetch_memories(\"Users core prompt\", \"GOAL\")\n        print(result)\n        return result\n\n\nif __name__ == \"__main__\":\n    agent = Agent()\n    # agent.prompt_correction(prompt_source=\"I would like a quicko veggiea meals under 25 near me and\", model_speed=\"slow\")\n    # agent.goal_optimization(factors={}, model_speed=\"slow\")\n    # agent._update_memories(\"lazy, stupid and hungry\", \"TRAITS\")\n    # agent.update_agent_traits(\"His personality is greedy\")\n    # agent.update_agent_preferences(\"Alergic to corn\")\n    # agent.add_zapier_calendar_action(\"I would like to schedule 1 hour meeting tomorrow at 12 about brocolli\", 'bla', 'BLA')\n    # agent.update_agent_summary(model_speed=\"slow\")\n    # agent.solution_generation(prompt=\"I would like a healthy chicken meal over 125$\", model_speed=\"slow\")\n    # loop = asyncio.get_event_loop()\n    # loop.run_until_complete(agent.prompt_decompose_to_meal_tree_categories(\"diet=vegan;availability=cheap\", \"food\", model_speed=\"slow\"))\n    # loop.close()\n    # import asyncio\n    #\n    #\n    # async def main():\n    #     out = await agent.prompt_to_choose_tree(prompt=\"I want would like a quick veggie meal Vietnamese cuisine\",\n    #                                             assistant_category=\"food\", model_speed=\"slow\")\n    #     # Rest of your code here\n    #\n    #\n    # # Run the async function\n    # asyncio.run(main())\n\n    # print(result)\n    # agent._test()\n    # agent.update_agent_summary(model_speed=\"slow\")\n    # agent.voice_text_input(\"Core prompt \", model_speed=\"slow\")\n"
  },
  {
    "path": "pyproject.toml",
    "content": "[tool.poetry]\nname = \"promethAI\"\nversion = \"0.1.0\"\ndescription = \"PromethAI helps with nutrition choices and is an AI agent\"\nauthors = [\"Vasilije Markovic\"]\nreadme = \"README.md\"\n\n[tool.poetry.dependencies]\npython = \"^3.10\"\n#langchain = {git = \"https://github.com/topoteretes/langchain.git\" , tag = \"v0.0.209\"}\nlangchain = \"v0.0.250\"\n\nnltk = \"3.8.1\"\nopenai = \"0.27.8\"\npinecone-client = \"2.2.2\"\npython-dotenv = \"1.0.0\"\npyyaml = \"6.0\"\nfastapi = \"0.98.0\"\nuvicorn = \"0.22.0\"\ngooglemaps = \"4.10.0\"\njinja2 = \"3.1.2\"\nreplicate = \"^0.8.4\"\npexpect = \"^4.8.0\"\nselenium = \"^4.9.0\"\nplaywright = \"^1.32.1\"\npytest-playwright = \"^0.3.3\"\nboto3 = \"^1.26.125\"\ngptcache = \"^0.1.22\"\nredis = \"^4.5.5\"\ngunicorn = \"^20.1.0\"\ntiktoken = \"^0.4.0\"\ngoogle-search-results = \"^2.4.2\"\nspacy = \"^3.5.3\"\npython-jose = \"^3.3.0\"\npypdf = \"^3.12.0\"\nfastjsonschema = \"^2.18.0\"\n\n\n\n\n\n[build-system]\nrequires = [\"poetry-core\"]\nbuild-backend = \"poetry.core.masonry.api\"\n"
  },
  {
    "path": "test_api.py",
    "content": "import pytest\nfrom fastapi.testclient import TestClient\nfrom llm_chains.chains import Agent\nfrom api import app\n\nclient = TestClient(app)\n\n\n@pytest.fixture(scope=\"session\")\ndef agent():\n    yield Agent()\n\n\nclass TestRoutes:\n    def test_root(self):\n        response = client.get(\"/\")\n        assert response.status_code == 200\n        assert response.json() == {\"message\": \"Hello, World, I am alive!\"}\n\n    class TestRoutes:\n        def test_root(self):\n            response = client.get(\"/\")\n            assert response.status_code == 200\n            assert response.json() == {\"message\": \"Hello, World, I am alive!\"}\n\n        def test_health_check(self):\n            response = client.get(\"/health\")\n            assert response.status_code == 200\n            assert response.json() == {\"status\": \"OK\"}\n\n        def test_prompt_to_choose_meal_tree(self):\n            payload = {\n                \"payload\": {\n                    \"user_id\": \"657\",\n                    \"session_id\": \"456\",\n                    \"model_speed\": \"slow\",\n                    \"prompt\": \"I want to eat healthy\",\n                }\n            }\n            response = client.post(\"/prompt-to-choose-meal-tree\", json=payload)\n            assert response.status_code == 200\n            response_body = response.json()\n\n            # Check that the response structure is correct\n            assert \"response\" in response_body\n            assert \"results\" in response_body[\"response\"]\n\n    def test_prompt_to_decompose_meal_tree_categories(self):\n        payload = {\n            \"payload\": {\n                \"user_id\": \"659\",\n                \"session_id\": \"458\",\n                \"model_speed\": \"slow\",\n                \"prompt_struct\": \"taste=Helsinki;health=Helsinki;cost=Helsinki\",\n            }\n        }\n        response = client.post(\n            \"/prompt-to-decompose-meal-tree-categories\", json=payload\n        )\n        assert response.status_code == 200\n        response_body = response.json()\n\n        # Check that the response structure is correct\n        assert \"response\" in response_body\n        assert \"category\" in response_body[\"response\"]\n        assert \"options\" in response_body[\"response\"]\n\n        # Check that the main category is 'location'\n        assert response_body[\"response\"][\"category\"] == \"location\"\n\n        # Check that the options are correct\n        options = response_body[\"response\"][\"options\"]\n        assert len(options) == 3  # There should be 3 options\n\n        # Check that each option has a 'category' and 'options'\n        for option in options:\n            assert \"category\" in option\n            assert \"options\" in option\n\n            # Check that each sub-option has a 'category'\n            for sub_option in option[\"options\"]:\n                assert \"category\" in sub_option\n\n\nif __name__ == \"__main__\":\n    pytest.main()\n"
  },
  {
    "path": "utils/load_prod_redis.py",
    "content": "import requests\nimport json\nfrom itertools import combinations\n\n# Define the endpoint URL\n\nendpoint_url = \"http://0.0.0.0:8000/prompt-to-decompose-meal-tree-categories\"\n\n# Define the meal choice factors\nmeal_choice_factors = [\n    \"taste\",\n    \"health\",\n    \"cost\",\n    \"cuisine\",\n    \"hunger\",\n    \"availability\",\n    \"diet\",\n    \"allergies\",\n    \"time\",\n    \"mood\",\n    \"calories\",\n]\n\nmeal_choice_factors.sort()\n\nprint(\"Factors used for sorting: \", meal_choice_factors)\n\n\n# Define the payload template\npayload_template = {\n    \"payload\": {\n        \"user_id\": \"123\",\n        \"session_id\": \"471\",\n        \"model_speed\": \"slow\",\n        \"prompt_struct\": \"\",\n    }\n}\n\n\nheaders = {\"Content-Type\": \"application/json\"}\n\n\n# Generate combinations of three factors\nfactor_combinations = list(combinations(meal_choice_factors, 3))\n# Get the total number of combinations\ntotal_combinations = len(factor_combinations)\n\n# Iterate through the combinations\nfor i, factors in enumerate(factor_combinations, 1):\n    # Combine three factors with the prompt structure\n    prompt_struct = \";\".join([f\"{factor}=Helsinki\" for factor in factors])\n    payload_template[\"payload\"][\"prompt_struct\"] = prompt_struct\n\n    # Convert payload template to JSON\n    payload_json = json.dumps(payload_template)\n\n    # Send the request to the endpoint\n    response = requests.request(\n        \"POST\", endpoint_url, headers=headers, data=payload_json\n    )\n\n    # Print the response\n    print(response.text)\n\n    # Print the progress and remaining requests\n    print(f\"Progress: {i}/{total_combinations}\")\n    print(f\"Requests remaining: {total_combinations - i}\")\n"
  },
  {
    "path": "utils/utils.py",
    "content": "import time\nimport subprocess\nimport openai\n\n\ndef openai_call(\n    self,\n    prompt: str,\n    model: str = None,\n    temperature: float = None,\n    max_tokens: int = 2000,\n):\n    while True:\n        try:\n            if model.startswith(\"llama\"):\n                # Spawn a subprocess to run llama.cpp\n                cmd = [\"llama/main\", \"-p\", prompt]\n                result = subprocess.run(\n                    cmd,\n                    shell=True,\n                    stderr=subprocess.DEVNULL,\n                    stdout=subprocess.PIPE,\n                    text=True,\n                )\n                return result.stdout.strip()\n            else:\n                # Use chat completion API\n                messages = [\n                    {\n                        \"role\": \"system\",\n                        \"content\": \"You are an intelligent agent with thoughts and memories. You have a memory which stores your past thoughts and actions and also how other users have interacted with you.\",\n                    },\n                    {\n                        \"role\": \"system\",\n                        \"content\": \"Keep your thoughts relatively simple and concise\",\n                    },\n                    {\"role\": \"user\", \"content\": prompt},\n                ]\n                response = openai.ChatCompletion.create(\n                    model=model,\n                    messages=messages,\n                    temperature=temperature,\n                    max_tokens=max_tokens,\n                    n=1,\n                    stop=None,\n                )\n                return response.choices[0].message.content\n        except openai.error.RateLimitError:\n            print(\n                \"The OpenAI API rate limit has been exceeded. Waiting 10 seconds and trying again.\"\n            )\n            time.sleep(10)  # Wait 10 seconds and try again\n        else:\n            break\n"
  },
  {
    "path": "validations/defaults/categories_defaults.json",
    "content": " {\"response\":{\n        \"results\": [\n            {\n                \"category\": \"Nutritional Content\",\n                \"options\": [\n                    {\n                        \"category\": \"High Protein\",\n                        \"options\": [\n                            {\n                                \"category\": \"Animal Source\"\n                            },\n                            {\n                                \"category\": \"Plant Source\"\n                            },\n                            {\n                                \"category\": \"Supplement\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"Low Fat\",\n                        \"options\": [\n                            {\n                                \"category\": \"Skimmed Products\"\n                            },\n                            {\n                                \"category\": \"Lean Meat\"\n                            },\n                            {\n                                \"category\": \"Low Fat Dairy\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"High Fiber\",\n                        \"options\": [\n                            {\n                                \"category\": \"Whole Grains\"\n                            },\n                            {\n                                \"category\": \"Legumes\"\n                            },\n                            {\n                                \"category\": \"Vegetables\"\n                            }\n                        ]\n                    }\n                ]\n            },\n            {\n                \"category\": \"Cuisine\",\n                \"options\": [\n                    {\n                        \"category\": \"Famous Cuisine\",\n                        \"options\": [\n                            {\n                                \"category\": \"Chinese\"\n                            },\n                            {\n                                \"category\": \"Japanese\"\n                            },\n                            {\n                                \"category\": \"French\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"Spicy Foods\",\n                        \"options\": [\n                            {\n                                \"category\": \"Mexican\"\n                            },\n                            {\n                                \"category\": \"Indian\"\n                            },\n                            {\n                                \"category\": \"Thai\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"Mediterranean Flavors\",\n                        \"options\": [\n                            {\n                                \"category\": \"Greek\"\n                            },\n                            {\n                                \"category\": \"Italian\"\n                            },\n                            {\n                                \"category\": \"Spanish\"\n                            }\n                        ]\n                    }\n                ]\n            },\n            {\n                \"category\": \"Allergies\",\n                \"options\": [\n                    {\n                        \"category\": \"Dairy\",\n                        \"options\": [\n                            {\n                                \"category\": \"Milk\"\n                            },\n                            {\n                                \"category\": \"Cheese\"\n                            },\n                            {\n                                \"category\": \"Butter\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"Nuts\",\n                        \"options\": [\n                            {\n                                \"category\": \"Peanuts\"\n                            },\n                            {\n                                \"category\": \"Almonds\"\n                            },\n                            {\n                                \"category\": \"Cashews\"\n                            }\n                        ]\n                    },\n                    {\n                        \"category\": \"Gluten\",\n                        \"options\": [\n                            {\n                                \"category\": \"Wheat\"\n                            },\n                            {\n                                \"category\": \"Rye\"\n                            },\n                            {\n                                \"category\": \"Barley\"\n                            }\n                        ]\n                    }\n                ]\n            }\n\n        ]\n    }\n }\n"
  },
  {
    "path": "validations/defaults/categories_input_defaults.json",
    "content": "{\n    \"response\": {\n        \"results\": [\n            {\n                \"category\": \"Nutritional Content\",\n                \"options\": [\n                    {\n                        \"category\": \"High Protein\",\n                        \"options\": [\n                            {\n                                \"category\": \"Animal Source\"\n                            },\n                            {\n                                \"category\": \"Plant Source\"\n                            },\n                            {\n                                \"category\": \"Supplement\"\n                            }\n                        ]\n                    }\n                ],\n                \"preference\": [\n                    \"Animal Source\"\n                ]\n            },\n            {\n                \"category\": \"Cuisine\",\n                \"options\": [\n                    {\n                        \"category\": \"Famous Cuisine\",\n                        \"options\": [\n                            {\n                                \"category\": \"Chinese\"\n                            },\n                            {\n                                \"category\": \"Japanese\"\n                            },\n                            {\n                                \"category\": \"French\"\n                            }\n                        ]\n                    }\n                ],\n                \"preference\": [\n                    \"Famous Cuisine\"\n                ]\n            },\n            {\n                \"category\": \"Allergies\",\n                \"options\": [\n                    {\n                        \"category\": \"Dairy\",\n                        \"options\": [\n                            {\n                                \"category\": \"Milk\"\n                            },\n                            {\n                                \"category\": \"Cheese\"\n                            },\n                            {\n                                \"category\": \"Butter\"\n                            }\n                        ]\n                    }\n                ],\n                \"preference\": [\n                    \"Dairy\"\n                ]\n            }\n        ]\n    }\n}\n"
  },
  {
    "path": "validations/schema/decompose_categories.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"response\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"results\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/option\"\n                    }\n                }\n            },\n            \"required\": [\"results\"]\n        }\n    },\n    \"required\": [\"response\"],\n    \"definitions\": {\n        \"option\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"category\": {\n                    \"type\": \"string\"\n                },\n                \"options\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/option\"\n                    }\n                }\n            },\n            \"required\": [\"category\"]\n        }\n    }\n}"
  },
  {
    "path": "validations/schema/decompose_categories_input.json",
    "content": "{\n    \"$schema\": \"http://json-schema.org/draft-07/schema#\",\n    \"type\": \"object\",\n    \"properties\": {\n        \"response\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"results\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/resultItem\"\n                    }\n                }\n            },\n            \"required\": [\"results\"]\n        }\n    },\n    \"required\": [\"response\"],\n    \"definitions\": {\n        \"resultItem\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"category\": {\n                    \"type\": \"string\"\n                },\n                \"options\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/option\"\n                    }\n                },\n                \"preference\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"type\": \"string\"\n                    }\n                }\n            },\n            \"required\": [\"category\", \"options\", \"preference\"]\n        },\n        \"option\": {\n            \"type\": \"object\",\n            \"properties\": {\n                \"category\": {\n                    \"type\": \"string\"\n                },\n                \"options\": {\n                    \"type\": \"array\",\n                    \"items\": {\n                        \"$ref\": \"#/definitions/option\"\n                    }\n                }\n            },\n            \"required\": [\"category\", \"options\"]\n        }\n    }\n}\n"
  }
]