Compare commits
584 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 784b607613 | |||
| 44aa16a0f8 | |||
| 3eff82082e | |||
| d2f6fce52e | |||
| 419dc6598c | |||
| 51092b0b64 | |||
| 918823d805 | |||
| e287fb9a89 | |||
| ab4f872502 | |||
| 8be831f7ed | |||
| 67c775276f | |||
| 12a4934112 | |||
| b386e24f5d | |||
| 58b6887bf5 | |||
| 2269194662 | |||
| 1290c1bb2e | |||
| c197a5fe93 | |||
| 563a130141 | |||
| 80945df4ca | |||
| 45ae1f0313 | |||
| e585d3c1cc | |||
| abd4ec64eb | |||
| 47afe52296 | |||
| f2ddc573f6 | |||
| 6f42a95aab | |||
| ac6b53ed0a | |||
| c39436ae74 | |||
| 607c689cb0 | |||
| 914feb65a0 | |||
| ab3c9f889d | |||
| bb2efb8b8b | |||
| 9148cce8fc | |||
| cbb2b2991d | |||
| fd1d5e0e2b | |||
| 04b0297ae4 | |||
| ef706ad976 | |||
| d9f09c1819 | |||
| 0773b37197 | |||
| c8a5c6f0e9 | |||
| c7b9498693 | |||
| c27ab0585c | |||
| e913c96926 | |||
| 0c9c5fe9c2 | |||
| 51fd7db205 | |||
| e9136c1aa0 | |||
| a546a9f56a | |||
| 40c9abe484 | |||
| c411dc294e | |||
| fb5a3bfd95 | |||
| 7441f1462d | |||
| c9240e7ca6 | |||
| 1e7618dfa4 | |||
| 4e5d34103f | |||
| da435bc025 | |||
| 2a43aa6902 | |||
| b620f8fae3 | |||
| 03f787d5cb | |||
| 19637804b3 | |||
| 80f145fceb | |||
| 34477d4936 | |||
| 4ec51f2dd6 | |||
| f842a92e25 | |||
| 83e8c97295 | |||
| 1a5d0d236a | |||
| ebbf90f4aa | |||
| 4f119692f1 | |||
| bbe56107fb | |||
| bd654e7aac | |||
| 33500a7ce2 | |||
| 4880557d51 | |||
| ea09b5f7f0 | |||
| 5258fd91ea | |||
| b305d674de | |||
| 7c24601d0f | |||
| 50c0285cb2 | |||
| 0a78198bb5 | |||
| edaeb78ccf | |||
| f80be2d2ea | |||
| 8700165b42 | |||
| 18fb92f1f8 | |||
| 14fc6bbadd | |||
| 5070a1d83e | |||
| 8a9088ea9d | |||
| 48b24f6f12 | |||
| f6ddd5ffc5 | |||
| b43a116b3c | |||
| 50512a5f03 | |||
| e3e107b31d | |||
| 21a04541ea | |||
| cdd5d8ac76 | |||
| 11094f504e | |||
| 5acaae5f56 | |||
| 4547d870af | |||
| dc0d8e0932 | |||
| c558eae9ce | |||
| abb9af66a6 | |||
| 4800e0344c | |||
| 439b425c61 | |||
| 2855f1635b | |||
| 08b67b4a78 | |||
| 1bddd46ed2 | |||
| 6ecdadfd97 | |||
| 4119040005 | |||
| 873eef6ef8 | |||
| 445fed4d3f | |||
| 52fd3e0dd4 | |||
| 8fd0e1f3b0 | |||
| 11fc4a8451 | |||
| e22293294e | |||
| 73e53aaff1 | |||
| 6fa946557f | |||
| fb0852f585 | |||
| 4070fc1bf0 | |||
| 00c1fa1ec7 | |||
| 04e77ef34e | |||
| 827d63d115 | |||
| e0d0f6e94c | |||
| fd07513004 | |||
| b0e436d9c4 | |||
| a4bfd9cfc6 | |||
| 8ca01918e5 | |||
| a5b2381458 | |||
| 26c771503b | |||
| 622ed4a7c9 | |||
| 940f0128d5 | |||
| 1354747ca8 | |||
| 9544c69c55 | |||
| 9ba445e623 | |||
| ebc5e25f98 | |||
| 78301ee63d | |||
| 797dea1dca | |||
| a0ff764f0a | |||
| a795798156 | |||
| 1a66f961f4 | |||
| 6fb2048af0 | |||
| ba9f186fc5 | |||
| 6c32d287b5 | |||
| 536f85b78a | |||
| f8619870ad | |||
| d00a2085d5 | |||
| 85ec61335a | |||
| 9b48a12c27 | |||
| c181ccbe42 | |||
| 8520033d44 | |||
| ebdce87fde | |||
| f2122ed696 | |||
| 3616eaadb4 | |||
| ef69c91b60 | |||
| 117824b32c | |||
| f77f5b996e | |||
| a4d32aec24 | |||
| 9111495fae | |||
| ee1e3f0957 | |||
| 4dc5c7348f | |||
| 4428768eaa | |||
| 11f4ce8fb6 | |||
| 6078738d34 | |||
| faacfeb891 | |||
| 8d7e8b6fb9 | |||
| 7e1d2ffdd7 | |||
| 91044ec591 | |||
| c77a75dfb5 | |||
| 6518c0c06b | |||
| 09cdaff9a2 | |||
| 56bf33ab7f | |||
| 752f638cfc | |||
| 92dd7edb57 | |||
| b4bb4cf053 | |||
| f0400e928a | |||
| aa5ad625af | |||
| f8f69eab03 | |||
| 2b2263acaa | |||
| 5e2e7fb639 | |||
| 6c12bc9044 | |||
| 9a11683003 | |||
| 38b4e06963 | |||
| 0766a44ccf | |||
| 036bf3a161 | |||
| 41bd258b93 | |||
| 38e212c721 | |||
| 2f285ea00a | |||
| d38120c839 | |||
| d94aee812b | |||
| 68d650ec40 | |||
| 769d926f5a | |||
| 9478bab04e | |||
| 7ad4af250f | |||
| 9fa368b114 | |||
| 4afef04f26 | |||
| 8fe2c3effc | |||
| fa78c972be | |||
| 0e66261644 | |||
| 819650a254 | |||
| 34c41c87dc | |||
| 2985b667b0 | |||
| 31bb0e7f0f | |||
| 8f28264aec | |||
| ec4fb11aa5 | |||
| b210723de1 | |||
| 433f99dd78 | |||
| e75c05112e | |||
| d2a5b50ff8 | |||
| 120690afd4 | |||
| 344dbeee42 | |||
| 3fe3b0320a | |||
| 75896b647f | |||
| 446d0975aa | |||
| b7d365119c | |||
| 2d9fbd4e49 | |||
| 22e14b5e65 | |||
| 1a654beea4 | |||
| f50f8a444a | |||
| 3cc3a0058d | |||
| ae473b5e3c | |||
| efb7e31565 | |||
| 069d265338 | |||
| 751a3a4bd1 | |||
| cb0499407e | |||
| 9afc6878c8 | |||
| 0b5b12575a | |||
| d79d30bf0c | |||
| 59600e2a5b | |||
| e572b5a3dc | |||
| 5b46daaee4 | |||
| 2784bae772 | |||
| 325e11f0de | |||
| 7444f59e3c | |||
| affe319460 | |||
| 862ff6cca6 | |||
| c020e65a50 | |||
| f582c1fe25 | |||
| 785929c502 | |||
| 68ec6615b1 | |||
| e2cca61cd3 | |||
| 69e83adae0 | |||
| 9e24aee40d | |||
| 3cff5e9898 | |||
| f3553040bc | |||
| 2b13984e11 | |||
| 0de9491c61 | |||
| c9df7a2020 | |||
| a7222e8c50 | |||
| 0373fa231c | |||
| 5f653e69ae | |||
| 2496ed133e | |||
| 62c0c52e31 | |||
| e36198dcc2 | |||
| 5fa6221f91 | |||
| f7696d1dc1 | |||
| 1878f8d4fc | |||
| 6c69ddef9b | |||
| 0c45020d81 | |||
| 4dfce44c1a | |||
| 1b661bb2fd | |||
| 73e726f6e3 | |||
| f58bbeffce | |||
| 99261e5fb5 | |||
| b4a59d1bd5 | |||
| 5c1f78879f | |||
| 94ba82f2a2 | |||
| b4ec14382b | |||
| 38ad57a22c | |||
| 60bbc180ba | |||
| a67d902b85 | |||
| ae2e9cb890 | |||
| 1976d38b25 | |||
| f5e3410e9a | |||
| 2f6ba642c7 | |||
| dd9b72dc62 | |||
| dd258c14b5 | |||
| 295cd3fac6 | |||
| c62663f2e4 | |||
| 367d6b70e2 | |||
| 27236bd1b2 | |||
| 6a82eb4287 | |||
| bd88fe3980 | |||
| 4f70fea6df | |||
| aee5bbb44b | |||
| a304ded500 | |||
| a54dde0509 | |||
| 52b4577d3b | |||
| e199f57279 | |||
| dec12b33a6 | |||
| 04daa1b206 | |||
| a7e1520d08 | |||
| 9e2b232c13 | |||
| 404e73af77 | |||
| a544b4d3ff | |||
| 6df63d9ca7 | |||
| 904baac153 | |||
| a926bcc640 | |||
| c0aafd38c9 | |||
| 19d80914df | |||
| d9d529987e | |||
| 12e6eaf802 | |||
| 7a026ea282 | |||
| 97dc90169b | |||
| 64c02f374a | |||
| 6c1ea7799e | |||
| 6be29f5bed | |||
| 68737da7a2 | |||
| da388b679f | |||
| 11f0d719f5 | |||
| e90673ae5b | |||
| f055028c6b | |||
| 106a338371 | |||
| 9fe80c5cca | |||
| 050706e95e | |||
| 6d2389de1c | |||
| dd97fad5a4 | |||
| 0f73ba9677 | |||
| 210fe9bb80 | |||
| ec8549d0e1 | |||
| b77d9d750f | |||
| a10823d309 | |||
| 3a09c2bd62 | |||
| a1394ce32e | |||
| 1020a4121f | |||
| 737837ae0b | |||
| 7ee2d0653b | |||
| 43926fb527 | |||
| 7bcc9e35dd | |||
| 6437661837 | |||
| b5f84f27ff | |||
| 48c38b5dc3 | |||
| b4f3bbbbc9 | |||
| 3cd50c4cd9 | |||
| cd2c40a9c4 | |||
| 33dcfe42b5 | |||
| db37b2ac15 | |||
| bee4e834b1 | |||
| 0272459435 | |||
| c0b5e93967 | |||
| 6983ebba49 | |||
| 9943d1e015 | |||
| b348251484 | |||
| e719b5bac3 | |||
| 54f43215cd | |||
| b246d9823e | |||
| 65c8dd445b | |||
| 0efbc80ac9 | |||
| 151746beec | |||
| c0ee680546 | |||
| 9303a1bf81 | |||
| d54cdc5b00 | |||
| b7a44ef472 | |||
| ae6f866901 | |||
| 7910cee259 | |||
| d66e647f99 | |||
| ff4a333be7 | |||
| 111749a95d | |||
| adde398b65 | |||
| d8897ce356 | |||
| 0ea8ab228c | |||
| d62a23edf6 | |||
| 51ebf3439b | |||
| 4a5ed1dd8d | |||
| e84b5034ea | |||
| a4831d6ed9 | |||
| 51b4966801 | |||
| 1d4e00ccef | |||
| c9fbc2e7d6 | |||
| fa34788df6 | |||
| 0f4f220119 | |||
| 512cfc9466 | |||
| 541b1cb7c7 | |||
| 36af1a7615 | |||
| b02e8feeda | |||
| 406c46e7f4 | |||
| e35eaf1bfc | |||
| 38426a7af1 | |||
| 141a23fb1e | |||
| bb28569abf | |||
| 1df46b2bb3 | |||
| 58f72e1ffe | |||
| 33409140b4 | |||
| f6b80e01a1 | |||
| 798d3fcc5a | |||
| 85f3ac428b | |||
| 9fcf2130b5 | |||
| 51df00729e | |||
| 023a61446f | |||
| e0b73e6a5a | |||
| 28460f725c | |||
| c93e49d2b8 | |||
| 07fb6bee54 | |||
| 3fa7db8420 | |||
| c14bd7b73b | |||
| 5201beaab0 | |||
| 122313d8a5 | |||
| 82fd595306 | |||
| 95c0d47236 | |||
| 919cc74e94 | |||
| d839991acb | |||
| 539286aafd | |||
| 23522b7b55 | |||
| bf3fac56e4 | |||
| a5bf8e9075 | |||
| 1d31b8f7e4 | |||
| b144c7dccc | |||
| 1364975396 | |||
| deaa7f50f8 | |||
| 744ab5156f | |||
| c45413969a | |||
| b314e5e080 | |||
| 17129e2eaa | |||
| 654fd8d74c | |||
| 9d3568ef75 | |||
| 14712cac88 | |||
| 0d568c758b | |||
| 7c6b88c7c5 | |||
| 32c93be46e | |||
| 7de8d85199 | |||
| f7dd65a3de | |||
| d8cdbe0041 | |||
| 2b8b6d3ea9 | |||
| 936c7e389f | |||
| 6864b4207b | |||
| 98eb5b54be | |||
| 3332e6e236 | |||
| 0533da72d7 | |||
| a1de238716 | |||
| f0d112254b | |||
| 830a7397ef | |||
| 5428765329 | |||
| 23c912f2b7 | |||
| 9c4b023297 | |||
| 53037b5ed8 | |||
| e2546a653d | |||
| 4b8cada873 | |||
| fa3ca1d08a | |||
| 8dd5cb9602 | |||
| a054f7be9c | |||
| df314dc6d1 | |||
| 930280f4ce | |||
| 5022c1ae29 | |||
| 6ced756a6b | |||
| b17268db50 | |||
| 476da37009 | |||
| 455f059c6f | |||
| 5255a37c93 | |||
| 68dc274f72 | |||
| 30228f7f8e | |||
| e15ef79ca9 | |||
| bc012a7518 | |||
| 3b4409cfad | |||
| d3726134b2 | |||
| 5acb7f1c55 | |||
| 81336668b3 | |||
| 35c2b83015 | |||
| cc1ee1deaa | |||
| 29bd038579 | |||
| f6c4f86986 | |||
| 68183e9dce | |||
| 78ec91a3a9 | |||
| c95d458e52 | |||
| 191ae3ec1e | |||
| ab9598d00a | |||
| 0f8a2e624a | |||
| d77e8da3f3 | |||
| a27eeb3255 | |||
| 413ccb83e6 | |||
| 797bb567c6 | |||
| f2a5dc40ee | |||
| 3979480532 | |||
| 76f1993e7a | |||
| d783fa2b89 | |||
| bbce18caac | |||
| 3ce2d8a656 | |||
| a5c86a2f5c | |||
| d18e533adf | |||
| 2b881aaad0 | |||
| 39cc07608f | |||
| 9894cfcced | |||
| b5d80be037 | |||
| b7870fbd9b | |||
| 36e6d486fc | |||
| 2d5dc84f1a | |||
| b47405e1bd | |||
| 8b64deab40 | |||
| c8846e0e93 | |||
| 7641cba01d | |||
| 4dc1785ef1 | |||
| b2286f3e34 | |||
| 65a20aa457 | |||
| d8a7d71344 | |||
| bb490df9a6 | |||
| cdfd6519c8 | |||
| e8a2846449 | |||
| d065cbf934 | |||
| 413b107b9a | |||
| c336292346 | |||
| adf50f1e81 | |||
| 636bc0a99d | |||
| a7a61fae1d | |||
| 5ec12212e4 | |||
| 77c90a308e | |||
| 4a8c50f886 | |||
| a86d7f52e9 | |||
| 4820ea15d6 | |||
| b5de605e2b | |||
| d6ed2050d4 | |||
| 16e123b7bb | |||
| 4eb91683a9 | |||
| 0cb78b9067 | |||
| e226a89637 | |||
| 431f8c2c6a | |||
| 19a9141c2d | |||
| bc649b9a85 | |||
| 702067e521 | |||
| 03a84daf9d | |||
| b91d922600 | |||
| ed02aebf9a | |||
| 1a048390fd | |||
| 1741d3bef6 | |||
| 540a0a3685 | |||
| d2fd3ce434 | |||
| ea76868d65 | |||
| f31351bedb | |||
| 8863983c7b | |||
| 64a34cac32 | |||
| 352e71461d | |||
| 87d0b5c76f | |||
| d0af018b8d | |||
| 55e9a1cbd6 | |||
| 65bafb75b1 | |||
| 01fd1c2437 | |||
| 78ba4468b0 | |||
| 8581c7ecce | |||
| 9be6fe6bc3 | |||
| 8c506da21e | |||
| c02002eb4b | |||
| 57ecfca862 | |||
| 28d41e9397 | |||
| 7a1866d280 | |||
| d229b108c3 | |||
| 39640cb697 | |||
| 9ecf2e9feb | |||
| 2db07cdb1f | |||
| faa29ef285 | |||
| 16b0d5b829 | |||
| 6ae33d04b8 | |||
| 333eb8d60f | |||
| 414c69fd62 | |||
| 9951b58005 | |||
| e73ed82ae9 | |||
| 8bde34a24f | |||
| b58380e505 | |||
| 16f8de810c | |||
| 70f2de4fd3 | |||
| a5d5e5825f | |||
| 0f16c72762 | |||
| 9ca7a0d6d1 | |||
| 7d5bfd8c9f | |||
| cc9a06b116 | |||
| b8fc7b0c9e | |||
| 3999f2a373 | |||
| 4eb2c0e123 | |||
| b8a838aee1 | |||
| 84e5932ea5 | |||
| e41573ca74 | |||
| 4c5c99e6ae | |||
| dcb940ba95 | |||
| 8d3b66f7e3 | |||
| bc89b6ea74 | |||
| f0742dffa2 | |||
| 6c71a1020d | |||
| 1db3e43adf | |||
| cb59b0b5e4 | |||
| 8e0f05055e | |||
| 4768bacf1c | |||
| dc206c0999 | |||
| 77e1983b2e | |||
| d344ee226c | |||
| 3d0e4141bf | |||
| 01fb216ff7 | |||
| a662b2a6c6 | |||
| b1af82eba8 | |||
| 378ef5246e | |||
| 606814f10e | |||
| 5e06a0d001 | |||
| c0e3274375 | |||
| 119ec5e405 | |||
| 79efa51941 |
@@ -1 +0,0 @@
|
||||
OPENAI_API_KEY=
|
||||
@@ -5,7 +5,7 @@ body:
|
||||
- type: markdown
|
||||
attributes:
|
||||
value: >
|
||||
#### Before submitting a bug, please make sure the issue hasn't been already addressed by searching through [the existing and past issues](https://github.com/gventuri/pandas-ai/issues?q=is%3Aissue+sort%3Acreated-desc+).
|
||||
#### Before submitting a bug, please make sure the issue hasn't been already addressed by searching through [the existing and past issues](https://github.com/embedchain/embedchain/issues?q=is%3Aissue+sort%3Acreated-desc+).
|
||||
- type: textarea
|
||||
attributes:
|
||||
label: 🐛 Describe the bug
|
||||
|
||||
@@ -2,14 +2,13 @@ name: Publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [published] # This will trigger the workflow when you create a new release
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
build-n-publish:
|
||||
name: Build and publish Python 🐍 distributions 📦 to PyPI and TestPyPI
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# IMPORTANT: this permission is mandatory for trusted publishing
|
||||
id-token: write
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
@@ -23,18 +22,25 @@ jobs:
|
||||
run: |
|
||||
curl -sSL https://install.python-poetry.org | python3 -
|
||||
echo "$HOME/.local/bin" >> $GITHUB_PATH
|
||||
|
||||
|
||||
- name: Install dependencies
|
||||
run: poetry install
|
||||
|
||||
run: |
|
||||
cd embedchain
|
||||
poetry install
|
||||
|
||||
- name: Build a binary wheel and a source tarball
|
||||
run: poetry build
|
||||
run: |
|
||||
cd embedchain
|
||||
poetry build
|
||||
|
||||
- name: Publish distribution 📦 to Test PyPI
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
repository_url: https://test.pypi.org/legacy/
|
||||
packages_dir: embedchain/dist/
|
||||
|
||||
- name: Publish distribution 📦 to PyPI
|
||||
if: startsWith(github.ref, 'refs/tags')
|
||||
uses: pypa/gh-action-pypi-publish@release/v1
|
||||
with:
|
||||
packages_dir: embedchain/dist/
|
||||
@@ -3,15 +3,41 @@ name: ci
|
||||
on:
|
||||
push:
|
||||
branches: [main]
|
||||
paths:
|
||||
- 'mem0/**'
|
||||
- 'tests/**'
|
||||
- 'embedchain/**'
|
||||
pull_request:
|
||||
paths:
|
||||
- 'mem0/**'
|
||||
- 'tests/**'
|
||||
- 'embedchain/**'
|
||||
|
||||
jobs:
|
||||
build:
|
||||
check_changes:
|
||||
runs-on: ubuntu-latest
|
||||
outputs:
|
||||
mem0_changed: ${{ steps.filter.outputs.mem0 }}
|
||||
embedchain_changed: ${{ steps.filter.outputs.embedchain }}
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: dorny/paths-filter@v2
|
||||
id: filter
|
||||
with:
|
||||
filters: |
|
||||
mem0:
|
||||
- 'mem0/**'
|
||||
- 'tests/**'
|
||||
embedchain:
|
||||
- 'embedchain/**'
|
||||
|
||||
build_mem0:
|
||||
needs: check_changes
|
||||
if: needs.check_changes.outputs.mem0_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10", "3.11"]
|
||||
|
||||
python-version: ["3.10", "3.11"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
@@ -19,10 +45,58 @@ jobs:
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
run: pip install poetry==1.4.2
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: 1.4.2
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .venv
|
||||
key: venv-mem0-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
|
||||
- name: Install dependencies
|
||||
run: poetry install --all-extras
|
||||
run: make install_all
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
- name: Run tests and generate coverage report
|
||||
run: make test
|
||||
|
||||
build_embedchain:
|
||||
needs: check_changes
|
||||
if: needs.check_changes.outputs.embedchain_changed == 'true'
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
matrix:
|
||||
python-version: ["3.9", "3.10", "3.11"]
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- name: Set up Python ${{ matrix.python-version }}
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: ${{ matrix.python-version }}
|
||||
- name: Install poetry
|
||||
uses: snok/install-poetry@v1
|
||||
with:
|
||||
version: 1.4.2
|
||||
virtualenvs-create: true
|
||||
virtualenvs-in-project: true
|
||||
- name: Load cached venv
|
||||
id: cached-poetry-dependencies
|
||||
uses: actions/cache@v2
|
||||
with:
|
||||
path: .venv
|
||||
key: venv-embedchain-${{ runner.os }}-${{ hashFiles('**/poetry.lock') }}
|
||||
- name: Install dependencies
|
||||
run: cd embedchain && make install_all
|
||||
if: steps.cached-poetry-dependencies.outputs.cache-hit != 'true'
|
||||
- name: Lint with ruff
|
||||
run: make ci_lint
|
||||
- name: Test with pytest
|
||||
run: make ci_test
|
||||
run: cd embedchain && make lint
|
||||
- name: Run tests and generate coverage report
|
||||
run: cd embedchain && make coverage
|
||||
- name: Upload coverage reports to Codecov
|
||||
uses: codecov/codecov-action@v3
|
||||
with:
|
||||
file: coverage.xml
|
||||
env:
|
||||
CODECOV_TOKEN: ${{ secrets.CODECOV_TOKEN }}
|
||||
@@ -76,7 +76,6 @@ docs/_build/
|
||||
target/
|
||||
|
||||
# Jupyter Notebook
|
||||
.ipynb_checkpoints
|
||||
|
||||
# IPython
|
||||
profile_default/
|
||||
@@ -165,9 +164,23 @@ cython_debug/
|
||||
|
||||
# Database
|
||||
db
|
||||
test-db
|
||||
!embedchain/embedchain/core/db/
|
||||
|
||||
.vscode
|
||||
/poetry.lock
|
||||
.idea/
|
||||
|
||||
.DS_Store
|
||||
|
||||
notebooks/*.yaml
|
||||
.ipynb_checkpoints/
|
||||
|
||||
!configs/*.yaml
|
||||
|
||||
# cache db
|
||||
*.db
|
||||
|
||||
# local directories for testing
|
||||
eval/
|
||||
qdrant_storage/
|
||||
.crossnote
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
repos:
|
||||
- repo: https://github.com/psf/black
|
||||
rev: 23.3.0
|
||||
hooks:
|
||||
- id: black
|
||||
- repo: https://github.com/charliermarsh/ruff-pre-commit
|
||||
rev: 'v0.0.220'
|
||||
hooks:
|
||||
- id: ruff
|
||||
name: ruff
|
||||
# Respect `exclude` and `extend-exclude` settings.
|
||||
args: ["--force-exclude"]
|
||||
- repo: local
|
||||
hooks:
|
||||
- id: pytest-check
|
||||
name: pytest-check
|
||||
entry: poetry run pytest
|
||||
language: system
|
||||
pass_filenames: false
|
||||
always_run: true
|
||||
@@ -1,30 +1,42 @@
|
||||
# Variables
|
||||
PYTHON := python3
|
||||
PIP := $(PYTHON) -m pip
|
||||
PROJECT_NAME := embedchain
|
||||
.PHONY: format sort lint
|
||||
|
||||
# Targets
|
||||
.PHONY: install format lint clean test ci_lint ci_test
|
||||
# Variables
|
||||
ISORT_OPTIONS = --profile black
|
||||
PROJECT_NAME := mem0ai
|
||||
|
||||
# Default target
|
||||
all: format sort lint
|
||||
|
||||
install:
|
||||
$(PIP) install --upgrade pip
|
||||
$(PIP) install -e .[dev]
|
||||
poetry install
|
||||
|
||||
install_all:
|
||||
poetry install
|
||||
poetry run pip install groq together boto3 litellm ollama
|
||||
|
||||
# Format code with ruff
|
||||
format:
|
||||
$(PYTHON) -m black .
|
||||
$(PYTHON) -m isort .
|
||||
poetry run ruff check . --fix $(RUFF_OPTIONS)
|
||||
|
||||
# Sort imports with isort
|
||||
sort:
|
||||
poetry run isort . $(ISORT_OPTIONS)
|
||||
|
||||
# Lint code with ruff
|
||||
lint:
|
||||
$(PYTHON) -m ruff .
|
||||
|
||||
clean:
|
||||
rm -rf dist build *.egg-info
|
||||
|
||||
test:
|
||||
$(PYTHON) -m pytest
|
||||
|
||||
ci_lint:
|
||||
poetry run ruff .
|
||||
|
||||
ci_test:
|
||||
poetry run pytest
|
||||
docs:
|
||||
cd docs && mintlify dev
|
||||
|
||||
build:
|
||||
poetry build
|
||||
|
||||
publish:
|
||||
poetry publish
|
||||
|
||||
clean:
|
||||
poetry run rm -rf dist
|
||||
|
||||
test:
|
||||
poetry run pytest tests
|
||||
|
||||
@@ -1,96 +1,212 @@
|
||||
# embedchain
|
||||
<p align="center">
|
||||
<img src="docs/images/banner.png" width="800px" alt="Mem0 Logo">
|
||||
</p>
|
||||
|
||||
[](https://pypi.org/project/embedchain/)
|
||||
[](https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw)
|
||||
[](https://discord.gg/CUU9FPhRNt)
|
||||
[](https://twitter.com/embedchain)
|
||||
[](https://embedchain.substack.com/)
|
||||
[](https://colab.research.google.com/drive/138lMWhENGeEu7Q1-6lNbNTHGLZXBBz_B?usp=sharing)
|
||||
<p align="center">
|
||||
<a href="https://mem0.ai/slack">
|
||||
<img src="https://img.shields.io/badge/slack-mem0-brightgreen.svg?logo=slack" alt="Mem0 Slack">
|
||||
</a>
|
||||
<a href="https://mem0.ai/discord">
|
||||
<img src="https://dcbadge.vercel.app/api/server/6PzXDgEjG5?style=flat" alt="Mem0 Discord">
|
||||
</a>
|
||||
<a href="https://x.com/mem0ai">
|
||||
<img src="https://img.shields.io/twitter/follow/mem0ai" alt="Mem0 Twitter">
|
||||
</a>
|
||||
<a href="https://www.ycombinator.com/companies/mem0"><img src="https://img.shields.io/badge/Y%20Combinator-S24-orange?style=flat-square" alt="Y Combinator S24"></a>
|
||||
<a href="https://www.npmjs.com/package/mem0ai"><img src="https://img.shields.io/npm/v/mem0ai?style=flat-square&label=npm+mem0ai" alt="mem0ai npm package"></a>
|
||||
<a href="https://pypi.python.org/pypi/mem0ai"><img src="https://img.shields.io/pypi/v/mem0ai.svg?style=flat-square&label=pypi+mem0ai" alt="mem0ai Python package on PyPi"></a>
|
||||
<a href="https://mem0.ai/email"><img src="https://img.shields.io/badge/substack-mem0-brightgreen.svg?logo=substack&label=mem0+substack" alt="Mem0 newsletter"></a>
|
||||
</p>
|
||||
|
||||
Embedchain is a framework to easily create LLM powered bots over any dataset. If you want a javascript version, check out [embedchain-js](https://github.com/embedchain/embedchainjs)
|
||||
# Mem0: The Memory Layer for Personalized AI
|
||||
|
||||
## Community
|
||||
Mem0 provides an intelligent, adaptive memory layer for Large Language Models (LLMs), enhancing personalized AI experiences by retaining and utilizing contextual information across diverse applications. This enhanced memory capability is crucial for applications ranging from customer support and healthcare diagnostics to autonomous systems and personalized content recommendations, allowing AI to remember user preferences, adapt to individual needs, and continuously improve over time.
|
||||
|
||||
* Join embedchain community on slack by accpeting [this invite](https://join.slack.com/t/embedchain/shared_invite/zt-22uwz3c46-Zg7cIh5rOBteT_xe1jwLDw)
|
||||
## 🚀 Quickstart
|
||||
|
||||
## 🤝 Schedule a 1-on-1 Session
|
||||
### Installation
|
||||
|
||||
Book a [1-on-1 Session](https://cal.com/taranjeetio/ec) with Taranjeet, the founder, to discuss any issues, provide feedback, or explore how we can improve Embedchain for you.
|
||||
|
||||
## 🔧 Quick install
|
||||
The Mem0 package can be installed directly from pip command in the terminal.
|
||||
|
||||
```bash
|
||||
pip install --upgrade embedchain
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
## 🔍 Demo
|
||||
### Basic Usage (Open Source)
|
||||
|
||||
Try out embedchain in your browser:
|
||||
|
||||
[](https://colab.research.google.com/drive/138lMWhENGeEu7Q1-6lNbNTHGLZXBBz_B?usp=sharing)
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
The documentation for embedchain can be found at [docs.embedchain.ai](https://docs.embedchain.ai).
|
||||
|
||||
## 💻 Usage
|
||||
|
||||
Embedchain empowers you to create chatbot models similar to ChatGPT, using your own evolving dataset.
|
||||
|
||||
### Data Types Supported
|
||||
|
||||
* Youtube video
|
||||
* PDF file
|
||||
* Web page
|
||||
* Sitemap
|
||||
* Doc file
|
||||
* Code documentation website loader
|
||||
* Notion
|
||||
|
||||
### Queries
|
||||
|
||||
For example, you can use Embedchain to create an Elon Musk bot using the following code:
|
||||
Mem0 supports various LLMs, details of which can be found in our docs, checkout [Supported LLMs](https://docs.mem0.ai/llms). By default, Mem0 is equipped with ```gpt-4o```, and to use it, you need to set the keys in the environment variable.
|
||||
|
||||
```python
|
||||
import os
|
||||
from embedchain import App
|
||||
|
||||
# Create a bot instance
|
||||
os.environ["OPENAI_API_KEY"] = "YOUR API KEY"
|
||||
elon_bot = App()
|
||||
|
||||
# Embed online resources
|
||||
elon_bot.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
elon_bot.add("https://tesla.com/elon-musk")
|
||||
elon_bot.add("https://www.youtube.com/watch?v=MxZpaJK74Y4")
|
||||
|
||||
# Query the bot
|
||||
elon_bot.query("How many companies does Elon Musk run?")
|
||||
# Answer: Elon Musk runs four companies: Tesla, SpaceX, Neuralink, and The Boring Company
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxx"
|
||||
```
|
||||
|
||||
## 🤝 Contributing
|
||||
Now, you can simply initialize the memory.
|
||||
|
||||
Contributions are welcome! Please check out the issues on the repository, and feel free to open a pull request.
|
||||
For more information, please see the [contributing guidelines](CONTRIBUTING.md).
|
||||
|
||||
For more reference, please go through [Development Guide](https://docs.embedchain.ai/contribution/dev) and [Documentation Guide](https://docs.embedchain.ai/contribution/docs).
|
||||
|
||||
<a href="https://github.com/embedchain/embedchain/graphs/contributors">
|
||||
<img src="https://contrib.rocks/image?repo=embedchain/embedchain" />
|
||||
</a>
|
||||
|
||||
## Citation
|
||||
|
||||
If you utilize this repository, please consider citing it with:
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
m = Memory()
|
||||
```
|
||||
@misc{embedchain,
|
||||
author = {Taranjeet Singh},
|
||||
title = {Embedchain: Framework to easily create LLM powered bots over any dataset},
|
||||
year = {2023},
|
||||
publisher = {GitHub},
|
||||
journal = {GitHub repository},
|
||||
howpublished = {\url{https://github.com/embedchain/embedchain}},
|
||||
|
||||
You can perform the following task on the memory.
|
||||
1. Add: adds memory
|
||||
2. Update: update memory of a given memory_id
|
||||
3. Search: fetch memories based on a query
|
||||
4. Get: return memories for a certain user/agent/session
|
||||
5. History: describes how a memory has changed over time for a specific memory ID
|
||||
|
||||
```python
|
||||
# 1. Add: Store a memory from any unstructured text
|
||||
result = m.add("I am working on improving my tennis skills. Suggest some online courses.", user_id="alice", metadata={"category": "hobbies"})
|
||||
|
||||
# Created memory --> 'Improving her tennis skills.' and 'Looking for online suggestions.'
|
||||
```
|
||||
|
||||
```python
|
||||
# 2. Update: update the memory
|
||||
result = m.update(memory_id=<memory_id_1>, data="Likes to play tennis on weekends")
|
||||
|
||||
# Updated memory --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'
|
||||
```
|
||||
|
||||
```python
|
||||
# 3. Search: search related memories
|
||||
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
|
||||
# Retrieved memory --> 'Likes to play tennis on weekends'
|
||||
```
|
||||
|
||||
```python
|
||||
# 4. Get all memories
|
||||
all_memories = m.get_all()
|
||||
memory_id = all_memories[0]["id"] # get a memory_id
|
||||
|
||||
# All memory items --> 'Likes to play tennis on weekends.' and 'Looking for online suggestions.'
|
||||
```
|
||||
|
||||
```python
|
||||
# 5. Get memory history for a particular memory_id
|
||||
history = m.history(memory_id=<memory_id_1>)
|
||||
|
||||
# Logs corresponding to memory_id_1 --> {'prev_value': 'Working on improving tennis skills and interested in online courses for tennis.', 'new_value': 'Likes to play tennis on weekends' }
|
||||
```
|
||||
|
||||
### Mem0 Platform
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
client = MemoryClient(api_key="your-api-key") # get api_key from https://app.mem0.ai/
|
||||
|
||||
# Store messages
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
result = client.add(messages, user_id="alex")
|
||||
print(result)
|
||||
|
||||
# Retrieve memories
|
||||
all_memories = client.get_all(user_id="alex")
|
||||
print(all_memories)
|
||||
|
||||
# Search memories
|
||||
query = "What do you know about me?"
|
||||
related_memories = client.search(query, user_id="alex")
|
||||
|
||||
# Get memory history
|
||||
history = client.history(memory_id="m1")
|
||||
print(history)
|
||||
```
|
||||
|
||||
> [!TIP]
|
||||
> If you are looking for a hosted version and don't want to setup the infrastucture yourself, checkout [Mem0 Platform Docs](https://docs.mem0.ai/platform/quickstart) to get started in minutes.
|
||||
|
||||
## 🔑 Core Features
|
||||
|
||||
- **Multi-Level Memory**: User, Session, and AI Agent memory retention
|
||||
- **Adaptive Personalization**: Continuous improvement based on interactions
|
||||
- **Developer-Friendly API**: Simple integration into various applications
|
||||
- **Cross-Platform Consistency**: Uniform behavior across devices
|
||||
- **Managed Service**: Hassle-free hosted solution
|
||||
|
||||
## 📖 Documentation
|
||||
|
||||
For detailed usage instructions and API reference, visit our documentation at [docs.mem0.ai](https://docs.mem0.ai).
|
||||
|
||||
## 🔧 Advanced Usage
|
||||
|
||||
For production environments, you can use Qdrant as a vector store:
|
||||
|
||||
```python
|
||||
from mem0 import Memory
|
||||
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
|
||||
## 🗺️ Roadmap
|
||||
|
||||
- Integration with various LLM providers
|
||||
- Support for LLM frameworks
|
||||
- Integration with AI Agents frameworks
|
||||
- Customizable memory creation/update rules
|
||||
- Hosted platform support
|
||||
|
||||
## 💰 Pricing
|
||||
|
||||
Choose the Mem0 plan that best fits your needs:
|
||||
|
||||
### Open Source (Self-hosted)
|
||||
Perfect for developers and small teams who want full control over their infrastructure.
|
||||
|
||||
### Pro (Hosted)
|
||||
Ideal for growing businesses that need a reliable, managed solution with generous free usage. Try the platform [here](https://app.mem0.ai)
|
||||
|
||||
### Enterprise (Hosted)
|
||||
Designed for large organizations with advanced security, compliance, and scalability needs.
|
||||
|
||||
| Feature | Open Source | Pro | Enterprise |
|
||||
|---------|-------------|-----|------------|
|
||||
| Hosting | Self-hosted | Hosted | Hosted |
|
||||
| API Calls | Unlimited | 100K free/month | Custom limits |
|
||||
| Support | Community | Email | Dedicated support |
|
||||
| Updates | Manual | Automatic | Automatic |
|
||||
| SSO | ❌ | ❌ | ✅ |
|
||||
| Audit Logs | ❌ | ❌ | ✅ |
|
||||
| Custom Integrations | ❌ | ❌ | ✅ |
|
||||
| SLA | ❌ | ❌ | ✅ |
|
||||
| Advanced Analytics | ❌ | Basic | Advanced |
|
||||
| Multi-region Deployment | ❌ | ❌ | ✅ |
|
||||
|
||||
[Contact us](mailto:taranjeet@mem0.ai) for Enterprise pricing and custom solutions.
|
||||
|
||||
## Star History
|
||||
|
||||
[](https://star-history.com/#mem0ai/mem0&Date)
|
||||
|
||||
## 🙋♂️ Support
|
||||
Join our Slack or Discord community for support and discussions.
|
||||
If you have any questions, feel free to reach out to us using one of the following methods:
|
||||
|
||||
- [Join our Discord](https://mem0.ai/discord)
|
||||
- [Join our Slack](https://mem0.ai/slack)
|
||||
- [Join our newsletter](https://mem0.ai/email)
|
||||
- [Follow us on Twitter](https://x.com/mem0ai)
|
||||
- [Email us](mailto:founders@mem0.ai)
|
||||
|
||||
## 📝 License
|
||||
|
||||
This project is licensed under the Apache 2.0 License - see the [LICENSE](LICENSE) file for details.
|
||||
|
||||
> [!NOTE]
|
||||
> The Mem0 repository now also includes the Embedchain project. We continue to maintain and support Embedchain ❤️. You can find the Embedchain codebase in the [embedchain](https://github.com/mem0ai/mem0/tree/main/embedchain) directory.
|
||||
@@ -0,0 +1,306 @@
|
||||
{
|
||||
"cells": [
|
||||
{
|
||||
"cell_type": "code",
|
||||
"source": [
|
||||
"!pip install mem0ai"
|
||||
],
|
||||
"metadata": {
|
||||
"id": "fu3euPKZsbaC"
|
||||
},
|
||||
"execution_count": null,
|
||||
"outputs": []
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "U2VC_0FElQid"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"import os\n",
|
||||
"from openai import OpenAI\n",
|
||||
"from mem0 import MemoryClient\n",
|
||||
"from multion.client import MultiOn\n",
|
||||
"\n",
|
||||
"# Configuration\n",
|
||||
"OPENAI_API_KEY = 'sk-xxx' # Replace with your actual OpenAI API key\n",
|
||||
"MULTION_API_KEY = 'xx' # Replace with your actual MultiOn API key\n",
|
||||
"MEM0_API_KEY = 'xx' # Replace with your actual Mem0 API key\n",
|
||||
"USER_ID = \"test_travel_agent\"\n",
|
||||
"\n",
|
||||
"# Set up OpenAI API key\n",
|
||||
"os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY\n",
|
||||
"\n",
|
||||
"# Initialize Mem0 and MultiOn\n",
|
||||
"memory = MemoryClient(api_key=MEM0_API_KEY)\n",
|
||||
"multion = MultiOn(api_key=MULTION_API_KEY)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "sq-OdPHKlQie",
|
||||
"outputId": "1d605222-0bf5-4ac9-99b9-6059b502c20b"
|
||||
},
|
||||
"outputs": [
|
||||
{
|
||||
"data": {
|
||||
"text/plain": [
|
||||
"{'message': 'Memory added successfully!'}"
|
||||
]
|
||||
},
|
||||
"execution_count": 2,
|
||||
"metadata": {},
|
||||
"output_type": "execute_result"
|
||||
}
|
||||
],
|
||||
"source": [
|
||||
"# Add conversation to Mem0\n",
|
||||
"conversation = [\n",
|
||||
" {\n",
|
||||
" \"role\": \"user\",\n",
|
||||
" \"content\": \"What are the best travel destinations in the world?\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"assistant\",\n",
|
||||
" \"content\": \"Could you please specify your interests or the type of travel information you are looking for? This will help me find the most relevant information for you.\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"user\",\n",
|
||||
" \"content\": \"Sure, I want to travel to San Francisco.\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"assistant\",\n",
|
||||
" \"content\": \"\"\"\n",
|
||||
" Based on the information gathered from TripAdvisor, here are some popular attractions, activities, and travel tips for San Francisco:\n",
|
||||
"\n",
|
||||
" 1. **Golden Gate Bridge**: A must-see iconic landmark.\n",
|
||||
" 2. **Alcatraz Island**: Famous former prison offering tours.\n",
|
||||
" 3. **Fisherman's Wharf**: Popular tourist area with shops, restaurants, and sea lions.\n",
|
||||
" 4. **Chinatown**: The largest Chinatown outside of Asia.\n",
|
||||
" 5. **Golden Gate Park**: Large urban park with gardens, museums, and recreational activities.\n",
|
||||
" 6. **Cable Cars**: Historic streetcars offering a unique way to see the city.\n",
|
||||
" 7. **Exploratorium**: Interactive science museum.\n",
|
||||
" 8. **San Francisco Museum of Modern Art (SFMOMA)**: Modern and contemporary art museum.\n",
|
||||
" 9. **Lombard Street**: Known for its steep, one-block section with eight hairpin turns.\n",
|
||||
" 10. **Union Square**: Major shopping and cultural hub.\n",
|
||||
"\n",
|
||||
" Travel Tips:\n",
|
||||
" - **Weather**: San Francisco has a mild climate, but it can be foggy and windy. Dress in layers.\n",
|
||||
" - **Transportation**: Use public transportation like BART, Muni, and cable cars to get around.\n",
|
||||
" - **Safety**: Be aware of your surroundings, especially in crowded tourist areas.\n",
|
||||
" - **Dining**: Try local specialties like sourdough bread, seafood, and Mission-style burritos.\n",
|
||||
" \"\"\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"user\",\n",
|
||||
" \"content\": \"Show me hotels around Golden Gate Bridge.\"\n",
|
||||
" },\n",
|
||||
" {\n",
|
||||
" \"role\": \"assistant\",\n",
|
||||
" \"content\": \"\"\"\n",
|
||||
" The search results for hotels around Golden Gate Bridge in San Francisco include:\n",
|
||||
"\n",
|
||||
" 1. Hilton Hotels In San Francisco - Hotel Near Fishermans Wharf (hilton.com)\n",
|
||||
" 2. The 10 Closest Hotels to Golden Gate Bridge (tripadvisor.com)\n",
|
||||
" 3. Hotels near Golden Gate Bridge (expedia.com)\n",
|
||||
" 4. Hotels near Golden Gate Bridge (hotels.com)\n",
|
||||
" 5. Holiday Inn Express & Suites San Francisco Fishermans Wharf, an IHG Hotel $146 (1.8K) 3-star hotel Golden Gate Bridge • 3.5 mi DEAL 19% less than usual\n",
|
||||
" 6. Holiday Inn San Francisco-Golden Gateway, an IHG Hotel $151 (3.5K) 3-star hotel Golden Gate Bridge • 3.7 mi Casual hotel with dining, a bar & a pool\n",
|
||||
" 7. Hotel Zephyr San Francisco $159 (3.8K) 4-star hotel Golden Gate Bridge • 3.7 mi Nautical-themed lodging with bay views\n",
|
||||
" 8. Lodge at the Presidio\n",
|
||||
" 9. The Inn Above Tide\n",
|
||||
" 10. Cavallo Point\n",
|
||||
" 11. Casa Madrona Hotel and Spa\n",
|
||||
" 12. Cow Hollow Inn and Suites\n",
|
||||
" 13. Samesun San Francisco\n",
|
||||
" 14. Inn on Broadway\n",
|
||||
" 15. Coventry Motor Inn\n",
|
||||
" 16. HI San Francisco Fisherman's Wharf Hostel\n",
|
||||
" 17. Loews Regency San Francisco Hotel\n",
|
||||
" 18. Fairmont Heritage Place Ghirardelli Square\n",
|
||||
" 19. Hotel Drisco Pacific Heights\n",
|
||||
" 20. Travelodge by Wyndham Presidio San Francisco\n",
|
||||
" \"\"\"\n",
|
||||
" }\n",
|
||||
"]\n",
|
||||
"\n",
|
||||
"memory.add(conversation, user_id=USER_ID)\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "hO8z9aNTlQif"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"def get_travel_info(question, use_memory=True):\n",
|
||||
" \"\"\"\n",
|
||||
" Get travel information based on user's question and optionally their preferences from memory.\n",
|
||||
"\n",
|
||||
" \"\"\"\n",
|
||||
" if use_memory:\n",
|
||||
" previous_memories = memory.search(question, user_id=USER_ID)\n",
|
||||
" relevant_memories_text = \"\"\n",
|
||||
" if previous_memories:\n",
|
||||
" print(\"Using previous memories to enhance the search...\")\n",
|
||||
" relevant_memories_text = '\\n'.join(mem[\"memory\"] for mem in previous_memories)\n",
|
||||
"\n",
|
||||
" command = \"Find travel information based on my interests:\"\n",
|
||||
" prompt = f\"{command}\\n Question: {question} \\n My preferences: {relevant_memories_text}\"\n",
|
||||
" else:\n",
|
||||
" command = \"Find travel information based on my interests:\"\n",
|
||||
" prompt = f\"{command}\\n Question: {question}\"\n",
|
||||
"\n",
|
||||
"\n",
|
||||
" print(\"Searching for travel information...\")\n",
|
||||
" browse_result = multion.browse(cmd=prompt)\n",
|
||||
" return browse_result.message"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "Wp2xpzMrlQig"
|
||||
},
|
||||
"source": [
|
||||
"## Example 1"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "bPRPwqsplQig"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"question = \"Show me flight details for it.\"\n",
|
||||
"answer_without_memory = get_travel_info(question, use_memory=False)\n",
|
||||
"answer_with_memory = get_travel_info(question, use_memory=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "a76ifa2HlQig"
|
||||
},
|
||||
"source": [
|
||||
"| Without Memory | With Memory |\n",
|
||||
"|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
|
||||
"| I have performed a Google search for \"flight details\" and reviewed the search results. Here are some relevant links and information: | Memorizing the following information: Flight details for San Francisco: |\n",
|
||||
"| 1. **FlightStats Global Flight Tracker** - Track the real-time flight status of your flight. See if your flight has been delayed or cancelled and track the live status. <br> [Flight Tracker - FlightStats](https://www.flightstats.com/flight-tracker/search) | 1. Prices from $232. Depart Thursday, August 22. Return Thursday, August 29. <br> 2. Prices from $216. Depart Friday, August 23. Return Friday, August 30. <br> 3. Prices from $236. Depart Saturday, August 24. Return Saturday, August 31. <br> 4. Prices from $215. Depart Sunday, August 25. Return Sunday, September 1. |\n",
|
||||
"| 2. **FlightAware - Flight Tracker** - Track live flights worldwide, see flight cancellations, and browse by airport. <br> [FlightAware - Flight Tracker](https://www.flightaware.com) | 5. Prices from $218. Depart Monday, August 26. Return Monday, September 2. <br> 6. Prices from $211. Depart Tuesday, August 27. Return Tuesday, September 3. <br> 7. Prices from $198. Depart Wednesday, August 28. Return Wednesday, September 4. <br> 8. Prices from $218. Depart Thursday, August 29. Return Thursday, September 5. |\n",
|
||||
"| 3. **Google Flights** - Show flights based on your search. <br> [Google Flights](https://www.google.com/flights) | 9. Prices from $194. Depart Friday, August 30. Return Friday, September 6. <br> 10. Prices from $218. Depart Saturday, August 31. Return Saturday, September 7. <br> 11. Prices from $212. Depart Sunday, September 1. Return Sunday, September 8. <br> 12. Prices from $247. Depart Monday, September 2. Return Monday, September 9. |\n",
|
||||
"| | 13. Prices from $212. Depart Tuesday, September 3. Return Tuesday, September 10. <br> 14. Prices from $203. Depart Wednesday, September 4. Return Wednesday, September 11. <br> 15. Prices from $242. Depart Thursday, September 5. Return Thursday, September 12. <br> 16. Prices from $191. Depart Friday, September 6. Return Friday, September 13. |\n",
|
||||
"| | 17. Prices from $215. Depart Saturday, September 7. Return Saturday, September 14. <br> 18. Prices from $229. Depart Sunday, September 8. Return Sunday, September 15. <br> 19. Prices from $183. Depart Monday, September 9. Return Monday, September 16. <br> 65. Prices from $194. Depart Friday, October 25. Return Friday, November 1. |\n",
|
||||
"| | 66. Prices from $205. Depart Saturday, October 26. Return Saturday, November 2. <br> 67. Prices from $241. Depart Sunday, October 27. Return Sunday, November 3. |\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "0cXpiAwMlQig"
|
||||
},
|
||||
"source": [
|
||||
"## Example 2"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "LpprKfpslQih"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"question = \"What places to visit there?\"\n",
|
||||
"answer_without_memory = get_travel_info(question, use_memory=False)\n",
|
||||
"answer_with_memory = get_travel_info(question, use_memory=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "kpfjeY1_lQih"
|
||||
},
|
||||
"source": [
|
||||
"| Without Memory | With Memory |\n",
|
||||
"|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
|
||||
"| Based on the information gathered, here are some top travel destinations to consider visiting: | Based on the information gathered, here are some top places to visit in San Francisco: |\n",
|
||||
"| 1. **Paris**: Known for its iconic attractions like the Eiffel Tower and the Louvre, Paris offers quaint cafes, trendy shopping districts, and beautiful Haussmann architecture. It's a city where you can always discover something new with each visit. | 1. **Golden Gate Bridge** - An iconic symbol of San Francisco, perfect for walking, biking, or simply enjoying the view. <br> 2. **Alcatraz Island** - The historic former prison offers tours and insights into its storied past. <br> 3. **Fisherman's Wharf** - A bustling waterfront area known for its seafood, shopping, and attractions like Pier 39. <br> 4. **Golden Gate Park** - A large urban park with gardens, museums, and recreational activities. <br> 5. **Chinatown San Francisco** - One of the oldest and most famous Chinatowns in North America, offering unique shops and delicious food. <br> 6. **Coit Tower** - Offers panoramic views of the city and murals depicting San Francisco's history. <br> 7. **Lands End** - A beautiful coastal trail with stunning views of the Pacific Ocean and the Golden Gate Bridge. <br> 8. **Palace of Fine Arts** - A picturesque structure and park, perfect for a leisurely stroll or photo opportunities. <br> 9. **Crissy Field & The Presidio Tunnel Tops** - Great for outdoor activities and scenic views of the bay. |\n",
|
||||
"| 2. **Bora Bora**: This small island in French Polynesia is famous for its stunning turquoise waters, luxurious overwater bungalows, and vibrant coral reefs. It's a popular destination for honeymooners and those seeking a tropical paradise. | |\n",
|
||||
"| 3. **Glacier National Park**: Located in Montana, USA, this park is known for its breathtaking landscapes, including rugged mountains, pristine lakes, and diverse wildlife. It's a haven for outdoor enthusiasts and hikers. | |\n",
|
||||
"| 4. **Rome**: The capital of Italy, Rome is rich in history and culture, featuring landmarks such as the Colosseum, the Vatican, and the Pantheon. It's a city where ancient history meets modern life. | |\n",
|
||||
"| 5. **Swiss Alps**: Renowned for their stunning natural beauty, the Swiss Alps offer opportunities for skiing, hiking, and enjoying picturesque mountain villages. | |\n",
|
||||
"| 6. **Maui**: One of Hawaii's most popular islands, Maui is known for its beautiful beaches, lush rainforests, and the scenic Hana Highway. It's a great destination for both relaxation and adventure. | |\n",
|
||||
"| 7. **London, England**: A vibrant city with a mix of historical landmarks like the Tower of London and modern attractions such as the London Eye. London offers diverse cultural experiences, world-class museums, and a bustling nightlife. | |\n",
|
||||
"| 8. **Maldives**: This tropical paradise in the Indian Ocean is famous for its crystal-clear waters, luxurious resorts, and abundant marine life. It's an ideal destination for snorkeling, diving, and relaxation. | |\n",
|
||||
"| 9. **Turks & Caicos**: Known for its pristine beaches and turquoise waters, this Caribbean destination is perfect for water sports, beach lounging, and exploring coral reefs. | |\n",
|
||||
"| 10. **Tokyo**: Japan's bustling capital offers a unique blend of traditional and modern attractions, from ancient temples to futuristic skyscrapers. Tokyo is also known for its vibrant food scene and shopping districts. | |\n"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "XdpkcMrclQih"
|
||||
},
|
||||
"source": [
|
||||
"## Example 3"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "code",
|
||||
"execution_count": null,
|
||||
"metadata": {
|
||||
"id": "Nntl2FxulQih"
|
||||
},
|
||||
"outputs": [],
|
||||
"source": [
|
||||
"question = \"What the weather there?\"\n",
|
||||
"answer_without_memory = get_travel_info(question, use_memory=False)\n",
|
||||
"answer_with_memory = get_travel_info(question, use_memory=True)"
|
||||
]
|
||||
},
|
||||
{
|
||||
"cell_type": "markdown",
|
||||
"metadata": {
|
||||
"id": "yt2pj1irlQih"
|
||||
},
|
||||
"source": [
|
||||
"| Without Memory | With Memory |\n",
|
||||
"|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|--------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|\n",
|
||||
"| The current weather in Paris is light rain with a temperature of 67°F. The precipitation is at 50%, humidity is 95%, and the wind speed is 5 mph. | The current weather in San Francisco is as follows: <br> - **Temperature**: 59°F <br> - **Condition**: Clear with periodic clouds <br> - **Precipitation**: 3% <br> - **Humidity**: 87% <br> - **Wind**: 12 mph |\n"
|
||||
]
|
||||
}
|
||||
],
|
||||
"metadata": {
|
||||
"kernelspec": {
|
||||
"display_name": ".venv",
|
||||
"language": "python",
|
||||
"name": "python3"
|
||||
},
|
||||
"language_info": {
|
||||
"codemirror_mode": {
|
||||
"name": "ipython",
|
||||
"version": 3
|
||||
},
|
||||
"file_extension": ".py",
|
||||
"mimetype": "text/x-python",
|
||||
"name": "python",
|
||||
"nbconvert_exporter": "python",
|
||||
"pygments_lexer": "ipython3",
|
||||
"version": "3.12.3"
|
||||
},
|
||||
"colab": {
|
||||
"provenance": []
|
||||
}
|
||||
},
|
||||
"nbformat": 4,
|
||||
"nbformat_minor": 0
|
||||
}
|
||||
@@ -1,7 +1,14 @@
|
||||
# Contributing to embedchain docs
|
||||
# Mintlify Starter Kit
|
||||
|
||||
Click on `Use this template` to copy the Mintlify starter kit. The starter kit contains examples including
|
||||
|
||||
### 👩💻 Development
|
||||
- Guide pages
|
||||
- Navigation
|
||||
- Customizations
|
||||
- API Reference pages
|
||||
- Use of popular components
|
||||
|
||||
### Development
|
||||
|
||||
Install the [Mintlify CLI](https://www.npmjs.com/package/mintlify) to preview the documentation changes locally. To install, use the following command
|
||||
|
||||
@@ -15,9 +22,9 @@ Run the following command at the root of your documentation (where mint.json is)
|
||||
mintlify dev
|
||||
```
|
||||
|
||||
### 😎 Publishing Changes
|
||||
### Publishing Changes
|
||||
|
||||
Changes will be deployed to production automatically after your PR is merged to the main branch.
|
||||
Install our Github App to auto propagate changes from your repo to your deployment. Changes will be deployed to production automatically after pushing to the default branch. Find the link to install on your dashboard.
|
||||
|
||||
#### Troubleshooting
|
||||
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<CardGroup cols={3}>
|
||||
<Card title="Discord" icon="discord" href="https://mem0.ai/discord" color="#7289DA">
|
||||
Join our community
|
||||
</Card>
|
||||
<Card title="GitHub" icon="github" href="https://github.com/mem0ai/mem0">
|
||||
Star us on GitHub
|
||||
</Card>
|
||||
<Card title="Support" icon="calendar" href="mailto:taranjeet@mem0.ai">
|
||||
Talk to founders
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -1,25 +0,0 @@
|
||||
---
|
||||
title: '➕ Adding Data'
|
||||
---
|
||||
|
||||
## Add Dataset
|
||||
|
||||
- This step assumes that you have already created an `app` instance by either using `App`, `OpenSourceApp` or `CustomApp`. We are calling our app instance as `naval_chat_bot` 🤖
|
||||
|
||||
- Now use `.add` method to add any dataset.
|
||||
|
||||
```python
|
||||
# naval_chat_bot = App() or
|
||||
# naval_chat_bot = OpenSourceApp()
|
||||
|
||||
# Embed Online Resources
|
||||
naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||
naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf")
|
||||
naval_chat_bot.add("https://nav.al/feedback")
|
||||
naval_chat_bot.add("https://nav.al/agi")
|
||||
|
||||
# Embed Local Resources
|
||||
naval_chat_bot.add(("Who is Naval Ravikant?", "Naval Ravikant is an Indian-American entrepreneur and investor."))
|
||||
```
|
||||
|
||||
The possible formats to add data can be found on the [Supported Data Formats](/advanced/data_types) page.
|
||||
@@ -1,140 +0,0 @@
|
||||
---
|
||||
title: '📱 App types'
|
||||
---
|
||||
|
||||
## App Types
|
||||
|
||||
We have three types of App.
|
||||
|
||||
### App
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
app = App()
|
||||
```
|
||||
|
||||
- `App` uses OpenAI's model, so these are paid models. 💸 You will be charged for embedding model usage and LLM usage.
|
||||
- `App` uses OpenAI's embedding model to create embeddings for chunks and ChatGPT API as LLM to get answer given the relevant docs. Make sure that you have an OpenAI account and an API key. If you don't have an API key, you can create one by visiting [this link](https://platform.openai.com/account/api-keys).
|
||||
- `App` is opinionated. It uses the best embedding model and LLM on the market.
|
||||
- Once you have the API key, set it in an environment variable called `OPENAI_API_KEY`
|
||||
|
||||
```python
|
||||
import os
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
|
||||
```
|
||||
|
||||
### Llama2App
|
||||
|
||||
```python
|
||||
import os
|
||||
|
||||
from embedchain import Llama2App
|
||||
|
||||
os.environ['REPLICATE_API_TOKEN'] = "REPLICATE API TOKEN"
|
||||
|
||||
zuck_bot = Llama2App()
|
||||
|
||||
# Embed your data
|
||||
zuck_bot.add("https://www.youtube.com/watch?v=Ff4fRgnuFgQ")
|
||||
zuck_bot.add("https://en.wikipedia.org/wiki/Mark_Zuckerberg")
|
||||
|
||||
# Nice, your bot is ready now. Start asking questions to your bot.
|
||||
zuck_bot.query("Who is Mark Zuckerberg?")
|
||||
# Answer: Mark Zuckerberg is an American internet entrepreneur and business magnate. He is the co-founder and CEO of Facebook. Born in 1984, he dropped out of Harvard University to focus on his social media platform, which has since grown to become one of the largest and most influential technology companies in the world.
|
||||
|
||||
# Enable web search for your bot
|
||||
zuck_bot.online = True # enable internet access for the bot
|
||||
zuck_bot.query("Who owns the new threads app and when it was founded?")
|
||||
# Answer: Based on the context provided, the new Threads app is owned by Meta, the parent company of Facebook, Instagram, and WhatsApp.
|
||||
```
|
||||
|
||||
- `Llama2App` uses Replicate's LLM model, so these are paid models. You can get the `REPLICATE_API_TOKEN` by registering on [their website](https://replicate.com/account).
|
||||
- `Llama2App` uses OpenAI's embedding model to create embeddings for chunks. Make sure that you have an OpenAI account and an API key. If you don't have an API key, you can create one by visiting [this link](https://platform.openai.com/account/api-keys).
|
||||
|
||||
|
||||
### OpenSourceApp
|
||||
|
||||
```python
|
||||
from embedchain import OpenSourceApp
|
||||
app = OpenSourceApp()
|
||||
```
|
||||
|
||||
- `OpenSourceApp` uses open source embedding and LLM model. It uses `all-MiniLM-L6-v2` from Sentence Transformers library as the embedding model and `gpt4all` as the LLM.
|
||||
- Here there is no need to setup any api keys. You just need to install embedchain package and these will get automatically installed. 📦
|
||||
- Once you have imported and instantiated the app, every functionality from here onwards is the same for either type of app. 📚
|
||||
- `OpenSourceApp` is opinionated. It uses the best open source embedding model and LLM on the market.
|
||||
- extra dependencies are required for this app type. Install them with `pip install --upgrade embedchain[opensource]`.
|
||||
|
||||
### CustomApp
|
||||
|
||||
```python
|
||||
from embedchain import CustomApp
|
||||
from embedchain.config import (CustomAppConfig, ElasticsearchDBConfig,
|
||||
EmbedderConfig, LlmConfig)
|
||||
from embedchain.embedder.vertexai import VertexAiEmbedder
|
||||
from embedchain.llm.vertex_ai import VertexAiLlm
|
||||
from embedchain.models import EmbeddingFunctions, Providers
|
||||
from embedchain.vectordb.elasticsearch import Elasticsearch
|
||||
|
||||
# short
|
||||
app = CustomApp(llm=VertexAiLlm(), db=Elasticsearch(), embedder=VertexAiEmbedder())
|
||||
# with configs
|
||||
app = CustomApp(
|
||||
config=CustomAppConfig(log_level="INFO"),
|
||||
llm=VertexAiLlm(config=LlmConfig(number_documents=5)),
|
||||
db=Elasticsearch(config=ElasticsearchDBConfig(es_url="...")),
|
||||
embedder=VertexAiEmbedder(config=EmbedderConfig()),
|
||||
)
|
||||
```
|
||||
|
||||
- `CustomApp` is not opinionated.
|
||||
- Configuration required. It's for advanced users who want to mix and match different embedding models and LLMs.
|
||||
- while it's doing that, it's still providing abstractions by allowing you to import Classes from `embedchain.llm`, `embedchain.vectordb`, and `embedchain.embedder`.
|
||||
- paid and free/open source providers included.
|
||||
- Once you have imported and instantiated the app, every functionality from here onwards is the same for either type of app. 📚
|
||||
- Following providers are available for an LLM
|
||||
- OPENAI
|
||||
- ANTHPROPIC
|
||||
- VERTEX_AI
|
||||
- GPT4ALL
|
||||
- AZURE_OPENAI
|
||||
- LLAMA2
|
||||
- Following embedding functions are available for an embedding function
|
||||
- OPENAI
|
||||
- HUGGING_FACE
|
||||
- VERTEX_AI
|
||||
- GPT4ALL
|
||||
- AZURE_OPENAI
|
||||
|
||||
|
||||
### PersonApp
|
||||
|
||||
```python
|
||||
from embedchain import PersonApp
|
||||
naval_chat_bot = PersonApp("name_of_person_or_character") #Like "Yoda"
|
||||
```
|
||||
|
||||
- `PersonApp` uses OpenAI's model, so these are paid models. 💸 You will be charged for embedding model usage and LLM usage.
|
||||
- `PersonApp` uses OpenAI's embedding model to create embeddings for chunks and ChatGPT API as LLM to get answer given the relevant docs. Make sure that you have an OpenAI account and an API key. If you don't have an API key, you can create one by visiting [this link](https://platform.openai.com/account/api-keys).
|
||||
- Once you have the API key, set it in an environment variable called `OPENAI_API_KEY`
|
||||
|
||||
```python
|
||||
import os
|
||||
os.environ["OPENAI_API_KEY"] = "sk-xxxx"
|
||||
```
|
||||
|
||||
#### Compatibility with other apps
|
||||
|
||||
- If there is any other app instance in your script or app, you can change the import as
|
||||
|
||||
```python
|
||||
from embedchain import App as EmbedChainApp
|
||||
from embedchain import OpenSourceApp as EmbedChainOSApp
|
||||
from embedchain import PersonApp as EmbedChainPersonApp
|
||||
|
||||
# or
|
||||
|
||||
from embedchain import App as ECApp
|
||||
from embedchain import OpenSourceApp as ECOSApp
|
||||
from embedchain import PersonApp as ECPApp
|
||||
```
|
||||
@@ -1,104 +0,0 @@
|
||||
---
|
||||
title: '⚙️ Custom configurations'
|
||||
---
|
||||
|
||||
Embedchain is made to work out of the box. However, for advanced users we're also offering configuration options. All of these configuration options are optional and have sane defaults.
|
||||
|
||||
## Concept
|
||||
The main `App` class is available in the following varieties: `CustomApp`, `OpenSourceApp` and `Llama2App` and `App`. The first is fully configurable, the others are opinionated in some aspects.
|
||||
|
||||
The `App` class has three subclasses: `llm`, `db` and `embedder`. These are the core ingredients that make up an EmbedChain app.
|
||||
App plus each one of the subclasses have a `config` attribute.
|
||||
You can pass a `Config` instance as an argument during initialization to persistently configure a class.
|
||||
These configs can be imported from `embedchain.config`
|
||||
|
||||
There are `set` methods for some things that should not (only) be set at start-up, like `app.db.set_collection_name`.
|
||||
|
||||
## Examples
|
||||
|
||||
### General
|
||||
|
||||
Here's the readme example with configuration options.
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
from embedchain.config import AppConfig, AddConfig, LlmConfig, ChunkerConfig
|
||||
|
||||
# Example: set the log level for debugging
|
||||
config = AppConfig(log_level="DEBUG")
|
||||
naval_chat_bot = App(config)
|
||||
|
||||
# Example: specify a custom collection name
|
||||
naval_chat_bot.db.set_collection_name("naval_chat_bot")
|
||||
|
||||
# Example: define your own chunker config for `youtube_video`
|
||||
chunker_config = ChunkerConfig(chunk_size=1000, chunk_overlap=100, length_function=len)
|
||||
# Example: Add your chunker config to an AddConfig to actually use it
|
||||
add_config = AddConfig(chunker=chunker_config)
|
||||
naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44", config=add_config)
|
||||
|
||||
# Example: Reset to default
|
||||
add_config = AddConfig()
|
||||
naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf", config=add_config)
|
||||
naval_chat_bot.add("https://nav.al/feedback", config=add_config)
|
||||
naval_chat_bot.add("https://nav.al/agi", config=add_config)
|
||||
naval_chat_bot.add(("Who is Naval Ravikant?", "Naval Ravikant is an Indian-American entrepreneur and investor."), config=add_config)
|
||||
|
||||
# Change the number of documents.
|
||||
query_config = LlmConfig(number_documents=5)
|
||||
print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?", config=query_config))
|
||||
```
|
||||
|
||||
### Custom prompt template
|
||||
|
||||
Here's the example of using custom prompt template with `.query`
|
||||
|
||||
```python
|
||||
from string import Template
|
||||
|
||||
import wikipedia
|
||||
|
||||
from embedchain import App
|
||||
from embedchain.config import LlmConfig
|
||||
|
||||
einstein_chat_bot = App()
|
||||
|
||||
# Embed Wikipedia page
|
||||
page = wikipedia.page("Albert Einstein")
|
||||
einstein_chat_bot.add(page.content)
|
||||
|
||||
# Example: use your own custom template with `$context` and `$query`
|
||||
einstein_chat_template = Template(
|
||||
"""
|
||||
You are Albert Einstein, a German-born theoretical physicist,
|
||||
widely ranked among the greatest and most influential scientists of all time.
|
||||
|
||||
Use the following information about Albert Einstein to respond to
|
||||
the human's query acting as Albert Einstein.
|
||||
Context: $context
|
||||
|
||||
Keep the response brief. If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
|
||||
Human: $query
|
||||
Albert Einstein:"""
|
||||
)
|
||||
# Example: Use the template, also add a system prompt.
|
||||
llm_config = LlmConfig(template=einstein_chat_template, system_prompt="You are Albert Einstein.")
|
||||
queries = [
|
||||
"Where did you complete your studies?",
|
||||
"Why did you win nobel prize?",
|
||||
"Why did you divorce your first wife?",
|
||||
]
|
||||
for query in queries:
|
||||
response = einstein_chat_bot.query(query, config=llm_config)
|
||||
print("Query: ", query)
|
||||
print("Response: ", response)
|
||||
|
||||
# Output
|
||||
# Query: Where did you complete your studies?
|
||||
# Response: I completed my secondary education at the Argovian cantonal school in Aarau, Switzerland.
|
||||
# Query: Why did you win nobel prize?
|
||||
# Response: I won the Nobel Prize in Physics in 1921 for my services to Theoretical Physics, particularly for my discovery of the law of the photoelectric effect.
|
||||
# Query: Why did you divorce your first wife?
|
||||
# Response: We divorced due to living apart for five years.
|
||||
```
|
||||
@@ -1,158 +0,0 @@
|
||||
---
|
||||
title: '📋 Supported data formats'
|
||||
---
|
||||
|
||||
## Automatic data type detection
|
||||
The add method automatically tries to detect the data_type, based on your input for the source argument. So `app.add('https://www.youtube.com/watch?v=dQw4w9WgXcQ')` is enough to embed a YouTube video.
|
||||
|
||||
This detection is implemented for all formats. It is based on factors such as whether it's a URL, a local file, the source data type, etc.
|
||||
|
||||
### Debugging automatic detection
|
||||
|
||||
|
||||
Set `log_level=DEBUG` (in [AppConfig](http://localhost:3000/advanced/query_configuration#appconfig)) and make sure it's working as intended.
|
||||
|
||||
Otherwise, you will not know when, for instance, an invalid filepath is interpreted as raw text instead.
|
||||
|
||||
### Forcing a data type
|
||||
|
||||
To omit any issues with the data type detection, you can **force** a data_type by adding it as a `add` method argument.
|
||||
The examples below show you the keyword to force the respective `data_type`.
|
||||
|
||||
Forcing can also be used for edge cases, such as interpreting a sitemap as a web_page, for reading its raw text instead of following links.
|
||||
|
||||
## Remote Data Types
|
||||
|
||||
<Tip>
|
||||
**Use local files in remote data types**
|
||||
|
||||
Some data_types are meant for remote content and only work with URLs.
|
||||
You can pass local files by formatting the path using the `file:` [URI scheme](https://en.wikipedia.org/wiki/File_URI_scheme), e.g. `file:///info.pdf`.
|
||||
</Tip>
|
||||
|
||||
### Youtube video
|
||||
|
||||
To add any youtube video to your app, use the data_type (first argument to `.add()` method) as `youtube_video`. Eg:
|
||||
|
||||
```python
|
||||
app.add('a_valid_youtube_url_here', data_type='youtube_video')
|
||||
```
|
||||
|
||||
### PDF file
|
||||
|
||||
To add any pdf file, use the data_type as `pdf_file`. Eg:
|
||||
|
||||
```python
|
||||
app.add('a_valid_url_where_pdf_file_can_be_accessed', data_type='pdf_file')
|
||||
```
|
||||
|
||||
Note that we do not support password protected pdfs.
|
||||
|
||||
### Web page
|
||||
|
||||
To add any web page, use the data_type as `web_page`. Eg:
|
||||
|
||||
```python
|
||||
app.add('a_valid_web_page_url', data_type='web_page')
|
||||
```
|
||||
|
||||
### Sitemap
|
||||
|
||||
Add all web pages from an xml-sitemap. Filters non-text files. Use the data_type as `sitemap`. Eg:
|
||||
|
||||
```python
|
||||
app.add('https://example.com/sitemap.xml', data_type='sitemap')
|
||||
```
|
||||
|
||||
### Doc file
|
||||
|
||||
To add any doc/docx file, use the data_type as `docx`. `docx` allows remote urls and conventional file paths. Eg:
|
||||
|
||||
```python
|
||||
app.add('https://example.com/content/intro.docx', data_type="docx")
|
||||
app.add('content/intro.docx', data_type="docx")
|
||||
```
|
||||
|
||||
### CSV file
|
||||
|
||||
To add any csv file, use the data_type as `csv`. `csv` allows remote urls and conventional file paths. Headers are included for each line, so if you have an `age` column, `18` will be added as `age: 18`. Eg:
|
||||
|
||||
```python
|
||||
app.add('https://example.com/content/sheet.csv', data_type="csv")
|
||||
app.add('content/sheet.csv', data_type="csv")
|
||||
```
|
||||
|
||||
### Code documentation website loader
|
||||
|
||||
To add any code documentation website as a loader, use the data_type as `docs_site`. Eg:
|
||||
|
||||
```python
|
||||
app.add("https://docs.embedchain.ai/", data_type="docs_site")
|
||||
```
|
||||
|
||||
### Notion
|
||||
To use notion you must install the extra dependencies with `pip install --upgrade embedchain[notion]`.
|
||||
|
||||
To load a notion page, use the data_type as `notion`. Since it is hard to automatically detect, forcing this is advised.
|
||||
The next argument must **end** with the `notion page id`. The id is a 32-character string. Eg:
|
||||
|
||||
```python
|
||||
app.add("cfbc134ca6464fc980d0391613959196", "notion")
|
||||
app.add("my-page-cfbc134ca6464fc980d0391613959196", "notion")
|
||||
app.add("https://www.notion.so/my-page-cfbc134ca6464fc980d0391613959196", "notion")
|
||||
```
|
||||
|
||||
### Mdx file
|
||||
|
||||
To add any mdx file to your app, use the data_type (first argument to `.add()` method) as `mdx`. Note that this supports support mdx file present on machine, so this should be a file path. Eg:
|
||||
|
||||
```python
|
||||
app.add('path/to/file.mdx', data_type='mdx')
|
||||
```
|
||||
|
||||
## Local Data Types
|
||||
|
||||
### Text
|
||||
|
||||
To supply your own text, use the data_type as `text` and enter a string. The text is not processed, this can be very versatile. Eg:
|
||||
|
||||
```python
|
||||
app.add('Seek wealth, not money or status. Wealth is having assets that earn while you sleep. Money is how we transfer time and wealth. Status is your place in the social hierarchy.', data_type='text')
|
||||
```
|
||||
|
||||
Note: This is not used in the examples because in most cases you will supply a whole paragraph or file, which did not fit.
|
||||
|
||||
### QnA pair
|
||||
|
||||
To supply your own QnA pair, use the data_type as `qna_pair` and enter a tuple. Eg:
|
||||
|
||||
```python
|
||||
app.add(("Question", "Answer"), data_type="qna_pair")
|
||||
```
|
||||
|
||||
## Reusing a vector database
|
||||
|
||||
Default behavior is to create a persistent vector DB in the directory **./db**. You can split your application into two Python scripts: one to create a local vector DB and the other to reuse this local persistent vector DB. This is useful when you want to index hundreds of documents and separately implement a chat interface.
|
||||
|
||||
Create a local index:
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
naval_chat_bot = App()
|
||||
naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||
naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf")
|
||||
```
|
||||
|
||||
You can reuse the local index with the same code, but without adding new documents:
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
naval_chat_bot = App()
|
||||
print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"))
|
||||
```
|
||||
|
||||
## More formats (coming soon!)
|
||||
|
||||
- If you want to add any other format, please create an [issue](https://github.com/embedchain/embedchain/issues) and we will add it to the list of supported formats.
|
||||
@@ -1,75 +0,0 @@
|
||||
---
|
||||
title: '🤝 Interface types'
|
||||
---
|
||||
|
||||
## Interface Types
|
||||
|
||||
The embedchain app exposes the following methods.
|
||||
|
||||
### Query Interface
|
||||
|
||||
- This interface is like a question answering bot. It takes a question and gets the answer. It does not maintain context about the previous chats.❓
|
||||
|
||||
- To use this, call `.query()` function to get the answer for any query.
|
||||
|
||||
```python
|
||||
print(naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"))
|
||||
# answer: Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.
|
||||
```
|
||||
|
||||
### Chat Interface
|
||||
|
||||
- This interface is a chat interface that remembers previous conversations. Right now it remembers 5 conversations by default. 💬
|
||||
|
||||
- To use this, call `.chat` function to get the answer for any query.
|
||||
|
||||
```python
|
||||
print(naval_chat_bot.chat("How to be happy in life?"))
|
||||
# answer: The most important trick to being happy is to realize happiness is a skill you develop and a choice you make. You choose to be happy, and then you work at it. It's just like building muscles or succeeding at your job. It's about recognizing the abundance and gifts around you at all times.
|
||||
|
||||
print(naval_chat_bot.chat("who is naval ravikant?"))
|
||||
# answer: Naval Ravikant is an Indian-American entrepreneur and investor.
|
||||
|
||||
print(naval_chat_bot.chat("what did the author say about happiness?"))
|
||||
# answer: The author, Naval Ravikant, believes that happiness is a choice you make and a skill you develop. He compares the mind to the body, stating that just as the body can be molded and changed, so can the mind. He emphasizes the importance of being present in the moment and not getting caught up in regrets of the past or worries about the future. By being present and grateful for where you are, you can experience true happiness.
|
||||
```
|
||||
|
||||
#### Dry Run
|
||||
|
||||
Dry Run is an option in the `add`, `query` and `chat` methods that allows the user to displays the data chunks and their constructed prompt which is not send to the LLM, to save money. It's used for [testing](/advanced/testing#dry-run).
|
||||
|
||||
|
||||
### Stream Response
|
||||
|
||||
- You can add config to your query method to stream responses like ChatGPT does. You would require a downstream handler to render the chunk in your desirable format. Supports both OpenAI model and OpenSourceApp. 📊
|
||||
|
||||
- To use this, instantiate a `QueryConfig` or `ChatConfig` object with `stream=True`. Then pass it to the `.chat()` or `.query()` method. The following example iterates through the chunks and prints them as they appear.
|
||||
|
||||
```python
|
||||
app = App()
|
||||
query_config = QueryConfig(stream = True)
|
||||
resp = app.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?", query_config)
|
||||
|
||||
for chunk in resp:
|
||||
print(chunk, end="", flush=True)
|
||||
# answer: Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.
|
||||
```
|
||||
|
||||
### Other Methods
|
||||
|
||||
#### Reset
|
||||
|
||||
Resets the database and deletes all embeddings. Irreversible. Requires reinitialization afterwards.
|
||||
|
||||
```python
|
||||
app.reset()
|
||||
```
|
||||
|
||||
#### Count
|
||||
|
||||
Counts the number of embeddings (chunks) in the database.
|
||||
|
||||
```python
|
||||
print(app.count())
|
||||
# returns: 481
|
||||
```
|
||||
@@ -1,77 +0,0 @@
|
||||
---
|
||||
title: '🔍 Query configurations'
|
||||
---
|
||||
|
||||
## AppConfig
|
||||
|
||||
| option | description | type | default |
|
||||
|-----------|-----------------------|---------------------------------|------------------------|
|
||||
| log_level | log level | string | WARNING |
|
||||
| embedding_fn| embedding function | chromadb.utils.embedding_functions | \{text-embedding-ada-002\} |
|
||||
| db | vector database (experimental) | BaseVectorDB | ChromaDB |
|
||||
| collection_name | initial collection name for the database | string | embedchain_store |
|
||||
| collect_metrics | collect anonymous telemetry data to improve embedchain | boolean | true |
|
||||
|
||||
|
||||
## AddConfig
|
||||
|
||||
|option|description|type|default|
|
||||
|---|---|---|---|
|
||||
|chunker|chunker config|ChunkerConfig|Default values for chunker depends on the `data_type`. Please refer [ChunkerConfig](#chunker-config)|
|
||||
|loader|loader config|LoaderConfig|None|
|
||||
|
||||
Yes, you are passing `ChunkerConfig` to `AddConfig`, like so:
|
||||
|
||||
```python
|
||||
chunker_config = ChunkerConfig(chunk_size=100)
|
||||
add_config = AddConfig(chunker=chunker_config)
|
||||
app.add("lorem ipsum", config=add_config)
|
||||
```
|
||||
|
||||
### ChunkerConfig
|
||||
|
||||
|option|description|type|default|
|
||||
|---|---|---|---|
|
||||
|chunk_size|Maximum size of chunks to return|int|Default value for various `data_type` mentioned below|
|
||||
|chunk_overlap|Overlap in characters between chunks|int|Default value for various `data_type` mentioned below|
|
||||
|length_function|Function that measures the length of given chunks|typing.Callable|Default value for various `data_type` mentioned below|
|
||||
|
||||
Default values of chunker config parameters for different `data_type`:
|
||||
|
||||
|data_type|chunk_size|chunk_overlap|length_function|
|
||||
|---|---|---|---|
|
||||
|docx|1000|0|len|
|
||||
|text|300|0|len|
|
||||
|qna_pair|300|0|len|
|
||||
|web_page|500|0|len|
|
||||
|pdf_file|1000|0|len|
|
||||
|youtube_video|2000|0|len|
|
||||
|docs_site|500|50|len|
|
||||
|notion|300|0|len|
|
||||
|
||||
### LoaderConfig
|
||||
|
||||
_coming soon_
|
||||
|
||||
## LlmConfig
|
||||
|
||||
|option|description|type|default|
|
||||
|---|---|---|---|
|
||||
|number_documents|Absolute number of documents to pull from the database as context.|int|1
|
||||
|template|custom template for prompt. If history is used with query, $history has to be included as well.|Template|Template("Use the following pieces of context to answer the query at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer. \$context Query: \$query Helpful Answer:")|
|
||||
|model|name of the model used.|string|depends on app type|
|
||||
|temperature|Controls the randomness of the model's output. Higher values (closer to 1) make output more random, lower values make it more deterministic.|float|0|
|
||||
|max_tokens|Controls how many tokens are used. Exact implementation (whether it counts prompt and/or response) depends on the model.|int|1000|
|
||||
|top_p|Controls the diversity of words. Higher values (closer to 1) make word selection more diverse, lower values make words less diverse.|float|1|
|
||||
|history|include conversation history from your client or database.|any (recommendation: list[str])|None|
|
||||
|stream|control if response is streamed back to the user.|bool|False|
|
||||
|deployment_name|t.b.a.|str|None|
|
||||
|system_prompt|System prompt string. Unused if none.|str|None|
|
||||
|
||||
## ChatConfig
|
||||
|
||||
All options for query and...
|
||||
|
||||
_coming soon_
|
||||
|
||||
`history` is not supported, as that is handled is handled automatically, the config option is not supported.
|
||||
@@ -1,40 +0,0 @@
|
||||
---
|
||||
title: '🧪 Testing'
|
||||
---
|
||||
|
||||
## Methods for testing
|
||||
|
||||
### Dry Run
|
||||
|
||||
Before you consume valueable tokens, you should make sure that data chunks are properly created and the embedding you have done works and that it's receiving the correct document from the database.
|
||||
|
||||
- For `query` or `chat` method, you can add this to your script:
|
||||
|
||||
```python
|
||||
print(naval_chat_bot.query('Can you tell me who Naval Ravikant is?', dry_run=True))
|
||||
|
||||
'''
|
||||
Use the following pieces of context to answer the query at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
Q: Who is Naval Ravikant?
|
||||
A: Naval Ravikant is an Indian-American entrepreneur and investor.
|
||||
Query: Can you tell me who Naval Ravikant is?
|
||||
Helpful Answer:
|
||||
'''
|
||||
```
|
||||
|
||||
_The embedding is confirmed to work as expected. It returns the right document, even if the question is asked slightly different. No prompt tokens have been consumed._
|
||||
|
||||
The dry run will still consume tokens to embed your query, but it is only **~1/15 of the prompt.**
|
||||
|
||||
|
||||
- For `add` method, you can add this to your script:
|
||||
|
||||
```python
|
||||
print(naval_chat_bot.add('https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf', dry_run=True))
|
||||
|
||||
'''
|
||||
{'chunks': ['THE ALMANACK OF NAVAL RAVIKANT', 'GETTING RICH IS NOT JUST ABOUT LUCK;', 'HAPPINESS IS NOT JUST A TRAIT WE ARE'], 'metadata': [{'source': 'C:\\Users\\Dev\\AppData\\Local\\Temp\\tmp3g5mjoiz\\tmp.pdf', 'page': 0, 'url': 'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf', 'data_type': 'pdf_file'}, {'source': 'C:\\Users\\Dev\\AppData\\Local\\Temp\\tmp3g5mjoiz\\tmp.pdf', 'page': 2, 'url': 'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf', 'data_type': 'pdf_file'}, {'source': 'C:\\Users\\Dev\\AppData\\Local\\Temp\\tmp3g5mjoiz\\tmp.pdf', 'page': 2, 'url': 'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf', 'data_type': 'pdf_file'}], 'count': 7358, 'type': <DataType.PDF_FILE: 'pdf_file'>}
|
||||
|
||||
# less items to show for readability
|
||||
'''
|
||||
```
|
||||
@@ -1,34 +0,0 @@
|
||||
---
|
||||
title: '💾 Vector Database'
|
||||
---
|
||||
|
||||
We support `Chroma` and `Elasticsearch` as two vector database.
|
||||
`Chroma` is used as a default database.
|
||||
|
||||
### Elasticsearch
|
||||
In order to use `Elasticsearch` as vector database we need to use App type `CustomApp`.
|
||||
```python
|
||||
import os
|
||||
from embedchain import CustomApp
|
||||
from embedchain.config import CustomAppConfig, ElasticsearchDBConfig
|
||||
from embedchain.models import Providers, EmbeddingFunctions, VectorDatabases
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = 'OPENAI_API_KEY'
|
||||
|
||||
es_config = ElasticsearchDBConfig(
|
||||
# elasticsearch url or list of nodes url with different hosts and ports.
|
||||
es_url='http://localhost:9200',
|
||||
# pass named parameters supported by Python Elasticsearch client
|
||||
ca_certs="/path/to/http_ca.crt",
|
||||
basic_auth=("username", "password")
|
||||
)
|
||||
config = CustomAppConfig(
|
||||
embedding_fn=EmbeddingFunctions.OPENAI,
|
||||
provider=Providers.OPENAI,
|
||||
db_type=VectorDatabases.ELASTICSEARCH,
|
||||
es_config=es_config,
|
||||
)
|
||||
es_app = CustomApp(config)
|
||||
```
|
||||
- Set `db_type=VectorDatabases.ELASTICSEARCH` and `es_config=ElasticsearchDBConfig(es_url='')` in `CustomAppConfig`.
|
||||
- `ElasticsearchDBConfig` accepts `es_url` as elasticsearch url or as list of nodes url with different hosts and ports. Additionally we can pass named parameters supported by Python Elasticsearch client.
|
||||
@@ -0,0 +1,294 @@
|
||||
---
|
||||
title: 🤖 LLMs
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Mem0 includes built-in support for various popular large language models. Memory can utilize the LLM provided by the user, ensuring efficient use for specific needs.
|
||||
|
||||
<CardGroup cols={4}>
|
||||
<Card title="OpenAI" href="#openai"></Card>
|
||||
<Card title="Ollama" href="#ollama"></Card>
|
||||
<Card title="Groq" href="#groq"></Card>
|
||||
<Card title="Together" href="#together"></Card>
|
||||
<Card title="AWS Bedrock" href="#aws-bedrock"></Card>
|
||||
<Card title="Litellm" href="#litellm"></Card>
|
||||
<Card title="Google AI" href="#google-ai"></Card>
|
||||
<Card title="Anthropic" href="#anthropic"></Card>
|
||||
<Card title="Mistral AI" href="#mistral-ai"></Card>
|
||||
<Card title="OpenAI Azure" href="#openai-azure"></Card>
|
||||
</CardGroup>
|
||||
|
||||
## OpenAI
|
||||
|
||||
To use OpenAI LLM models, you have to set the `OPENAI_API_KEY` environment variable. You can obtain the OpenAI API key from the [OpenAI Platform](https://platform.openai.com/account/api-keys).
|
||||
|
||||
Once you have obtained the key, you can use it like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "openai",
|
||||
"config": {
|
||||
"model": "gpt-4o",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Ollama
|
||||
|
||||
You can use LLMs from Ollama to run Mem0 locally. These [models](https://ollama.com/search?c=tools) support tool support.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # for embedder
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "ollama",
|
||||
"config": {
|
||||
"model": "mixtral:8x7b",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Groq
|
||||
|
||||
[Groq](https://groq.com/) is the creator of the world's first Language Processing Unit (LPU), providing exceptional speed performance for AI workloads running on their LPU Inference Engine.
|
||||
|
||||
In order to use LLMs from Groq, go to their [platform](https://console.groq.com/keys) and get the API key. Set the API key as `GROQ_API_KEY` environment variable to use the model as given below in the example.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["GROQ_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "groq",
|
||||
"config": {
|
||||
"model": "mixtral-8x7b-32768",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 1000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Together
|
||||
|
||||
To use TogetherAI LLM models, you have to set the `TOGETHER_API_KEY` environment variable. You can obtain the TogetherAI API key from their [Account settings page](https://api.together.xyz/settings/api-keys).
|
||||
|
||||
Once you have obtained the key, you can use it like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["TOGETHER_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "togetherai",
|
||||
"config": {
|
||||
"model": "mistralai/Mixtral-8x7B-Instruct-v0.1",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## AWS Bedrock
|
||||
|
||||
### Setup
|
||||
- Before using the AWS Bedrock LLM, make sure you have the appropriate model access from [Bedrock Console](https://us-east-1.console.aws.amazon.com/bedrock/home?region=us-east-1#/modelaccess).
|
||||
- You will also need to authenticate the `boto3` client by using a method in the [AWS documentation](https://boto3.amazonaws.com/v1/documentation/api/latest/guide/credentials.html#configuring-credentials)
|
||||
- You will have to export `AWS_REGION`, `AWS_ACCESS_KEY`, and `AWS_SECRET_ACCESS_KEY` to set environment variables.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ['AWS_REGION'] = 'us-east-1'
|
||||
os.environ["AWS_ACCESS_KEY"] = "xx"
|
||||
os.environ["AWS_SECRET_ACCESS_KEY"] = "xx"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "aws_bedrock",
|
||||
"config": {
|
||||
"model": "arn:aws:bedrock:us-east-1:123456789012:model/your-model-name",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Litellm
|
||||
|
||||
[Litellm](https://litellm.vercel.app/docs/) is compatible with over 100 large language models (LLMs), all using a standardized input/output format. You can explore the [available models]((https://litellm.vercel.app/docs/providers)) to use with Litellm. Ensure you set the `API_KEY` for the model you choose to use.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "litellm",
|
||||
"config": {
|
||||
"model": "gpt-3.5-turbo",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Google AI
|
||||
|
||||
To use Google AI model, you have to set the `GOOGLE_API_KEY` environment variable. You can obtain the Google API key from the [Google Maker Suite](https://makersuite.google.com/app/apikey)
|
||||
|
||||
Once you have obtained the key, you can use it like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["GEMINI_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "litellm",
|
||||
"config": {
|
||||
"model": "gemini/gemini-pro",
|
||||
"temperature": 0.2,
|
||||
"max_tokens": 1500,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Anthropic
|
||||
|
||||
To use anthropic's models, please set the `ANTHROPIC_API_KEY` which you find on their [Account Settings Page](https://console.anthropic.com/account/keys).
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["ANTHROPIC_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "litellm",
|
||||
"config": {
|
||||
"model": "claude-3-opus-20240229",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Mistral AI
|
||||
|
||||
To use mistral's models, please Obtain the Mistral AI api key from their [console](https://console.mistral.ai/). Set the `MISTRAL_API_KEY` environment variable to use the model as given below in the example.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "your-api-key" # used for embedding model
|
||||
os.environ["MISTRAL_API_KEY"] = "your-api-key"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "litellm",
|
||||
"config": {
|
||||
"model": "open-mixtral-8x7b",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## OpenAI Azure
|
||||
|
||||
To use Azure AI models, you have to set the `AZURE_API_KEY`, `AZURE_API_BASE`, and `AZURE_API_VERSION` environment variables. You can obtain the Azure API key from the [Azure](https://azure.microsoft.com/).
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
|
||||
os.environ["AZURE_API_KEY"] = "your-api-key"
|
||||
|
||||
# Needed to use custom models
|
||||
os.environ["AZURE_API_BASE"] = "your-api-base-url"
|
||||
os.environ["AZURE_API_VERSION"] = "version-to-use"
|
||||
|
||||
config = {
|
||||
"llm": {
|
||||
"provider": "litellm",
|
||||
"config": {
|
||||
"model": "azure_ai/command-r-plus",
|
||||
"temperature": 0.1,
|
||||
"max_tokens": 2000,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
@@ -0,0 +1,64 @@
|
||||
---
|
||||
title: 🗄 Vector Databases
|
||||
---
|
||||
|
||||
## Overview
|
||||
|
||||
Mem0 includes built-in support for various popular databases. Memory can utilize the database provided by the user, ensuring efficient use for specific needs.
|
||||
|
||||
<CardGroup>
|
||||
<Card title="Qdrant" href="#qdrant"></Card>
|
||||
<Card title="Chroma" href="#chroma"></Card>
|
||||
</CardGroup>
|
||||
|
||||
|
||||
## Qdrant
|
||||
|
||||
[Qdrant](https://qdrant.tech/) is an open-source vector search engine. It is designed to work with large-scale datasets and provides a high-performance search engine for vector data.
|
||||
|
||||
To use Qdrant you can do like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
|
||||
config = {
|
||||
"vectordb": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"collection_name": "test",
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
## Chroma
|
||||
|
||||
[Chroma](https://www.trychroma.com/) is an AI-native open-source vector database that simplifies building LLM apps by providing tools for storing, embedding, and searching embeddings with a focus on simplicity and speed.
|
||||
|
||||
To use ChromaDB you can do like this:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
|
||||
config = {
|
||||
"vectordb": {
|
||||
"provider": "chromadb",
|
||||
"config": {
|
||||
"collection_name": "test",
|
||||
"path": "db",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
m = Memory.from_config(config)
|
||||
m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
@@ -1,91 +0,0 @@
|
||||
---
|
||||
title: '🌍 API Server'
|
||||
---
|
||||
|
||||
The API Server based on Flask integrates the `embedchain` package, offering endpoints to add, query, and chat to engage in conversations with a chatbot using JSON requests.
|
||||
|
||||
### 🐳 Docker Setup
|
||||
|
||||
- Open variables.env, and edit it to add your 🔑 `OPENAI_API_KEY`.
|
||||
- To setup your api server using docker, run the following command inside this folder using your terminal.
|
||||
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
📝 Note: The build command might take a while to install all the packages depending on your system resources.
|
||||
|
||||
### 🚀 Usage Instructions
|
||||
|
||||
- Your api server is running on [http://localhost:5000/](http://localhost:5000/)
|
||||
- To use the api server, make an api call to the endpoints `/add`, `/query` and `/chat` using the json formats discussed below.
|
||||
- To add data sources to the bot (/add):
|
||||
```json
|
||||
// Request
|
||||
{
|
||||
"data_type": "your_data_type_here",
|
||||
"url_or_text": "your_url_or_text_here"
|
||||
}
|
||||
|
||||
// Response
|
||||
{
|
||||
"data": "Added data_type: url_or_text"
|
||||
}
|
||||
```
|
||||
- To ask queries from the bot (/query):
|
||||
```json
|
||||
// Request
|
||||
{
|
||||
"question": "your_question_here"
|
||||
}
|
||||
|
||||
// Response
|
||||
{
|
||||
"data": "your_answer_here"
|
||||
}
|
||||
```
|
||||
- To chat with the bot (/chat):
|
||||
```json
|
||||
// Request
|
||||
{
|
||||
"question": "your_question_here"
|
||||
}
|
||||
|
||||
// Response
|
||||
{
|
||||
"data": "your_answer_here"
|
||||
}
|
||||
```
|
||||
|
||||
### 📡 Curl Call Formats
|
||||
|
||||
- To add data sources to the bot (/add):
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"data_type": "your_data_type_here",
|
||||
"url_or_text": "your_url_or_text_here"
|
||||
}' \
|
||||
http://localhost:5000/add
|
||||
```
|
||||
- To ask queries from the bot (/query):
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"question": "your_question_here"
|
||||
}' \
|
||||
http://localhost:5000/query
|
||||
```
|
||||
- To chat with the bot (/chat):
|
||||
```bash
|
||||
curl -X POST \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"question": "your_question_here"
|
||||
}' \
|
||||
http://localhost:5000/chat
|
||||
```
|
||||
|
||||
🎉 Happy Chatting! 🎉
|
||||
@@ -0,0 +1,109 @@
|
||||
---
|
||||
title: Customer Support AI Agent
|
||||
---
|
||||
|
||||
You can create a personalized Customer Support AI Agent using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Customer Support AI Agent leverages Mem0 to retain information across interactions, enabling a personalized and efficient support experience.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the necessary packages using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the simplified code to create and interact with a Customer Support AI Agent using Mem0:
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
class CustomerSupportAIAgent:
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the CustomerSupportAIAgent with memory configuration and OpenAI client.
|
||||
"""
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
self.memory = Memory.from_config(config)
|
||||
self.client = OpenAI()
|
||||
self.app_id = "customer-support"
|
||||
|
||||
def handle_query(self, query, user_id=None):
|
||||
"""
|
||||
Handle a customer query and store the relevant information in memory.
|
||||
|
||||
:param query: The customer query to handle.
|
||||
:param user_id: Optional user ID to associate with the memory.
|
||||
"""
|
||||
# Start a streaming chat completion request to the AI
|
||||
stream = self.client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
stream=True,
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a customer support AI agent."},
|
||||
{"role": "user", "content": query}
|
||||
]
|
||||
)
|
||||
# Store the query in memory
|
||||
self.memory.add(query, user_id=user_id, metadata={"app_id": self.app_id})
|
||||
|
||||
# Print the response from the AI in real-time
|
||||
for chunk in stream:
|
||||
if chunk.choices[0].delta.content is not None:
|
||||
print(chunk.choices[0].delta.content, end="")
|
||||
|
||||
def get_memories(self, user_id=None):
|
||||
"""
|
||||
Retrieve all memories associated with the given customer ID.
|
||||
|
||||
:param user_id: Optional user ID to filter memories.
|
||||
:return: List of memories.
|
||||
"""
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
|
||||
# Instantiate the CustomerSupportAIAgent
|
||||
support_agent = CustomerSupportAIAgent()
|
||||
|
||||
# Define a customer ID
|
||||
customer_id = "jane_doe"
|
||||
|
||||
# Handle a customer query
|
||||
support_agent.handle_query("I need help with my recent order. It hasn't arrived yet.", user_id=customer_id)
|
||||
```
|
||||
|
||||
### Fetching Memories
|
||||
|
||||
You can fetch all the memories at any point in time using the following code:
|
||||
|
||||
```python
|
||||
memories = support_agent.get_memories(user_id=customer_id)
|
||||
for m in memories:
|
||||
print(m['text'])
|
||||
```
|
||||
|
||||
### Key Points
|
||||
|
||||
- **Initialization**: The CustomerSupportAIAgent class is initialized with the necessary memory configuration and OpenAI client setup.
|
||||
- **Handling Queries**: The handle_query method sends a query to the AI and stores the relevant information in memory.
|
||||
- **Retrieving Memories**: The get_memories method fetches all stored memories associated with a customer.
|
||||
|
||||
### Conclusion
|
||||
|
||||
As the conversation progresses, Mem0's memory automatically updates based on the interactions, providing a continuously improving personalized support experience.
|
||||
@@ -1,22 +0,0 @@
|
||||
---
|
||||
title: '🌐 Full Stack'
|
||||
---
|
||||
|
||||
### 🐳 Docker Setup
|
||||
|
||||
- To setup full stack app using docker, run the following command inside this folder using your terminal.
|
||||
|
||||
```bash
|
||||
docker-compose up --build
|
||||
```
|
||||
|
||||
📝 Note: The build command might take a while to install all the packages depending on your system resources.
|
||||
|
||||
### 🚀 Usage Instructions
|
||||
|
||||
- Go to [http://localhost:3000/](http://localhost:3000/) in your browser to view the dashboard.
|
||||
- Add your `OpenAI API key` 🔑 in the Settings.
|
||||
- Create a new bot and you'll be navigated to its page.
|
||||
- Here you can add your data sources and then chat with the bot.
|
||||
|
||||
🎉 Happy Chatting! 🎉
|
||||
@@ -0,0 +1,32 @@
|
||||
---
|
||||
title: Overview
|
||||
description: How to use mem0 in your existing applications?
|
||||
---
|
||||
|
||||
|
||||
With Mem0, you can create stateful LLM-based applications such as chatbots, virtual assistants, or AI agents. Mem0 enhances your applications by providing a memory layer that makes responses:
|
||||
|
||||
- More personalized
|
||||
- More reliable
|
||||
- Cost-effective by reducing the number of LLM interactions
|
||||
- More engaging
|
||||
- Enables long-term memory
|
||||
|
||||
Here are some examples of how Mem0 can be integrated into various applications:
|
||||
|
||||
## Example Use Cases
|
||||
|
||||
<CardGroup cols={1}>
|
||||
<Card title="Personal AI Tutor" icon="square-1" href="/examples/personal-ai-tutor">
|
||||
<img width="100%" src="/images/ai-tutor.png" />
|
||||
Create a Personalized AI Tutor that adapts to student progress and learning preferences.
|
||||
</Card>
|
||||
<Card title="Personal Travel Assistant" icon="square-2" href="/examples/personal-travel-assistant">
|
||||
<img src="/images/personal-travel-agent.png" />
|
||||
Build a Personalized AI Travel Assistant that understands your travel preferences and past itineraries.
|
||||
</Card>
|
||||
<Card title="Customer Support Agent" icon="square-3" href="/examples/customer-support-agent">
|
||||
<img width="100%" src="/images/customer-support-agent.png" />
|
||||
Develop a Personal AI Assistant that remembers user preferences, past interactions, and context to provide personalized and efficient assistance.
|
||||
</Card>
|
||||
</CardGroup>
|
||||
@@ -0,0 +1,111 @@
|
||||
---
|
||||
title: Personalized AI Tutor
|
||||
---
|
||||
|
||||
You can create a personalized AI Tutor using Mem0. This guide will walk you through the necessary steps and provide the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Tutor leverages Mem0 to retain information across interactions, enabling a tailored learning experience. By integrating with OpenAI's GPT-4 model, the tutor can provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
Before you begin, ensure you have the required dependencies installed. You can install the necessary packages using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Below is the complete code to create and interact with a Personalized AI Tutor using Mem0:
|
||||
|
||||
```python
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
# Initialize the OpenAI client
|
||||
client = OpenAI()
|
||||
|
||||
class PersonalAITutor:
|
||||
def __init__(self):
|
||||
"""
|
||||
Initialize the PersonalAITutor with memory configuration and OpenAI client.
|
||||
"""
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
self.memory = Memory.from_config(config)
|
||||
self.client = client
|
||||
self.app_id = "app-1"
|
||||
|
||||
def ask(self, question, user_id=None):
|
||||
"""
|
||||
Ask a question to the AI and store the relevant facts in memory
|
||||
|
||||
:param question: The question to ask the AI.
|
||||
:param user_id: Optional user ID to associate with the memory.
|
||||
"""
|
||||
# Start a streaming chat completion request to the AI
|
||||
stream = self.client.chat.completions.create(
|
||||
model="gpt-4",
|
||||
stream=True,
|
||||
messages=[
|
||||
{"role": "system", "content": "You are a personal AI Tutor."},
|
||||
{"role": "user", "content": question}
|
||||
]
|
||||
)
|
||||
# Store the question in memory
|
||||
self.memory.add(question, user_id=user_id, metadata={"app_id": self.app_id})
|
||||
|
||||
# Print the response from the AI in real-time
|
||||
for chunk in stream:
|
||||
if chunk.choices[0].delta.content is not None:
|
||||
print(chunk.choices[0].delta.content, end="")
|
||||
|
||||
def get_memories(self, user_id=None):
|
||||
"""
|
||||
Retrieve all memories associated with the given user ID.
|
||||
|
||||
:param user_id: Optional user ID to filter memories.
|
||||
:return: List of memories.
|
||||
"""
|
||||
return self.memory.get_all(user_id=user_id)
|
||||
|
||||
# Instantiate the PersonalAITutor
|
||||
ai_tutor = PersonalAITutor()
|
||||
|
||||
# Define a user ID
|
||||
user_id = "john_doe"
|
||||
|
||||
# Ask a question
|
||||
ai_tutor.ask("I am learning introduction to CS. What is queue? Briefly explain.", user_id=user_id)
|
||||
```
|
||||
|
||||
### Fetching Memories
|
||||
|
||||
You can fetch all the memories at any point in time using the following code:
|
||||
|
||||
```python
|
||||
memories = ai_tutor.get_memories(user_id=user_id)
|
||||
for m in memories:
|
||||
print(m['text'])
|
||||
```
|
||||
|
||||
### Key Points
|
||||
|
||||
- **Initialization**: The PersonalAITutor class is initialized with the necessary memory configuration and OpenAI client setup.
|
||||
- **Asking Questions**: The ask method sends a question to the AI and stores the relevant information in memory.
|
||||
- **Retrieving Memories**: The get_memories method fetches all stored memories associated with a user.
|
||||
|
||||
### Conclusion
|
||||
|
||||
As the conversation progresses, Mem0's memory automatically updates based on the interactions, providing a continuously improving personalized learning experience. This setup ensures that the AI Tutor can offer contextually relevant and accurate responses, enhancing the overall educational process.
|
||||
@@ -0,0 +1,101 @@
|
||||
---
|
||||
title: Personal AI Travel Assistant
|
||||
---
|
||||
Create a personalized AI Travel Assistant using Mem0. This guide provides step-by-step instructions and the complete code to get you started.
|
||||
|
||||
## Overview
|
||||
|
||||
The Personalized AI Travel Assistant uses Mem0 to store and retrieve information across interactions, enabling a tailored travel planning experience. It integrates with OpenAI's GPT-4 model to provide detailed and context-aware responses to user queries.
|
||||
|
||||
## Setup
|
||||
|
||||
Install the required dependencies using pip:
|
||||
|
||||
```bash
|
||||
pip install openai mem0ai
|
||||
```
|
||||
|
||||
## Full Code Example
|
||||
|
||||
Here's the complete code to create and interact with a Personalized AI Travel Assistant using Mem0:
|
||||
|
||||
```python
|
||||
import os
|
||||
from openai import OpenAI
|
||||
from mem0 import Memory
|
||||
|
||||
# Set the OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = 'sk-xxx'
|
||||
|
||||
class PersonalTravelAssistant:
|
||||
def __init__(self):
|
||||
self.client = OpenAI()
|
||||
self.memory = Memory()
|
||||
self.messages = [{"role": "system", "content": "You are a personal AI Assistant."}]
|
||||
|
||||
def ask_question(self, question, user_id):
|
||||
# Fetch previous related memories
|
||||
previous_memories = self.search_memories(question, user_id=user_id)
|
||||
prompt = question
|
||||
if previous_memories:
|
||||
prompt = f"User input: {question}\n Previous memories: {previous_memories}"
|
||||
self.messages.append({"role": "user", "content": prompt})
|
||||
|
||||
# Generate response using GPT-4o
|
||||
response = self.client.chat.completions.create(
|
||||
model="gpt-4o",
|
||||
messages=self.messages
|
||||
)
|
||||
answer = response.choices[0].message.content
|
||||
self.messages.append({"role": "assistant", "content": answer})
|
||||
|
||||
# Store the question in memory
|
||||
self.memory.add(question, user_id=user_id)
|
||||
return answer
|
||||
|
||||
def get_memories(self, user_id):
|
||||
memories = self.memory.get_all(user_id=user_id)
|
||||
return [m['text'] for m in memories]
|
||||
|
||||
def search_memories(self, query, user_id):
|
||||
memories = self.memory.search(query, user_id=user_id)
|
||||
return [m['text'] for m in memories]
|
||||
|
||||
# Usage example
|
||||
user_id = "traveler_123"
|
||||
ai_assistant = PersonalTravelAssistant()
|
||||
|
||||
def main():
|
||||
while True:
|
||||
question = input("Question: ")
|
||||
if question.lower() in ['q', 'exit']:
|
||||
print("Exiting...")
|
||||
break
|
||||
|
||||
answer = ai_assistant.ask_question(question, user_id=user_id)
|
||||
print(f"Answer: {answer}")
|
||||
memories = ai_assistant.get_memories(user_id=user_id)
|
||||
print("Memories:")
|
||||
for memory in memories:
|
||||
print(f"- {memory}")
|
||||
print("-----")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
```
|
||||
|
||||
## Key Components
|
||||
|
||||
- **Initialization**: The `PersonalTravelAssistant` class is initialized with the OpenAI client and Mem0 memory setup.
|
||||
- **Asking Questions**: The `ask_question` method sends a question to the AI, incorporates previous memories, and stores new information.
|
||||
- **Memory Management**: The `get_memories` and search_memories methods handle retrieval and searching of stored memories.
|
||||
|
||||
## Usage
|
||||
|
||||
1. Set your OpenAI API key in the environment variable.
|
||||
2. Instantiate the `PersonalTravelAssistant`.
|
||||
3. Use the `main()` function to interact with the assistant in a loop.
|
||||
|
||||
## Conclusion
|
||||
|
||||
This Personalized AI Travel Assistant leverages Mem0's memory capabilities to provide context-aware responses. As you interact with it, the assistant learns and improves, offering increasingly personalized travel advice and information.
|
||||
|
Before Width: | Height: | Size: 70 KiB |
@@ -0,0 +1,49 @@
|
||||
<svg width="24" height="24" viewBox="0 0 24 24" fill="none" xmlns="http://www.w3.org/2000/svg">
|
||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61505C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5914 7.95343 21.1394Z" fill="white"/>
|
||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61505C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5914 7.95343 21.1394Z" fill="url(#paint0_radial_101_2703)"/>
|
||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61505C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5914 7.95343 21.1394Z" fill="black" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
||||
<path d="M7.95343 21.1394C4.89586 21.1304 2.25471 19.458 0.987296 16.2895C-0.280118 13.121 0.108924 9.16314 1.74363 5.61505C4.8012 5.62409 7.44235 7.29648 8.70976 10.465C9.97718 13.6335 9.58814 17.5914 7.95343 21.1394Z" fill="url(#paint1_linear_101_2703)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
||||
<path d="M8.68359 10.4755C9.94543 13.63 9.56145 17.5723 7.9354 21.1112C4.89702 21.0957 2.27411 19.4306 1.01347 16.279C-0.248375 13.1245 0.135612 9.18218 1.76165 5.64328C4.80004 5.65883 7.42295 7.32386 8.68359 10.4755Z" stroke="url(#paint2_linear_101_2703)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="white"/>
|
||||
<path d="M7.31038 21.2574C11.3543 20.2215 14.8836 17.3754 16.6285 13.2361C18.3735 9.09671 17.9448 4.58749 15.8598 0.976291C11.8159 2.01214 8.2866 4.85826 6.54167 8.99762C4.79674 13.137 5.2254 17.6462 7.31038 21.2574Z" fill="url(#paint3_radial_101_2703)"/>
|
||||
<path d="M16.6026 13.2251C14.8642 17.349 11.3512 20.1866 7.32411 21.2248C5.25257 17.624 4.82926 13.1324 6.56764 9.00855C8.30603 4.88472 11.819 2.04706 15.8461 1.00889C17.9176 4.60967 18.3409 9.10131 16.6026 13.2251Z" stroke="url(#paint4_linear_101_2703)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="white"/>
|
||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint5_radial_101_2703)"/>
|
||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="black" fill-opacity="0.2" style="mix-blend-mode:hard-light"/>
|
||||
<path d="M7.23368 21.2069C9.78906 23.2373 13.2102 23.9506 16.5772 22.8141C19.9441 21.6775 22.5058 18.9445 23.7304 15.6382C21.175 13.6078 17.7538 12.8944 14.3869 14.031C11.0199 15.1676 8.45822 17.9006 7.23368 21.2069Z" fill="url(#paint6_linear_101_2703)" fill-opacity="0.5" style="mix-blend-mode:hard-light"/>
|
||||
<path d="M16.5682 22.7874C13.2176 23.9184 9.81361 23.2124 7.2672 21.1975C8.49194 17.9068 11.0444 15.189 14.3959 14.0577C17.7465 12.9266 21.1504 13.6326 23.6968 15.6476C22.4721 18.9383 19.9196 21.656 16.5682 22.7874Z" stroke="url(#paint7_linear_101_2703)" stroke-opacity="0.05" stroke-width="0.056338"/>
|
||||
<defs>
|
||||
<radialGradient id="paint0_radial_101_2703" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(-3.00503 15.023) rotate(-10.029) scale(17.9572 17.784)">
|
||||
<stop stop-color="#00B0BB"/>
|
||||
<stop offset="1" stop-color="#00DB65"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="paint1_linear_101_2703" x1="7.39036" y1="4.81308" x2="1.62975" y2="18.6894" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#18E299"/>
|
||||
<stop offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint2_linear_101_2703" x1="7.94816" y1="8.01563" x2="1.7612" y2="18.746" gradientUnits="userSpaceOnUse">
|
||||
<stop/>
|
||||
<stop offset="1" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint3_radial_101_2703" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(8.11404 20.8822) rotate(-75.7542) scale(21.6246 23.7772)">
|
||||
<stop stop-color="#00BBBB"/>
|
||||
<stop offset="0.712616" stop-color="#00DB65"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="paint4_linear_101_2703" x1="7.60205" y1="5.8709" x2="15.5561" y2="16.3719" gradientUnits="userSpaceOnUse">
|
||||
<stop/>
|
||||
<stop offset="1" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
<radialGradient id="paint5_radial_101_2703" cx="0" cy="0" r="1" gradientUnits="userSpaceOnUse" gradientTransform="translate(7.84537 21.5181) rotate(-20.3525) scale(18.5603 17.32)">
|
||||
<stop stop-color="#00B0BB"/>
|
||||
<stop offset="1" stop-color="#00DB65"/>
|
||||
</radialGradient>
|
||||
<linearGradient id="paint6_linear_101_2703" x1="16.8078" y1="13.0071" x2="10.0409" y2="22.9937" gradientUnits="userSpaceOnUse">
|
||||
<stop stop-color="#00B1BC"/>
|
||||
<stop offset="1"/>
|
||||
</linearGradient>
|
||||
<linearGradient id="paint7_linear_101_2703" x1="16.8078" y1="13.0071" x2="14.1687" y2="23.841" gradientUnits="userSpaceOnUse">
|
||||
<stop/>
|
||||
<stop offset="1" stop-opacity="0"/>
|
||||
</linearGradient>
|
||||
</defs>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 5.3 KiB |
@@ -0,0 +1,22 @@
|
||||
---
|
||||
title: OpenAI Compatibility
|
||||
---
|
||||
|
||||
Mem0 seamlessly offers an OpenAI-compatible API, making it easy to incorporate into existing projects.
|
||||
|
||||
## Mem0 Params for Chat Completion
|
||||
|
||||
- `user_id` (Optional[str]): Identifier for the user.
|
||||
|
||||
- `agent_id` (Optional[str]): Identifier for the agent.
|
||||
|
||||
- `run_id` (Optional[str]): Identifier for the run.
|
||||
|
||||
- `metadata` (Optional[dict]): Additional metadata to be stored with the memory.
|
||||
|
||||
- `filters` (Optional[dict]): Filters to apply when searching for relevant memories.
|
||||
|
||||
- `limit` (Optional[int]): Maximum number of relevant memories to retrieve. Default is 10.
|
||||
|
||||
|
||||
Other parameters are similar to OpenAI's API, making it easy to integrate Mem0 into your existing applications.
|
||||
|
After Width: | Height: | Size: 2.8 MiB |
|
After Width: | Height: | Size: 843 KiB |
|
Before Width: | Height: | Size: 256 KiB |
|
After Width: | Height: | Size: 177 KiB |
|
After Width: | Height: | Size: 4.6 MiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 565 KiB |
|
After Width: | Height: | Size: 3.9 MiB |
|
After Width: | Height: | Size: 180 KiB |
|
After Width: | Height: | Size: 169 KiB |
@@ -0,0 +1,211 @@
|
||||
---
|
||||
title: MultiOn
|
||||
---
|
||||
|
||||
Build personal browser agent remembers user preferences and automates web tasks. It integrates Mem0 for memory management with MultiOn for executing browser actions, enabling personalized and efficient web interactions.
|
||||
|
||||
## Overview
|
||||
|
||||
In this guide, we'll explore two examples of creating Browser-based AI Agents:
|
||||
1. An agent that searches [arxiv.org](https://arxiv.org) for research papers relevant to user's research interests.
|
||||
2. A travel agent that provides personalized travel information based on user preferences.
|
||||
|
||||
## Setup and Configuration
|
||||
|
||||
Install necessary libraries:
|
||||
|
||||
```bash
|
||||
pip install mem0ai multion openai
|
||||
```
|
||||
|
||||
First, we'll import the necessary libraries and set up our configurations.
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory, MemoryClient
|
||||
from multion.client import MultiOn
|
||||
from openai import OpenAI
|
||||
|
||||
# Configuration
|
||||
OPENAI_API_KEY = 'sk-xxx' # Replace with your actual OpenAI API key
|
||||
MULTION_API_KEY = 'your-multion-key' # Replace with your actual MultiOn API key
|
||||
MEM0_API_KEY = 'your-mem0-key' # Replace with your actual Mem0 API key
|
||||
USER_ID = "your-user-id"
|
||||
|
||||
# Set up OpenAI API key
|
||||
os.environ['OPENAI_API_KEY'] = OPENAI_API_KEY
|
||||
|
||||
# Initialize Mem0 and MultiOn
|
||||
memory = Memory() # For local usage
|
||||
memory_client = MemoryClient(api_key=MEM0_API_KEY) # For API usage
|
||||
multion = MultiOn(api_key=MULTION_API_KEY)
|
||||
```
|
||||
|
||||
## Example 1: Research Paper Search Agent
|
||||
|
||||
### Add memories to Mem0
|
||||
|
||||
Define user data and add it to Mem0.
|
||||
|
||||
```python
|
||||
USER_DATA = """
|
||||
About me
|
||||
- I'm Deshraj Yadav, Co-founder and CTO at Mem0, interested in AI and ML Infrastructure.
|
||||
- Previously, I was a Senior Autopilot Engineer at Tesla, leading the AI Platform for Autopilot.
|
||||
- I built EvalAI at Georgia Tech, an open-source platform for evaluating ML algorithms.
|
||||
- Outside of work, I enjoy playing cricket in two leagues in the San Francisco.
|
||||
"""
|
||||
|
||||
memory.add(USER_DATA, user_id=USER_ID)
|
||||
print("User data added to memory.")
|
||||
```
|
||||
|
||||
### Retrieving Relevant Memories
|
||||
|
||||
Define search command and retrieve relevant memories from Mem0.
|
||||
|
||||
```python
|
||||
command = "Find papers on arxiv that I should read based on my interests."
|
||||
|
||||
relevant_memories = memory.search(command, user_id=USER_ID, limit=3)
|
||||
relevant_memories_text = '\n'.join(mem['text'] for mem in relevant_memories)
|
||||
print(f"Relevant memories:")
|
||||
print(relevant_memories_text)
|
||||
```
|
||||
|
||||
### Browsing arXiv
|
||||
|
||||
Use MultiOn to browse arXiv based on the command and relevant memories.
|
||||
|
||||
```python
|
||||
prompt = f"{command}\n My past memories: {relevant_memories_text}"
|
||||
browse_result = multion.browse(cmd=prompt, url="https://arxiv.org/")
|
||||
print(browse_result)
|
||||
```
|
||||
|
||||
## Example 2: Travel Agent
|
||||
|
||||
### Get Travel Information
|
||||
|
||||
Add conversation to Mem0 and create a function to get travel information based on user's question and optionally their preferences from memory.
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
def get_travel_info(question, use_memory=True):
|
||||
if use_memory:
|
||||
previous_memories = memory_client.search(question, user_id=USER_ID)
|
||||
relevant_memories_text = ""
|
||||
if previous_memories:
|
||||
print("Using previous memories to enhance the search...")
|
||||
relevant_memories_text = '\n'.join(mem["memory"] for mem in previous_memories)
|
||||
|
||||
command = "Find travel information based on my interests:"
|
||||
prompt = f"{command}\n Question: {question} \n My preferences: {relevant_memories_text}"
|
||||
else:
|
||||
command = "Find travel information based on my interests:"
|
||||
prompt = f"{command}\n Question: {question}"
|
||||
|
||||
print("Searching for travel information...")
|
||||
browse_result = multion.browse(cmd=prompt)
|
||||
return browse_result.message
|
||||
|
||||
# Example usage
|
||||
question = "Show me flight details for it."
|
||||
answer_without_memory = get_travel_info(question, use_memory=False)
|
||||
answer_with_memory = get_travel_info(question, use_memory=True)
|
||||
|
||||
print("Answer without memory:", answer_without_memory)
|
||||
print("Answer with memory:", answer_with_memory)
|
||||
|
||||
# Another example
|
||||
question = "What is the best place to eat there?"
|
||||
answer_without_memory = get_travel_info(question, use_memory=False)
|
||||
answer_with_memory = get_travel_info(question, use_memory=True)
|
||||
|
||||
print("Answer without memory:", answer_without_memory)
|
||||
print("Answer with memory:", answer_with_memory)
|
||||
```
|
||||
|
||||
```json Conversation
|
||||
# Add conversation to Mem0
|
||||
conversation = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What are the best travel destinations in the world?"
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Could you please specify your interests or the type of travel information you are looking for? This will help me find the most relevant information for you."
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Sure, I want to travel to San Francisco."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": """
|
||||
Based on the information gathered from TripAdvisor, here are some popular attractions, activities, and travel tips for San Francisco: \
|
||||
|
||||
1. **Golden Gate Bridge**: A must-see iconic landmark. \
|
||||
2. **Alcatraz Island**: Famous former prison offering tours. \
|
||||
3. **Fisherman's Wharf**: Popular tourist area with shops, restaurants, and sea lions. \
|
||||
4. **Chinatown**: The largest Chinatown outside of Asia. \
|
||||
5. **Golden Gate Park**: Large urban park with gardens, museums, and recreational activities. \
|
||||
6. **Cable Cars**: Historic streetcars offering a unique way to see the city. \
|
||||
7. **Exploratorium**: Interactive science museum. \
|
||||
8. **San Francisco Museum of Modern Art (SFMOMA)**: Modern and contemporary art museum. \
|
||||
9. **Lombard Street**: Known for its steep, one-block section with eight hairpin turns. \
|
||||
10. **Union Square**: Major shopping and cultural hub. \
|
||||
|
||||
Travel Tips: \
|
||||
- **Weather**: San Francisco has a mild climate, but it can be foggy and windy. Dress in layers. \
|
||||
- **Transportation**: Use public transportation like BART, Muni, and cable cars to get around. \
|
||||
- **Safety**: Be aware of your surroundings, especially in crowded tourist areas. \
|
||||
- **Dining**: Try local specialties like sourdough bread, seafood, and Mission-style burritos. \
|
||||
"""
|
||||
},
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Show me hotels around Golden Gate Bridge."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": """The search results for hotels around Golden Gate Bridge in San Francisco include: \
|
||||
|
||||
1. Hilton Hotels In San Francisco - Hotel Near Fishermans Wharf (hilton.com) \
|
||||
2. The 10 Closest Hotels to Golden Gate Bridge (tripadvisor.com) \
|
||||
3. Hotels near Golden Gate Bridge (expedia.com) \
|
||||
4. Hotels near Golden Gate Bridge (hotels.com) \
|
||||
5. Holiday Inn Express & Suites San Francisco Fishermans Wharf, an IHG Hotel $146 (1.8K) 3-star hotel Golden Gate Bridge • 3.5 mi DEAL 19% less than usual \
|
||||
6. Holiday Inn San Francisco-Golden Gateway, an IHG Hotel $151 (3.5K) 3-star hotel Golden Gate Bridge • 3.7 mi Casual hotel with dining, a bar & a pool \
|
||||
7. Hotel Zephyr San Francisco $159 (3.8K) 4-star hotel Golden Gate Bridge • 3.7 mi Nautical-themed lodging with bay views \
|
||||
8. Lodge at the Presidio \
|
||||
9. The Inn Above Tide \
|
||||
10. Cavallo Point \
|
||||
11. Casa Madrona Hotel and Spa \
|
||||
12. Cow Hollow Inn and Suites \
|
||||
13. Samesun San Francisco \
|
||||
14. Inn on Broadway \
|
||||
15. Coventry Motor Inn \
|
||||
16. HI San Francisco Fisherman's Wharf Hostel \
|
||||
17. Loews Regency San Francisco Hotel \
|
||||
18. Fairmont Heritage Place Ghirardelli Square \
|
||||
19. Hotel Drisco Pacific Heights \
|
||||
20. Travelodge by Wyndham Presidio San Francisco \
|
||||
"""
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
## Conclusion
|
||||
|
||||
By integrating Mem0 with MultiOn, you've created personalized browser agents that remember user preferences and automate web tasks. The first example demonstrates a research-focused agent, while the second example shows a travel agent capable of providing personalized recommendations.
|
||||
|
||||
These examples illustrate how combining memory management with web browsing capabilities can create powerful, context-aware AI agents for various applications.
|
||||
|
||||
## Help
|
||||
|
||||
- For more details and advanced usage, refer to the full [cookbooks here](https://github.com/mem0ai/mem0/blob/main/cookbooks).
|
||||
- Feel free to visit our [Github](https://github.com/mem0ai/mem0) or [Mem0 Platform](https://app.mem0.ai/).
|
||||
- For any questions or assistance, please reach out to `taranjeetio` on [Discord](https://mem0.ai/discord).
|
||||
@@ -1,56 +0,0 @@
|
||||
---
|
||||
title: 📚 Introduction
|
||||
description: '📝 Embedchain is a framework to easily create LLM powered bots over any dataset.'
|
||||
---
|
||||
|
||||
## 🤔 What is Embedchain?
|
||||
|
||||
Embedchain abstracts the entire process of loading a dataset, chunking it, creating embeddings, and storing it in a vector database.
|
||||
|
||||
You can add a single or multiple datasets using the `.add` method. Then, simply use the `.query` method to find answers from the added datasets.
|
||||
|
||||
If you want to create a Naval Ravikant bot with a YouTube video, a book in PDF format, two blog posts, and a question and answer pair, all you need to do is add the respective links. Embedchain will take care of the rest, creating a bot for you.
|
||||
|
||||
```python
|
||||
from embedchain import App
|
||||
|
||||
naval_chat_bot = App()
|
||||
# Embed Online Resources
|
||||
naval_chat_bot.add("https://www.youtube.com/watch?v=3qHkcs3kG44")
|
||||
naval_chat_bot.add("https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf")
|
||||
naval_chat_bot.add("https://nav.al/feedback")
|
||||
naval_chat_bot.add("https://nav.al/agi")
|
||||
|
||||
# Embed Local Resources
|
||||
naval_chat_bot.add(("Who is Naval Ravikant?", "Naval Ravikant is an Indian-American entrepreneur and investor."))
|
||||
|
||||
naval_chat_bot.query("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?")
|
||||
# Answer: Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.
|
||||
```
|
||||
|
||||
## 🚀 How it works?
|
||||
|
||||
Creating a chat bot over any dataset involves the following steps:
|
||||
|
||||
1. Detect the data type and load the data
|
||||
2. Create meaningful chunks
|
||||
3. Create embeddings for each chunk
|
||||
4. Store the chunks in a vector database
|
||||
|
||||
When a user asks a query, the following process happens to find the answer:
|
||||
|
||||
1. Create an embedding for the query
|
||||
2. Find similar documents for the query from the vector database
|
||||
3. Pass the similar documents as context to LLM to get the final answer.
|
||||
|
||||
The process of loading the dataset and querying involves multiple steps, each with its own nuances:
|
||||
|
||||
- How should I chunk the data? What is a meaningful chunk size?
|
||||
- How should I create embeddings for each chunk? Which embedding model should I use?
|
||||
- How should I store the chunks in a vector database? Which vector database should I use?
|
||||
- Should I store metadata along with the embeddings?
|
||||
- How should I find similar documents for a query? Which ranking model should I use?
|
||||
|
||||
Embedchain takes care of all these nuances and provides a simple interface to create bots over any dataset.
|
||||
|
||||
In the first release, we make it easier for anyone to get a chatbot over any dataset up and running in less than a minute. Just create an app instance, add the datasets using the `.add` method, and use the `.query` method to get the relevant answers.
|
||||
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 13 KiB |
|
After Width: | Height: | Size: 66 KiB |
|
Before Width: | Height: | Size: 42 KiB After Width: | Height: | Size: 13 KiB |
@@ -1,55 +1,105 @@
|
||||
{
|
||||
"$schema": "https://mintlify.com/schema.json",
|
||||
"name": "Embedchain",
|
||||
"name": "Mem0.ai",
|
||||
"favicon": "/logo/favicon.png",
|
||||
"colors": {
|
||||
"primary": "#3B2FC9",
|
||||
"light": "#6673FF",
|
||||
"dark": "#3B2FC9",
|
||||
"background": {
|
||||
"dark": "#0f1117",
|
||||
"light": "#fff"
|
||||
}
|
||||
},
|
||||
"logo": {
|
||||
"dark": "/logo/dark.svg",
|
||||
"light": "/logo/light.svg"
|
||||
"light": "/logo/light.svg",
|
||||
"href": "https://github.com/mem0ai/mem0"
|
||||
},
|
||||
"favicon": "/favicon.png",
|
||||
"colors": {
|
||||
"primary": "#12A7D3",
|
||||
"light": "#81D7F7",
|
||||
"dark": "#004E7A"
|
||||
},
|
||||
"topbarLinks": [
|
||||
"tabs": [
|
||||
{
|
||||
"name": "Twitter",
|
||||
"url": "https://twitter.com/embedchain"
|
||||
"name": "💡 Examples",
|
||||
"url": "examples"
|
||||
},
|
||||
{
|
||||
"name": "Discord",
|
||||
"url": "https://discord.gg/6PzXDgEjG5"
|
||||
"name": "🖥️ Platform",
|
||||
"url": "platform"
|
||||
}
|
||||
],
|
||||
"topbarCtaButton": {
|
||||
"name": "GitHub",
|
||||
"url": "https://embedchain.ai"
|
||||
"name": "Your Memory Dashboard",
|
||||
"url": "https://app.mem0.ai"
|
||||
},
|
||||
"anchors": [
|
||||
{
|
||||
"name": "Your Memory Dashboard",
|
||||
"icon": "discord",
|
||||
"url": "https://app.mem0.ai"
|
||||
},
|
||||
{
|
||||
"name": "Discord",
|
||||
"icon": "discord",
|
||||
"url": "https://mem0.ai/discord"
|
||||
},
|
||||
{
|
||||
"name": "GitHub",
|
||||
"icon": "github",
|
||||
"url": "https://github.com/mem0ai/mem0"
|
||||
},
|
||||
{
|
||||
"name": "Support",
|
||||
"icon": "envelope",
|
||||
"url": "mailto:taranjeet@mem0.ai"
|
||||
}
|
||||
],
|
||||
"navigation": [
|
||||
{
|
||||
"group": "Getting started",
|
||||
"pages": ["quickstart", "introduction"]
|
||||
"group": "Get Started",
|
||||
"pages": [
|
||||
"overview",
|
||||
"quickstart"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Advanced",
|
||||
"pages": ["advanced/app_types", "advanced/interface_types", "advanced/adding_data", "advanced/data_types", "advanced/query_configuration", "advanced/configuration", "advanced/testing", "advanced/vector_database", "advanced/showcase"]
|
||||
"group": "Components",
|
||||
"pages": [
|
||||
"components/llms.mdx",
|
||||
"components/vectordb.mdx"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Examples",
|
||||
"pages": ["examples/full_stack", "examples/api_server", "examples/discord_bot", "examples/slack_bot", "examples/telegram_bot", "examples/whatsapp_bot", "examples/poe_bot"]
|
||||
"group": "Features",
|
||||
"pages":[
|
||||
"features/openai_compatibility"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "Contribution Guidelines",
|
||||
"pages": ["contribution/dev", "contribution/docs"]
|
||||
"group": "Integrations",
|
||||
"pages": [
|
||||
"integrations/multion"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "💡 Examples",
|
||||
"pages": [
|
||||
"examples/overview",
|
||||
"examples/personal-ai-tutor",
|
||||
"examples/customer-support-agent",
|
||||
"examples/personal-travel-assistant"
|
||||
]
|
||||
},
|
||||
{
|
||||
"group": "🖥️ Platform",
|
||||
"pages": [
|
||||
"platform/overview",
|
||||
"platform/quickstart"
|
||||
]
|
||||
}
|
||||
|
||||
],
|
||||
"footerSocials": {
|
||||
"twitter": "https://twitter.com/embedchain",
|
||||
"github": "https://github.com/embedchain/embedchain",
|
||||
"linkedin": "https://www.linkedin.com/company/embedchain",
|
||||
"website": "https://embedchain.ai"
|
||||
},
|
||||
"backgroundImage": "/background.png",
|
||||
"isWhiteLabeled": true
|
||||
}
|
||||
"discord": "https://mem0.ai/discord",
|
||||
"x": "https://x.com/mem0ai",
|
||||
"github": "https://github.com/mem0ai",
|
||||
"linkedin": "https://www.linkedin.com/company/mem0/"
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,62 @@
|
||||
---
|
||||
title: 📚 Overview
|
||||
description: 'Welcome to the Mem0 docs!'
|
||||
---
|
||||
|
||||
> Mem0 provides a smart, self-improving memory layer for Large Language Models, enabling personalized AI experiences across applications.
|
||||
|
||||
## Core features
|
||||
|
||||
- **User, Session, and AI Agent Memory**: Retains information across user sessions, interactions, and AI agents, ensuring continuity and context.
|
||||
- **Adaptive Personalization**: Continuously improves personalization based on user interactions and feedback.
|
||||
- **Developer-Friendly API**: Offers a straightforward API for seamless integration into various applications.
|
||||
- **Platform Consistency**: Ensures consistent behavior and data across different platforms and devices.
|
||||
- **Managed Service**: Provides a hosted solution for easy deployment and maintenance.
|
||||
|
||||
If you are looking to quick start, jump to one of the following links:
|
||||
|
||||
<CardGroup cols={2}>
|
||||
<Card title="Open Source Quickstart" icon="square-1" href="/quickstart/">
|
||||
Get started with Mem0 open source
|
||||
</Card>
|
||||
<Card title="Mem0 Platform Quickstart" icon="square-2" href="/platform/quickstart/">
|
||||
Begin with Mem0 Platform
|
||||
</Card>
|
||||
<Card title="Examples" icon="square-3" href="/examples/overview/">
|
||||
Explore practical use cases
|
||||
</Card>
|
||||
</CardGroup>
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
- **Personalized Learning Assistants**: Long-term memory allows learning assistants to remember user preferences, past interactions, and progress, providing a more tailored and effective learning experience.
|
||||
|
||||
- **Customer Support AI Agents**: By retaining information from previous interactions, customer support bots can offer more accurate and context-aware assistance, improving customer satisfaction and reducing resolution times.
|
||||
|
||||
- **Healthcare Assistants**: Long-term memory enables healthcare assistants to keep track of patient history, medication schedules, and treatment plans, ensuring personalized and consistent care.
|
||||
|
||||
- **Virtual Companions**: Virtual companions can use long-term memory to build deeper relationships with users by remembering personal details, preferences, and past conversations, making interactions more meaningful.
|
||||
|
||||
- **Productivity Tools**: Long-term memory helps productivity tools remember user habits, frequently used documents, and task history, streamlining workflows and enhancing efficiency.
|
||||
|
||||
- **Gaming AI**: In gaming, AI with long-term memory can create more immersive experiences by remembering player choices, strategies, and progress, adapting the game environment accordingly.
|
||||
|
||||
## How is Mem0 different from RAG?
|
||||
|
||||
Mem0's memory implementation for Large Language Models (LLMs) offers several advantages over Retrieval-Augmented Generation (RAG):
|
||||
|
||||
- **Entity Relationships**: Mem0 can understand and relate entities across different interactions, unlike RAG which retrieves information from static documents. This leads to a deeper understanding of context and relationships.
|
||||
|
||||
- **Recency, Relevancy, and Decay**: Mem0 prioritizes recent interactions and gradually forgets outdated information, ensuring the memory remains relevant and up-to-date for more accurate responses.
|
||||
|
||||
- **Contextual Continuity**: Mem0 retains information across sessions, maintaining continuity in conversations and interactions, which is essential for long-term engagement applications like virtual companions or personalized learning assistants.
|
||||
|
||||
- **Adaptive Learning**: Mem0 improves its personalization based on user interactions and feedback, making the memory more accurate and tailored to individual users over time.
|
||||
|
||||
- **Dynamic Updates**: Mem0 can dynamically update its memory with new information and interactions, unlike RAG which relies on static data. This allows for real-time adjustments and improvements, enhancing the user experience.
|
||||
|
||||
These advanced memory capabilities make Mem0 a powerful tool for developers aiming to create personalized and context-aware AI applications.
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -0,0 +1,45 @@
|
||||
---
|
||||
title: Introduction
|
||||
description: 'Empower your AI applications with long-term memory and personalization'
|
||||
---
|
||||
|
||||
## Welcome to Mem0 Platform
|
||||
|
||||
Mem0 Platform is a managed service that revolutionizes the way AI applications handle memory. By providing a smart, self-improving memory layer for Large Language Models (LLMs), we enable developers to create personalized AI experiences that evolve with each user interaction.
|
||||
|
||||
## Why Choose Mem0 Platform?
|
||||
|
||||
1. **Enhanced User Experience**: Deliver tailored interactions that make your AI applications truly stand out.
|
||||
2. **Simplified Development**: Our API-first approach streamlines integration, allowing you to focus on building great features.
|
||||
3. **Scalable Solution**: Designed to grow with your application, from prototypes to production-ready systems.
|
||||
|
||||
## Key Features
|
||||
|
||||
- **Comprehensive Memory Management**: Easily manage long-term, short-term, semantic, and episodic memories for individual users, agents, and sessions through our robust APIs.
|
||||
- **Self-Improving Memory**: Our adaptive system continuously learns from user interactions, refining its understanding over time.
|
||||
- **Cross-Platform Consistency**: Ensure a unified user experience across various AI platforms and applications.
|
||||
- **Centralized Memory Control**: Store, update, and delete memories effortlessly, taking away the hassle of memory management.
|
||||
|
||||
## Common Use Cases
|
||||
|
||||
- Personalized Learning Assistants
|
||||
- Customer Support AI Agents
|
||||
- Healthcare Assistants
|
||||
- Virtual Companions
|
||||
- Productivity Tools
|
||||
- Gaming AI
|
||||
|
||||
## Getting Started
|
||||
Ready to supercharge your AI application with Mem0? Follow these steps:
|
||||
|
||||
1. **Sign Up**: Create your Mem0 account at our platform.
|
||||
2. **API Key**: Generate your API key in the dashboard.
|
||||
3. **Installation**: Install our Python SDK using pip: `pip install mem0ai`
|
||||
4. **Quick Implementation**: Check out our [Quickstart Guide](/platform/quickstart) to start using Mem0 quickly.
|
||||
|
||||
## Next Steps
|
||||
|
||||
- Explore our API Reference for detailed endpoint documentation.
|
||||
- Join our [slack](https://mem0.ai/slack) or [discord](https://mem0.ai/discord) with other developers and get support.
|
||||
|
||||
We're excited to see what you'll build with Mem0 Platform. Let's create smarter, more personalized AI experiences together!
|
||||
@@ -0,0 +1,620 @@
|
||||
---
|
||||
title: Quickstart
|
||||
description: 'Get started with Mem0 Platform in minutes'
|
||||
---
|
||||
|
||||
## 1. Installation
|
||||
|
||||
<CodeGroup>
|
||||
```bash pip
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
```bash npm
|
||||
npm install mem0ai
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## 2. API Key Setup
|
||||
|
||||
1. Sign in to [Mem0 Platform](https://app.mem0.ai/dashboard/api-keys)
|
||||
2. Copy your API Key from the dashboard
|
||||
|
||||

|
||||
|
||||
## 3. Instantiate Client
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
from mem0 import MemoryClient
|
||||
client = MemoryClient(api_key="your-api-key")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const MemoryClient = require('mem0ai');
|
||||
const client = new MemoryClient('your-api-key');
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
## 4. Memory Operations
|
||||
|
||||
Mem0 provides a simple and customizable interface for performing CRUD operations on memory.
|
||||
|
||||
### 4.1 Create Memories
|
||||
|
||||
You can create long-term and short-term memories for your users, AI Agents, etc. Here are some examples:
|
||||
|
||||
#### Long-term memory for a user
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
client.add(messages, user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
];
|
||||
client.add(messages, { user_id: "alex" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
],
|
||||
"user_id": "alex"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'ok'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#### Short-term memory for a user session
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
messages = [
|
||||
{"role": "user", "content": "I'm planning a trip to Japan next month."},
|
||||
{"role": "assistant", "content": "That's exciting, Alex! A trip to Japan next month sounds wonderful. Would you like some recommendations for vegetarian-friendly restaurants in Japan?"},
|
||||
{"role": "user", "content": "Yes, please! Especially in Tokyo."},
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
]
|
||||
client.add(messages, user_id="alex123", session_id="trip-planning-2024")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const messages = [
|
||||
{"role": "user", "content": "I'm planning a trip to Japan next month."},
|
||||
{"role": "assistant", "content": "That's exciting, Alex! A trip to Japan next month sounds wonderful. Would you like some recommendations for vegetarian-friendly restaurants in Japan?"},
|
||||
{"role": "user", "content": "Yes, please! Especially in Tokyo."},
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
];
|
||||
client.add(messages, { user_id: "alex123", session_id: "trip-planning-2024" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "I'm planning a trip to Japan next month."},
|
||||
{"role": "assistant", "content": "That's exciting, Alex! A trip to Japan next month sounds wonderful. Would you like some recommendations for vegetarian-friendly restaurants in Japan?"},
|
||||
{"role": "user", "content": "Yes, please! Especially in Tokyo."},
|
||||
{"role": "assistant", "content": "Great! I'll remember that you're interested in vegetarian restaurants in Tokyo for your upcoming trip. I'll prepare a list for you in our next interaction."}
|
||||
],
|
||||
"user_id": "alex123",
|
||||
"session_id": "trip-planning-2024"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'ok'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#### Long-term memory for agents
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
messages = [
|
||||
{"role": "system", "content": "You are a personalized travel assistant. Remember user preferences and provide tailored recommendations."},
|
||||
{"role": "assistant", "content": "Understood. I'll maintain personalized travel preferences for each user and provide customized recommendations based on their dietary restrictions, interests, and past interactions."}
|
||||
]
|
||||
client.add(messages, agent_id="travel-assistant")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const messages = [
|
||||
{"role": "system", "content": "You are a personalized travel assistant. Remember user preferences and provide tailored recommendations."},
|
||||
{"role": "assistant", "content": "Understood. I'll maintain personalized travel preferences for each user and provide customized recommendations based on their dietary restrictions, interests, and past interactions."}
|
||||
];
|
||||
client.add(messages, { agent_id: "travel-assistant" })
|
||||
.then(response => console.log(response))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "system", "content": "You are a personalized travel assistant. Remember user preferences and provide tailored recommendations."},
|
||||
{"role": "assistant", "content": "Understood. I'll maintain personalized travel preferences for each user and provide customized recommendations based on their dietary restrictions, interests, and past interactions."}
|
||||
],
|
||||
"agent_id": "travel-assistant"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'ok'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
You can monitor memory operations on the platform:
|
||||
|
||||

|
||||
|
||||
### 4.2 Search Relevant Memories
|
||||
|
||||
You can also get related memories for a given natural language question using our search method.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
query = "What do you know about me?"
|
||||
client.search(query, user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const query = "What do you know about me?";
|
||||
client.search(query, { user_id: "alex" })
|
||||
.then(results => console.log(results))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/search/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"query": "What do you know about me?",
|
||||
"user_id": "alex"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id": "7f165f7e-b411-4afe-b7e5-35789b72c4a5",
|
||||
"memory": "Name: Alex. Vegetarian. Allergic to nuts.",
|
||||
"input": [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."
|
||||
},
|
||||
{
|
||||
"role": "assistant",
|
||||
"content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."
|
||||
}
|
||||
],
|
||||
"user_id": "alex",
|
||||
"hash": "9ee7e1455e84d1dab700ed8749aed75a",
|
||||
"metadata": null,
|
||||
"created_at": "2024-07-20T01:30:36.275141-07:00",
|
||||
"updated_at": "2024-07-20T01:30:36.275172-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 4.3 Get All Memories
|
||||
|
||||
Fetch all memories for a user, agent, or session using the getAll() method.
|
||||
|
||||
#### Get all memories of an AI Agent
|
||||
|
||||
<CodeGroup>
|
||||
```python Python
|
||||
client.get_all(agent_id="travel-assistant")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.getAll({ agent_id: "travel-assistant" })
|
||||
.then(memories => console.log(memories))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/?agent_id=travel-assistant" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00"
|
||||
},
|
||||
{
|
||||
"id":"0a14d8f0-e364-4f5c-b305-10da1f0d0878",
|
||||
"memory":"Will maintain personalized travel preferences for each user. Provide customized recommendations based on dietary restrictions, interests, and past interactions.",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#### Get all memories of user
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
user_memories = client.get_all(user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.getAll({ user_id: "alex" })
|
||||
.then(memories => console.log(memories))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"f38b689d-6b24-45b7-bced-17fbb4d8bac7",
|
||||
"memory":"是素食主义者,对坚果过敏。",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"62bc074f56d1f909f1b4c2b639f56f6a",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-25T23:57:00.108347-07:00",
|
||||
"updated_at":"2024-07-25T23:57:00.108367-07:00"
|
||||
},
|
||||
{
|
||||
"id":"0a14d8f0-e364-4f5c-b305-10da1f0d0878",
|
||||
"memory":"Will maintain personalized travel preferences for each user. Provide customized recommendations based on dietary restrictions, interests, and past interactions.",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"35a305373d639b0bffc6c2a3e2eb4244",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:31:03.543759-07:00",
|
||||
"updated_at":"2024-07-26T00:31:03.543778-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#### Get short-term memories for a session
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
short_term_memories = client.get_all(user_id="alex123", session_id="trip-planning-2024")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.getAll({ user_id: "alex123", session_id: "trip-planning-2024" })
|
||||
.then(memories => console.log(memories))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/?user_id=alex123&session_id=trip-planning-2024" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"06d8df63-7bd2-4fad-9acb-60871bcecee0",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at":"2024-07-26T00:25:16.566492-07:00"
|
||||
},
|
||||
{
|
||||
"id":"b4229775-d860-4ccb-983f-0f628ca112f5",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:33:20.350542-07:00",
|
||||
"updated_at":"2024-07-26T00:33:20.350560-07:00"
|
||||
},
|
||||
{
|
||||
"id":"df1aca24-76cf-4b92-9f58-d03857efcb64",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:51:09.642275-07:00",
|
||||
"updated_at":"2024-07-26T00:51:09.642295-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
#### Get specific memory
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
memory = client.get(memory_id="582bbe6d-506b-48c6-a4c6-5df3b1e63428")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.get("582bbe6d-506b-48c6-a4c6-5df3b1e63428")
|
||||
.then(memory => console.log(memory))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/582bbe6d-506b-48c6-a4c6-5df3b1e63428" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id":"06d8df63-7bd2-4fad-9acb-60871bcecee0",
|
||||
"memory":"Planning a trip to Japan next month. Interested in vegetarian restaurants in Tokyo.",
|
||||
"user_id":"alex123",
|
||||
"hash":"d2088c936e259f2f5d2d75543d31401c",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T00:25:16.566471-07:00",
|
||||
"updated_at":"2024-07-26T00:25:16.566492-07:00"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 4.4 Memory History
|
||||
|
||||
Get history of how a memory has changed over time
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
# Add some message to create history
|
||||
messages = [{"role": "user", "content": "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."}]
|
||||
client.add(messages, user_id="alex")
|
||||
|
||||
# Add second message to update history
|
||||
messages.append({'role': 'user', 'content': 'I turned vegetarian now.'})
|
||||
client.add(messages, user_id="alex")
|
||||
|
||||
# Get history of how memory changed over time
|
||||
memory_id = "<memory-id-here>"
|
||||
history = client.history(memory_id)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
// Add some message to create history
|
||||
let messages = [{ role: "user", content: "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.." }];
|
||||
client.add(messages, { user_id: "alex" })
|
||||
.then(result => {
|
||||
// Add second message to update history
|
||||
messages.push({ role: 'user', content: 'I turned vegetarian now.' });
|
||||
return client.add(messages, { user_id: "alex" });
|
||||
})
|
||||
.then(result => {
|
||||
// Get history of how memory changed over time
|
||||
const memoryId = result.id; // Assuming the API returns the memory ID
|
||||
return client.history(memoryId);
|
||||
})
|
||||
.then(history => console.log(history))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
# First, add the initial memory
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."}],
|
||||
"user_id": "alex"
|
||||
}'
|
||||
|
||||
# Then, update the memory
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [
|
||||
{"role": "user", "content": "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."},
|
||||
{"role": "user", "content": "I turned vegetarian now."}
|
||||
],
|
||||
"user_id": "alex"
|
||||
}'
|
||||
|
||||
# Finally, get the history (replace <memory-id-here> with the actual memory ID)
|
||||
curl -X GET "https://api.mem0.ai/v1/memories/<memory-id-here>/history/" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"d6306e85-eaa6-400c-8c2f-ab994a8c4d09",
|
||||
"memory_id":"b163df0e-ebc8-4098-95df-3f70a733e198",
|
||||
"input":[
|
||||
{
|
||||
"role":"user",
|
||||
"content":"I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."
|
||||
},
|
||||
{
|
||||
"role":"user",
|
||||
"content":"I turned vegetarian now."
|
||||
}
|
||||
],
|
||||
"old_memory":"None",
|
||||
"new_memory":"Turned vegetarian.",
|
||||
"user_id":"alex123456",
|
||||
"event":"ADD",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T01:02:41.737310-07:00",
|
||||
"updated_at":"2024-07-26T01:02:41.726073-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### 4.5 Update Memory
|
||||
|
||||
Update a memory with new data.
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
message = "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."
|
||||
client.update(memory_id, message)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
const message = "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes..";
|
||||
client.update("memory-id-here", message)
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X PUT "https://api.mem0.ai/v1/memories/memory-id-here" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"message": "I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes.."
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id":"c190ab1a-a2f1-4f6f-914a-495e9a16b76e",
|
||||
"memory":"I recently tried chicken and I loved it. I'm thinking of trying more non-vegetarian dishes..",
|
||||
"agent_id":"travel-assistant",
|
||||
"hash":"af1161983e03667063d1abb60e6d5c06",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-30T22:46:40.455758-07:00",
|
||||
"updated_at":"2024-07-30T22:48:35.257828-07:00"
|
||||
}
|
||||
```
|
||||
|
||||
</CodeGroup>
|
||||
|
||||
### 4.6 Delete Memory
|
||||
|
||||
Delete specific memory:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.delete(memory_id)
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.delete("memory-id-here")
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.mem0.ai/v1/memories/memory-id-here" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Memory deleted successfully'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Delete all memories of a user:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.delete_all(user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.deleteAll({ user_id: "alex" })
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X DELETE "https://api.mem0.ai/v1/memories/?user_id=alex" \
|
||||
-H "Authorization: Token your-api-key"
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Memories deleted successfully!'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
Fun fact: You can also delete the memory using the `add()` method by passing a natural language command:
|
||||
|
||||
<CodeGroup>
|
||||
|
||||
```python Python
|
||||
client.add("Delete all of my food preferences", user_id="alex")
|
||||
```
|
||||
|
||||
```javascript JavaScript
|
||||
client.add("Delete all of my food preferences", { user_id: "alex" })
|
||||
.then(result => console.log(result))
|
||||
.catch(error => console.error(error));
|
||||
```
|
||||
|
||||
```bash cURL
|
||||
curl -X POST "https://api.mem0.ai/v1/memories/" \
|
||||
-H "Authorization: Token your-api-key" \
|
||||
-H "Content-Type: application/json" \
|
||||
-d '{
|
||||
"messages": [{"role": "user", "content": "Delete all of my food preferences"}],
|
||||
"user_id": "alex"
|
||||
}'
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'ok'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -1,35 +1,298 @@
|
||||
---
|
||||
title: '🚀 Quickstart'
|
||||
description: '💡 Start building LLM powered bots under 30 seconds'
|
||||
title: 🚀 Quickstart
|
||||
description: 'Get started with Mem0 quickly!'
|
||||
---
|
||||
|
||||
Install embedchain python package:
|
||||
> Welcome to the Mem0 quickstart guide. This guide will help you get up and running with Mem0 in no time.
|
||||
|
||||
## Installation
|
||||
|
||||
To install Mem0, you can use pip. Run the following command in your terminal:
|
||||
|
||||
```bash
|
||||
pip install --upgrade embedchain
|
||||
pip install mem0ai
|
||||
```
|
||||
|
||||
Creating a chatbot involves 3 steps:
|
||||
## Basic Usage
|
||||
|
||||
- ⚙️ Import the App instance
|
||||
- 🗃️ Add Dataset
|
||||
- 💬 Query or Chat on the dataset and get answers (Interface Types)
|
||||
### Initialize Mem0
|
||||
|
||||
Run your first bot in python using the following code. Make sure to set the `OPENAI_API_KEY` 🔑 environment variable in the code.
|
||||
<Tabs>
|
||||
<Tab title="Basic">
|
||||
```python
|
||||
from mem0 import Memory
|
||||
m = Memory()
|
||||
```
|
||||
</Tab>
|
||||
<Tab title="Advanced">
|
||||
If you want to run Mem0 in production, initialize using the following method:
|
||||
|
||||
Run Qdrant first:
|
||||
|
||||
```bash
|
||||
docker pull qdrant/qdrant
|
||||
|
||||
docker run -p 6333:6333 -p 6334:6334 \
|
||||
-v $(pwd)/qdrant_storage:/qdrant/storage:z \
|
||||
qdrant/qdrant
|
||||
```
|
||||
|
||||
Then, instantiate memory with qdrant server:
|
||||
|
||||
```python
|
||||
import os
|
||||
from mem0 import Memory
|
||||
|
||||
from embedchain import App
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
os.environ["OPENAI_API_KEY"] = "xxx"
|
||||
elon_musk_bot = App()
|
||||
|
||||
# Embed Online Resources
|
||||
elon_musk_bot.add("https://en.wikipedia.org/wiki/Elon_Musk")
|
||||
elon_musk_bot.add("https://www.tesla.com/elon-musk")
|
||||
|
||||
response = elon_musk_bot.query("How many companies does Elon Musk run?")
|
||||
print(response)
|
||||
# Answer: 'Elon Musk runs four companies: Tesla, SpaceX, Neuralink, and The Boring Company.'
|
||||
m = Memory.from_config(config)
|
||||
```
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
|
||||
### Store a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# For a user
|
||||
result = m.add("Likes to play cricket on weekends", user_id="alice", metadata={"category": "hobbies"})
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'ok'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Retrieve Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get all memories
|
||||
all_memories = m.get_all()
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"13efe83b-a8df-4ec0-814e-428d6e8451eb",
|
||||
"memory":"Likes to play cricket on weekends",
|
||||
"hash":"87bcddeb-fe45-4353-bc22-15a841c50308",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T08:44:41.039788-07:00",
|
||||
"updated_at":"None",
|
||||
"user_id":"alice"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
# Get a single memory by ID
|
||||
specific_memory = m.get("m1")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{
|
||||
"id":"13efe83b-a8df-4ec0-814e-428d6e8451eb",
|
||||
"memory":"Likes to play cricket on weekends",
|
||||
"hash":"87bcddeb-fe45-4353-bc22-15a841c50308",
|
||||
"metadata":"None",
|
||||
"created_at":"2024-07-26T08:44:41.039788-07:00",
|
||||
"updated_at":"None",
|
||||
"user_id":"alice"
|
||||
}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Search Memories
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
related_memories = m.search(query="What are Alice's hobbies?", user_id="alice")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"ea925981-272f-40dd-b576-be64e4871429",
|
||||
"memory":"Likes to play cricket and plays cricket on weekends.",
|
||||
"hash":"c8809002-25c1-4c97-a3a2-227ce9c20c53",
|
||||
"metadata":{
|
||||
"category":"hobbies"
|
||||
},
|
||||
"score":0.32116443111457704,
|
||||
"created_at":"2024-07-26T10:29:36.630547-07:00",
|
||||
"updated_at":"None",
|
||||
"user_id":"alice"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Update a Memory
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
result = m.update(memory_id="m1", data="Likes to play tennis on weekends")
|
||||
```
|
||||
|
||||
```json Output
|
||||
{'message': 'Memory updated successfully!'}
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Memory History
|
||||
|
||||
<CodeGroup>
|
||||
```python Code
|
||||
history = m.history(memory_id="m1")
|
||||
```
|
||||
|
||||
```json Output
|
||||
[
|
||||
{
|
||||
"id":"4e0e63d6-a9c6-43c0-b11c-a1bad3fc7abb",
|
||||
"memory_id":"ea925981-272f-40dd-b576-be64e4871429",
|
||||
"old_memory":"None",
|
||||
"new_memory":"Likes to play cricket and plays cricket on weekends.",
|
||||
"event":"ADD",
|
||||
"created_at":"2024-07-26T10:29:36.630547-07:00",
|
||||
"updated_at":"None"
|
||||
},
|
||||
{
|
||||
"id":"548b75f0-f442-44b9-9ca1-772a105abb12",
|
||||
"memory_id":"ea925981-272f-40dd-b576-be64e4871429",
|
||||
"old_memory":"Likes to play cricket and plays cricket on weekends.",
|
||||
"new_memory":"Likes to play tennis on weekends",
|
||||
"event":"UPDATE",
|
||||
"created_at":"2024-07-26T10:29:36.630547-07:00",
|
||||
"updated_at":"2024-07-26T10:32:46.332336-07:00"
|
||||
}
|
||||
]
|
||||
```
|
||||
</CodeGroup>
|
||||
|
||||
### Delete Memory
|
||||
|
||||
```python
|
||||
m.delete(memory_id="m1") # Delete a memory
|
||||
|
||||
m.delete_all(user_id="alice") # Delete all memories
|
||||
```
|
||||
|
||||
### Reset Memory
|
||||
|
||||
```python
|
||||
m.reset() # Reset all memories
|
||||
```
|
||||
|
||||
## Chat Completion
|
||||
|
||||
Mem0 can be easily integrate into chat applications to enhance conversational agents with structured memory. Mem0's APIs are designed to be compatible with OpenAI's, with the goal of making it easy to leverage Mem0 in applications you may have already built.
|
||||
|
||||
If you have a `Mem0 API key`, you can use it to initialize the client. Alternatively, you can initialize Mem0 without an API key if you're using it locally.
|
||||
|
||||
Mem0 supports several language models (LLMs) through integration with various [providers](https://litellm.vercel.app/docs/providers).
|
||||
|
||||
## Use Mem0 Platform
|
||||
|
||||
```python
|
||||
from mem0 import Mem0
|
||||
|
||||
client = Mem0(api_key="m0-xxx")
|
||||
|
||||
# First interaction: Storing user preferences
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "I love indian food but I cannot eat pizza since allergic to cheese."
|
||||
},
|
||||
]
|
||||
user_id = "deshraj"
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
# Memory saved after this will look like: "Loves Indian food. Allergic to cheese and cannot eat pizza."
|
||||
|
||||
# Second interaction: Leveraging stored memory
|
||||
messages = [
|
||||
{
|
||||
"role": "user",
|
||||
"content": "Suggest restaurants in San Francisco to eat.",
|
||||
}
|
||||
]
|
||||
|
||||
chat_completion = client.chat.completions.create(messages=messages, model="gpt-4o-mini", user_id=user_id)
|
||||
print(chat_completion.choices[0].message.content)
|
||||
# Answer: You might enjoy Indian restaurants in San Francisco, such as Amber India, Dosa, or Curry Up Now, which offer delicious options without cheese.
|
||||
```
|
||||
|
||||
In this example, you can see how the second response is tailored based on the information provided in the first interaction. Mem0 remembers the user's preference for Indian food and their cheese allergy, using this information to provide more relevant and personalized restaurant suggestions in San Francisco.
|
||||
|
||||
### Use Mem0 OSS
|
||||
|
||||
```python
|
||||
config = {
|
||||
"vector_store": {
|
||||
"provider": "qdrant",
|
||||
"config": {
|
||||
"host": "localhost",
|
||||
"port": 6333,
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
client = Mem0(config=config)
|
||||
|
||||
chat_completion = client.chat.completions.create(
|
||||
messages=[
|
||||
{
|
||||
"role": "user",
|
||||
"content": "What's the capital of France?",
|
||||
}
|
||||
],
|
||||
model="gpt-4o",
|
||||
)
|
||||
```
|
||||
|
||||
## APIs
|
||||
|
||||
Get started with using Mem0 APIs in your applications. For more details, refer to the [Platform](/platform/quickstart.mdx).
|
||||
|
||||
Here is an example of how to use Mem0 APIs:
|
||||
|
||||
```python
|
||||
from mem0 import MemoryClient
|
||||
client = MemoryClient(api_key="your-api-key") # get api_key from https://app.mem0.ai/
|
||||
|
||||
# Store messages
|
||||
messages = [
|
||||
{"role": "user", "content": "Hi, I'm Alex. I'm a vegetarian and I'm allergic to nuts."},
|
||||
{"role": "assistant", "content": "Hello Alex! I've noted that you're a vegetarian and have a nut allergy. I'll keep this in mind for any food-related recommendations or discussions."}
|
||||
]
|
||||
result = client.add(messages, user_id="alex")
|
||||
print(result)
|
||||
|
||||
# Retrieve memories
|
||||
all_memories = client.get_all(user_id="alex")
|
||||
print(all_memories)
|
||||
|
||||
# Search memories
|
||||
query = "What do you know about me?"
|
||||
related_memories = client.search(query, user_id="alex")
|
||||
|
||||
# Get memory history
|
||||
history = client.history(memory_id="m1")
|
||||
print(history)
|
||||
```
|
||||
|
||||
If you have any questions, please feel free to reach out to us using one of the following methods:
|
||||
|
||||
<Snippet file="get-help.mdx" />
|
||||
@@ -0,0 +1,4 @@
|
||||
One of the core principles of software development is DRY (Don't Repeat
|
||||
Yourself). This is a principle that apply to documentation as
|
||||
well. If you find yourself repeating the same content in multiple places, you
|
||||
should consider creating a custom snippet to keep your content in sync.
|
||||
@@ -1,2 +0,0 @@
|
||||
node_modules
|
||||
dist
|
||||
@@ -1,56 +0,0 @@
|
||||
{
|
||||
// Configuration for JavaScript files
|
||||
"extends": [
|
||||
"airbnb-base",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"singleQuote": true,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
]
|
||||
},
|
||||
"overrides": [
|
||||
// Configuration for TypeScript files
|
||||
{
|
||||
"files": ["**/*.ts", "**/__tests__/*.test.ts"],
|
||||
"plugins": [
|
||||
"@typescript-eslint",
|
||||
"unused-imports",
|
||||
"simple-import-sort"
|
||||
],
|
||||
"extends": [
|
||||
"airbnb-typescript",
|
||||
"plugin:prettier/recommended"
|
||||
],
|
||||
"parserOptions": {
|
||||
"project": "./tsconfig.json"
|
||||
},
|
||||
"rules": {
|
||||
"prettier/prettier": [
|
||||
"error",
|
||||
{
|
||||
"singleQuote": true,
|
||||
"endOfLine": "auto"
|
||||
}
|
||||
],
|
||||
"@typescript-eslint/comma-dangle": "off", // Avoid conflict rule between Eslint and Prettier
|
||||
"@typescript-eslint/consistent-type-imports": "error", // Ensure `import type` is used when it's necessary
|
||||
"import/prefer-default-export": "off", // Named export is easier to refactor automatically
|
||||
"simple-import-sort/imports": "error", // Import configuration for `eslint-plugin-simple-import-sort`
|
||||
"simple-import-sort/exports": "error", // Export configuration for `eslint-plugin-simple-import-sort`
|
||||
"@typescript-eslint/no-unused-vars": "off",
|
||||
"react/jsx-filename-extension": "off", // Gives error
|
||||
"unused-imports/no-unused-imports": "error",
|
||||
"unused-imports/no-unused-vars": [
|
||||
"error",
|
||||
{ "argsIgnorePattern": "^_" }
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,47 +0,0 @@
|
||||
name: Node.js Package
|
||||
|
||||
on:
|
||||
release:
|
||||
types: [created]
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
- run: npm ci
|
||||
- run: npm test
|
||||
- run: npm run build
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
- uses: actions/upload-artifact@v3
|
||||
with:
|
||||
name: types
|
||||
path: types
|
||||
|
||||
publish-npm:
|
||||
needs: build
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v3
|
||||
- uses: actions/setup-node@v3
|
||||
with:
|
||||
node-version: 16
|
||||
registry-url: https://registry.npmjs.org/
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: dist
|
||||
path: dist
|
||||
- uses: actions/download-artifact@v3
|
||||
with:
|
||||
name: types
|
||||
path: types
|
||||
- run: npm ci
|
||||
- run: npm publish
|
||||
env:
|
||||
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
||||
@@ -1,138 +0,0 @@
|
||||
# Logs
|
||||
logs
|
||||
*.log
|
||||
npm-debug.log*
|
||||
yarn-debug.log*
|
||||
yarn-error.log*
|
||||
lerna-debug.log*
|
||||
.pnpm-debug.log*
|
||||
|
||||
# Diagnostic reports (https://nodejs.org/api/report.html)
|
||||
report.[0-9]*.[0-9]*.[0-9]*.[0-9]*.json
|
||||
|
||||
# Runtime data
|
||||
pids
|
||||
*.pid
|
||||
*.seed
|
||||
*.pid.lock
|
||||
|
||||
# Directory for instrumented libs generated by jscoverage/JSCover
|
||||
lib-cov
|
||||
|
||||
# Coverage directory used by tools like istanbul
|
||||
coverage
|
||||
*.lcov
|
||||
|
||||
# nyc test coverage
|
||||
.nyc_output
|
||||
|
||||
# Grunt intermediate storage (https://gruntjs.com/creating-plugins#storing-task-files)
|
||||
.grunt
|
||||
|
||||
# Bower dependency directory (https://bower.io/)
|
||||
bower_components
|
||||
|
||||
# node-waf configuration
|
||||
.lock-wscript
|
||||
|
||||
# Compiled binary addons (https://nodejs.org/api/addons.html)
|
||||
build/Release
|
||||
|
||||
# Dependency directories
|
||||
node_modules/
|
||||
jspm_packages/
|
||||
|
||||
# Snowpack dependency directory (https://snowpack.dev/)
|
||||
web_modules/
|
||||
|
||||
# TypeScript cache
|
||||
*.tsbuildinfo
|
||||
|
||||
# Optional npm cache directory
|
||||
.npm
|
||||
|
||||
# Optional eslint cache
|
||||
.eslintcache
|
||||
|
||||
# Optional stylelint cache
|
||||
.stylelintcache
|
||||
|
||||
# Microbundle cache
|
||||
.rpt2_cache/
|
||||
.rts2_cache_cjs/
|
||||
.rts2_cache_es/
|
||||
.rts2_cache_umd/
|
||||
|
||||
# Optional REPL history
|
||||
.node_repl_history
|
||||
|
||||
# Output of 'npm pack'
|
||||
*.tgz
|
||||
|
||||
# Yarn Integrity file
|
||||
.yarn-integrity
|
||||
|
||||
# dotenv environment variable files
|
||||
.env
|
||||
.env.development.local
|
||||
.env.test.local
|
||||
.env.production.local
|
||||
.env.local
|
||||
|
||||
# parcel-bundler cache (https://parceljs.org/)
|
||||
.cache
|
||||
.parcel-cache
|
||||
|
||||
# Next.js build output
|
||||
.next
|
||||
out
|
||||
|
||||
# Nuxt.js build / generate output
|
||||
.nuxt
|
||||
dist
|
||||
|
||||
# Gatsby files
|
||||
.cache/
|
||||
# Comment in the public line in if your project uses Gatsby and not Next.js
|
||||
# https://nextjs.org/blog/next-9-1#public-directory-support
|
||||
# public
|
||||
|
||||
# vuepress build output
|
||||
.vuepress/dist
|
||||
|
||||
# vuepress v2.x temp and cache directory
|
||||
.temp
|
||||
.cache
|
||||
|
||||
# Docusaurus cache and generated files
|
||||
.docusaurus
|
||||
|
||||
# Serverless directories
|
||||
.serverless/
|
||||
|
||||
# FuseBox cache
|
||||
.fusebox/
|
||||
|
||||
# DynamoDB Local files
|
||||
.dynamodb/
|
||||
|
||||
# TernJS port file
|
||||
.tern-port
|
||||
|
||||
# Stores VSCode versions used for testing VSCode extensions
|
||||
.vscode-test
|
||||
|
||||
# yarn v2
|
||||
.yarn/cache
|
||||
.yarn/unplugged
|
||||
.yarn/build-state.yml
|
||||
.yarn/install-state.gz
|
||||
.pnp.*
|
||||
|
||||
.ideas.md
|
||||
.todos.md
|
||||
|
||||
# Custom
|
||||
dist
|
||||
types
|
||||
build
|
||||
@@ -1,4 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
npx --no -- commitlint --edit $1
|
||||
@@ -1,5 +0,0 @@
|
||||
#!/bin/sh
|
||||
. "$(dirname "$0")/_/husky.sh"
|
||||
|
||||
# Disable concurent to run `check-types` after ESLint in lint-staged
|
||||
npx lint-staged --concurrent false
|
||||
@@ -1,8 +0,0 @@
|
||||
cff-version: 1.2.0
|
||||
message: "If you use this software, please cite it as below."
|
||||
authors:
|
||||
- family-names: "Singh"
|
||||
given-names: "Taranjeet"
|
||||
title: "Embedchain"
|
||||
date-released: 2023-06-25
|
||||
url: "https://github.com/embedchain/embedchainjs"
|
||||
@@ -1,263 +0,0 @@
|
||||
# embedchainjs
|
||||
|
||||
[](https://discord.gg/CUU9FPhRNt)
|
||||
[](https://twitter.com/embedchain)
|
||||
[](https://embedchain.substack.com/)
|
||||
|
||||
embedchain is a framework to easily create LLM powered bots over any dataset. embedchainjs is Javascript version of embedchain. If you want a python version, check out [embedchain-python](https://github.com/embedchain/embedchain)
|
||||
|
||||
# 🤝 Let's Talk Embedchain!
|
||||
|
||||
Schedule a [Feedback Session](https://cal.com/taranjeetio/ec) with Taranjeet, the founder, to discuss any issues, provide feedback, or explore improvements.
|
||||
|
||||
# How it works
|
||||
|
||||
It abstracts the entire process of loading dataset, chunking it, creating embeddings and then storing in vector database.
|
||||
|
||||
You can add a single or multiple dataset using `.add` and `.addLocal` function and then use `.query` function to find an answer from the added datasets.
|
||||
|
||||
If you want to create a Naval Ravikant bot which has 2 of his blog posts, as well as a question and answer pair you supply, all you need to do is add the links to the blog posts and the QnA pair and embedchain will create a bot for you.
|
||||
|
||||
```javascript
|
||||
const dotenv = require("dotenv");
|
||||
dotenv.config();
|
||||
const { App } = require("embedchain");
|
||||
|
||||
//Run the app commands inside an async function only
|
||||
async function testApp() {
|
||||
const navalChatBot = await App();
|
||||
|
||||
// Embed Online Resources
|
||||
await navalChatBot.add("web_page", "https://nav.al/feedback");
|
||||
await navalChatBot.add("web_page", "https://nav.al/agi");
|
||||
await navalChatBot.add(
|
||||
"pdf_file",
|
||||
"https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf"
|
||||
);
|
||||
|
||||
// Embed Local Resources
|
||||
await navalChatBot.addLocal("qna_pair", [
|
||||
"Who is Naval Ravikant?",
|
||||
"Naval Ravikant is an Indian-American entrepreneur and investor.",
|
||||
]);
|
||||
|
||||
const result = await navalChatBot.query(
|
||||
"What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"
|
||||
);
|
||||
console.log(result);
|
||||
// answer: Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.
|
||||
}
|
||||
|
||||
testApp();
|
||||
```
|
||||
|
||||
# Getting Started
|
||||
|
||||
## Installation
|
||||
|
||||
- First make sure that you have the package installed. If not, then install it using `npm`
|
||||
|
||||
```bash
|
||||
npm install embedchain && npm install -S openai@^3.3.0
|
||||
```
|
||||
|
||||
- Currently, it is only compatible with openai 3.X, not the latest version 4.X. Please make sure to use the right version, otherwise you will see the `ChromaDB` error `TypeError: OpenAIApi.Configuration is not a constructor`
|
||||
|
||||
- Make sure that dotenv package is installed and your `OPENAI_API_KEY` in a file called `.env` in the root folder. You can install dotenv by
|
||||
|
||||
```js
|
||||
npm install dotenv
|
||||
```
|
||||
|
||||
- Download and install Docker on your device by visiting [this link](https://www.docker.com/). You will need this to run Chroma vector database on your machine.
|
||||
|
||||
- Run the following commands to setup Chroma container in Docker
|
||||
|
||||
```bash
|
||||
git clone https://github.com/chroma-core/chroma.git
|
||||
cd chroma
|
||||
docker-compose up -d --build
|
||||
```
|
||||
|
||||
- Once Chroma container has been set up, run it inside Docker
|
||||
|
||||
## Usage
|
||||
|
||||
- We use OpenAI's embedding model to create embeddings for chunks and ChatGPT API as LLM to get answer given the relevant docs. Make sure that you have an OpenAI account and an API key. If you have dont have an API key, you can create one by visiting [this link](https://platform.openai.com/account/api-keys).
|
||||
|
||||
- Once you have the API key, set it in an environment variable called `OPENAI_API_KEY`
|
||||
|
||||
```js
|
||||
// Set this inside your .env file
|
||||
OPENAI_API_KEY = "sk-xxxx";
|
||||
```
|
||||
|
||||
- Load the environment variables inside your .js file using the following commands
|
||||
|
||||
```js
|
||||
const dotenv = require("dotenv");
|
||||
dotenv.config();
|
||||
```
|
||||
|
||||
- Next import the `App` class from embedchain and use `.add` function to add any dataset.
|
||||
- Now your app is created. You can use `.query` function to get the answer for any query.
|
||||
|
||||
```js
|
||||
const dotenv = require("dotenv");
|
||||
dotenv.config();
|
||||
const { App } = require("embedchain");
|
||||
|
||||
async function testApp() {
|
||||
const navalChatBot = await App();
|
||||
|
||||
// Embed Online Resources
|
||||
await navalChatBot.add("web_page", "https://nav.al/feedback");
|
||||
await navalChatBot.add("web_page", "https://nav.al/agi");
|
||||
await navalChatBot.add(
|
||||
"pdf_file",
|
||||
"https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf"
|
||||
);
|
||||
|
||||
// Embed Local Resources
|
||||
await navalChatBot.addLocal("qna_pair", [
|
||||
"Who is Naval Ravikant?",
|
||||
"Naval Ravikant is an Indian-American entrepreneur and investor.",
|
||||
]);
|
||||
|
||||
const result = await navalChatBot.query(
|
||||
"What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?"
|
||||
);
|
||||
console.log(result);
|
||||
// answer: Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.
|
||||
}
|
||||
|
||||
testApp();
|
||||
```
|
||||
|
||||
- If there is any other app instance in your script or app, you can change the import as
|
||||
|
||||
```javascript
|
||||
const { App: EmbedChainApp } = require("embedchain");
|
||||
|
||||
// or
|
||||
|
||||
const { App: ECApp } = require("embedchain");
|
||||
```
|
||||
|
||||
## Format supported
|
||||
|
||||
We support the following formats:
|
||||
|
||||
### PDF File
|
||||
|
||||
To add any pdf file, use the data_type as `pdf_file`. Eg:
|
||||
|
||||
```javascript
|
||||
await app.add("pdf_file", "a_valid_url_where_pdf_file_can_be_accessed");
|
||||
```
|
||||
|
||||
### Web Page
|
||||
|
||||
To add any web page, use the data_type as `web_page`. Eg:
|
||||
|
||||
```javascript
|
||||
await app.add("web_page", "a_valid_web_page_url");
|
||||
```
|
||||
|
||||
### QnA Pair
|
||||
|
||||
To supply your own QnA pair, use the data_type as `qna_pair` and enter a tuple. Eg:
|
||||
|
||||
```javascript
|
||||
await app.addLocal("qna_pair", ["Question", "Answer"]);
|
||||
```
|
||||
|
||||
### More Formats coming soon
|
||||
|
||||
- If you want to add any other format, please create an [issue](https://github.com/embedchain/embedchainjs/issues) and we will add it to the list of supported formats.
|
||||
|
||||
## Testing
|
||||
|
||||
Before you consume valueable tokens, you should make sure that the embedding you have done works and that it's receiving the correct document from the database.
|
||||
|
||||
For this you can use the `dryRun` method.
|
||||
|
||||
Following the example above, add this to your script:
|
||||
|
||||
```js
|
||||
let result = await naval_chat_bot.dryRun("What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?");console.log(result);
|
||||
|
||||
'''
|
||||
Use the following pieces of context to answer the query at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.
|
||||
terms of the unseen. And I think that’s critical. That is what humans do uniquely that no other creature, no other computer, no other intelligence—biological or artificial—that we have ever encountered does. And not only do we do it uniquely, but if we were to meet an alien species that also had the power to generate these good explanations, there is no explanation that they could generate that we could not understand. We are maximally capable of understanding. There is no concept out there that is possible in this physical reality that a human being, given sufficient time and resources and
|
||||
Query: What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?
|
||||
Helpful Answer:
|
||||
'''
|
||||
```
|
||||
|
||||
_The embedding is confirmed to work as expected. It returns the right document, even if the question is asked slightly different. No prompt tokens have been consumed._
|
||||
|
||||
**The dry run will still consume tokens to embed your query, but it is only ~1/15 of the prompt.**
|
||||
|
||||
# How does it work?
|
||||
|
||||
Creating a chat bot over any dataset needs the following steps to happen
|
||||
|
||||
- load the data
|
||||
- create meaningful chunks
|
||||
- create embeddings for each chunk
|
||||
- store the chunks in vector database
|
||||
|
||||
Whenever a user asks any query, following process happens to find the answer for the query
|
||||
|
||||
- create the embedding for query
|
||||
- find similar documents for this query from vector database
|
||||
- pass similar documents as context to LLM to get the final answer.
|
||||
|
||||
The process of loading the dataset and then querying involves multiple steps and each steps has nuances of it is own.
|
||||
|
||||
- How should I chunk the data? What is a meaningful chunk size?
|
||||
- How should I create embeddings for each chunk? Which embedding model should I use?
|
||||
- How should I store the chunks in vector database? Which vector database should I use?
|
||||
- Should I store meta data along with the embeddings?
|
||||
- How should I find similar documents for a query? Which ranking model should I use?
|
||||
|
||||
These questions may be trivial for some but for a lot of us, it needs research, experimentation and time to find out the accurate answers.
|
||||
|
||||
embedchain is a framework which takes care of all these nuances and provides a simple interface to create bots over any dataset.
|
||||
|
||||
In the first release, we are making it easier for anyone to get a chatbot over any dataset up and running in less than a minute. All you need to do is create an app instance, add the data sets using `.add` function and then use `.query` function to get the relevant answer.
|
||||
|
||||
# Tech Stack
|
||||
|
||||
embedchain is built on the following stack:
|
||||
|
||||
- [Langchain](https://github.com/hwchase17/langchain) as an LLM framework to load, chunk and index data
|
||||
- [OpenAI's Ada embedding model](https://platform.openai.com/docs/guides/embeddings) to create embeddings
|
||||
- [OpenAI's ChatGPT API](https://platform.openai.com/docs/guides/gpt/chat-completions-api) as LLM to get answers given the context
|
||||
- [Chroma](https://github.com/chroma-core/chroma) as the vector database to store embeddings
|
||||
|
||||
# Team
|
||||
|
||||
## Author
|
||||
|
||||
- Taranjeet Singh ([@taranjeetio](https://twitter.com/taranjeetio))
|
||||
|
||||
## Maintainer
|
||||
|
||||
- [cachho](https://github.com/cachho)
|
||||
- [sahilyadav902](https://github.com/sahilyadav902)
|
||||
|
||||
## Citation
|
||||
|
||||
If you utilize this repository, please consider citing it with:
|
||||
```
|
||||
@misc{embedchain,
|
||||
author = {Taranjeet Singh},
|
||||
title = {Embechain: Framework to easily create LLM powered bots over any dataset},
|
||||
year = {2023},
|
||||
publisher = {GitHub},
|
||||
journal = {GitHub repository},
|
||||
howpublished = {\url{https://github.com/embedchain/embedchainjs}},
|
||||
}
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
module.exports = { extends: ['@commitlint/config-conventional'] };
|
||||
@@ -1,66 +0,0 @@
|
||||
import { EmbedChainApp } from '../embedchain';
|
||||
|
||||
const mockAdd = jest.fn();
|
||||
const mockAddLocal = jest.fn();
|
||||
const mockQuery = jest.fn();
|
||||
|
||||
jest.mock('../embedchain', () => {
|
||||
return {
|
||||
EmbedChainApp: jest.fn().mockImplementation(() => {
|
||||
return {
|
||||
add: mockAdd,
|
||||
addLocal: mockAddLocal,
|
||||
query: mockQuery,
|
||||
};
|
||||
}),
|
||||
};
|
||||
});
|
||||
|
||||
describe('Test App', () => {
|
||||
beforeEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('tests the App', async () => {
|
||||
mockQuery.mockResolvedValue(
|
||||
'Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.'
|
||||
);
|
||||
|
||||
const navalChatBot = await new EmbedChainApp(undefined, false);
|
||||
|
||||
// Embed Online Resources
|
||||
await navalChatBot.add('web_page', 'https://nav.al/feedback');
|
||||
await navalChatBot.add('web_page', 'https://nav.al/agi');
|
||||
await navalChatBot.add(
|
||||
'pdf_file',
|
||||
'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf'
|
||||
);
|
||||
|
||||
// Embed Local Resources
|
||||
await navalChatBot.addLocal('qna_pair', [
|
||||
'Who is Naval Ravikant?',
|
||||
'Naval Ravikant is an Indian-American entrepreneur and investor.',
|
||||
]);
|
||||
|
||||
const result = await navalChatBot.query(
|
||||
'What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?'
|
||||
);
|
||||
|
||||
expect(mockAdd).toHaveBeenCalledWith('web_page', 'https://nav.al/feedback');
|
||||
expect(mockAdd).toHaveBeenCalledWith('web_page', 'https://nav.al/agi');
|
||||
expect(mockAdd).toHaveBeenCalledWith(
|
||||
'pdf_file',
|
||||
'https://navalmanack.s3.amazonaws.com/Eric-Jorgenson_The-Almanack-of-Naval-Ravikant_Final.pdf'
|
||||
);
|
||||
expect(mockAddLocal).toHaveBeenCalledWith('qna_pair', [
|
||||
'Who is Naval Ravikant?',
|
||||
'Naval Ravikant is an Indian-American entrepreneur and investor.',
|
||||
]);
|
||||
expect(mockQuery).toHaveBeenCalledWith(
|
||||
'What unique capacity does Naval argue humans possess when it comes to understanding explanations or concepts?'
|
||||
);
|
||||
expect(result).toBe(
|
||||
'Naval argues that humans possess the unique capacity to understand explanations or concepts to the maximum extent possible in this physical reality.'
|
||||
);
|
||||
});
|
||||
});
|
||||
@@ -1,44 +0,0 @@
|
||||
import { createHash } from 'crypto';
|
||||
import type { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
|
||||
|
||||
import type { BaseLoader } from '../loaders';
|
||||
import type { Input, LoaderResult } from '../models';
|
||||
import type { ChunkResult } from '../models/ChunkResult';
|
||||
|
||||
class BaseChunker {
|
||||
textSplitter: RecursiveCharacterTextSplitter;
|
||||
|
||||
constructor(textSplitter: RecursiveCharacterTextSplitter) {
|
||||
this.textSplitter = textSplitter;
|
||||
}
|
||||
|
||||
async createChunks(loader: BaseLoader, url: Input): Promise<ChunkResult> {
|
||||
const documents: ChunkResult['documents'] = [];
|
||||
const ids: ChunkResult['ids'] = [];
|
||||
const datas: LoaderResult = await loader.loadData(url);
|
||||
const metadatas: ChunkResult['metadatas'] = [];
|
||||
|
||||
const dataPromises = datas.map(async (data) => {
|
||||
const { content, metaData } = data;
|
||||
const chunks: string[] = await this.textSplitter.splitText(content);
|
||||
chunks.forEach((chunk) => {
|
||||
const chunkId = createHash('sha256')
|
||||
.update(chunk + metaData.url)
|
||||
.digest('hex');
|
||||
ids.push(chunkId);
|
||||
documents.push(chunk);
|
||||
metadatas.push(metaData);
|
||||
});
|
||||
});
|
||||
|
||||
await Promise.all(dataPromises);
|
||||
|
||||
return {
|
||||
documents,
|
||||
ids,
|
||||
metadatas,
|
||||
};
|
||||
}
|
||||
}
|
||||
|
||||
export { BaseChunker };
|
||||
@@ -1,26 +0,0 @@
|
||||
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
|
||||
|
||||
import { BaseChunker } from './BaseChunker';
|
||||
|
||||
interface TextSplitterChunkParams {
|
||||
chunkSize: number;
|
||||
chunkOverlap: number;
|
||||
keepSeparator: boolean;
|
||||
}
|
||||
|
||||
const TEXT_SPLITTER_CHUNK_PARAMS: TextSplitterChunkParams = {
|
||||
chunkSize: 1000,
|
||||
chunkOverlap: 0,
|
||||
keepSeparator: false,
|
||||
};
|
||||
|
||||
class PdfFileChunker extends BaseChunker {
|
||||
constructor() {
|
||||
const textSplitter = new RecursiveCharacterTextSplitter(
|
||||
TEXT_SPLITTER_CHUNK_PARAMS
|
||||
);
|
||||
super(textSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
export { PdfFileChunker };
|
||||
@@ -1,26 +0,0 @@
|
||||
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
|
||||
|
||||
import { BaseChunker } from './BaseChunker';
|
||||
|
||||
interface TextSplitterChunkParams {
|
||||
chunkSize: number;
|
||||
chunkOverlap: number;
|
||||
keepSeparator: boolean;
|
||||
}
|
||||
|
||||
const TEXT_SPLITTER_CHUNK_PARAMS: TextSplitterChunkParams = {
|
||||
chunkSize: 300,
|
||||
chunkOverlap: 0,
|
||||
keepSeparator: false,
|
||||
};
|
||||
|
||||
class QnaPairChunker extends BaseChunker {
|
||||
constructor() {
|
||||
const textSplitter = new RecursiveCharacterTextSplitter(
|
||||
TEXT_SPLITTER_CHUNK_PARAMS
|
||||
);
|
||||
super(textSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
export { QnaPairChunker };
|
||||
@@ -1,26 +0,0 @@
|
||||
import { RecursiveCharacterTextSplitter } from 'langchain/text_splitter';
|
||||
|
||||
import { BaseChunker } from './BaseChunker';
|
||||
|
||||
interface TextSplitterChunkParams {
|
||||
chunkSize: number;
|
||||
chunkOverlap: number;
|
||||
keepSeparator: boolean;
|
||||
}
|
||||
|
||||
const TEXT_SPLITTER_CHUNK_PARAMS: TextSplitterChunkParams = {
|
||||
chunkSize: 500,
|
||||
chunkOverlap: 0,
|
||||
keepSeparator: false,
|
||||
};
|
||||
|
||||
class WebPageChunker extends BaseChunker {
|
||||
constructor() {
|
||||
const textSplitter = new RecursiveCharacterTextSplitter(
|
||||
TEXT_SPLITTER_CHUNK_PARAMS
|
||||
);
|
||||
super(textSplitter);
|
||||
}
|
||||
}
|
||||
|
||||
export { WebPageChunker };
|
||||
@@ -1,6 +0,0 @@
|
||||
import { BaseChunker } from './BaseChunker';
|
||||
import { PdfFileChunker } from './PdfFile';
|
||||
import { QnaPairChunker } from './QnaPair';
|
||||
import { WebPageChunker } from './WebPage';
|
||||
|
||||
export { BaseChunker, PdfFileChunker, QnaPairChunker, WebPageChunker };
|
||||
@@ -1,317 +0,0 @@
|
||||
/* eslint-disable max-classes-per-file */
|
||||
import type { Collection } from 'chromadb';
|
||||
import type { QueryResponse } from 'chromadb/dist/main/types';
|
||||
import * as fs from 'fs';
|
||||
import { Document } from 'langchain/document';
|
||||
import OpenAI from 'openai';
|
||||
import * as path from 'path';
|
||||
import { v4 as uuidv4 } from 'uuid';
|
||||
|
||||
import type { BaseChunker } from './chunkers';
|
||||
import { PdfFileChunker, QnaPairChunker, WebPageChunker } from './chunkers';
|
||||
import type { BaseLoader } from './loaders';
|
||||
import { LocalQnaPairLoader, PdfFileLoader, WebPageLoader } from './loaders';
|
||||
import type {
|
||||
DataDict,
|
||||
DataType,
|
||||
FormattedResult,
|
||||
Input,
|
||||
LocalInput,
|
||||
Metadata,
|
||||
Method,
|
||||
RemoteInput,
|
||||
} from './models';
|
||||
import { ChromaDB } from './vectordb';
|
||||
import type { BaseVectorDB } from './vectordb/BaseVectorDb';
|
||||
|
||||
const openai = new OpenAI({
|
||||
apiKey: process.env.OPENAI_API_KEY,
|
||||
});
|
||||
|
||||
class EmbedChain {
|
||||
dbClient: any;
|
||||
|
||||
// TODO: Definitely assign
|
||||
collection!: Collection;
|
||||
|
||||
userAsks: [DataType, Input][] = [];
|
||||
|
||||
initApp: Promise<void>;
|
||||
|
||||
collectMetrics: boolean;
|
||||
|
||||
sId: string; // sessionId
|
||||
|
||||
constructor(db?: BaseVectorDB, collectMetrics: boolean = true) {
|
||||
if (!db) {
|
||||
this.initApp = this.setupChroma();
|
||||
} else {
|
||||
this.initApp = this.setupOther(db);
|
||||
}
|
||||
|
||||
this.collectMetrics = collectMetrics;
|
||||
|
||||
// Send anonymous telemetry
|
||||
this.sId = uuidv4();
|
||||
this.sendTelemetryEvent('init');
|
||||
}
|
||||
|
||||
async setupChroma(): Promise<void> {
|
||||
const db = new ChromaDB();
|
||||
await db.initDb;
|
||||
this.dbClient = db.client;
|
||||
if (db.collection) {
|
||||
this.collection = db.collection;
|
||||
} else {
|
||||
// TODO: Add proper error handling
|
||||
console.error('No collection');
|
||||
}
|
||||
}
|
||||
|
||||
async setupOther(db: BaseVectorDB): Promise<void> {
|
||||
await db.initDb;
|
||||
// TODO: Figure out how we can initialize an unknown database.
|
||||
// this.dbClient = db.client;
|
||||
// this.collection = db.collection;
|
||||
this.userAsks = [];
|
||||
}
|
||||
|
||||
static getLoader(dataType: DataType) {
|
||||
const loaders: { [t in DataType]: BaseLoader } = {
|
||||
pdf_file: new PdfFileLoader(),
|
||||
web_page: new WebPageLoader(),
|
||||
qna_pair: new LocalQnaPairLoader(),
|
||||
};
|
||||
return loaders[dataType];
|
||||
}
|
||||
|
||||
static getChunker(dataType: DataType) {
|
||||
const chunkers: { [t in DataType]: BaseChunker } = {
|
||||
pdf_file: new PdfFileChunker(),
|
||||
web_page: new WebPageChunker(),
|
||||
qna_pair: new QnaPairChunker(),
|
||||
};
|
||||
return chunkers[dataType];
|
||||
}
|
||||
|
||||
public async add(dataType: DataType, url: RemoteInput) {
|
||||
const loader = EmbedChain.getLoader(dataType);
|
||||
const chunker = EmbedChain.getChunker(dataType);
|
||||
this.userAsks.push([dataType, url]);
|
||||
const { documents, countNewChunks } = await this.loadAndEmbed(
|
||||
loader,
|
||||
chunker,
|
||||
url
|
||||
);
|
||||
|
||||
if (this.collectMetrics) {
|
||||
const wordCount = documents.reduce(
|
||||
(sum, document) => sum + document.split(' ').length,
|
||||
0
|
||||
);
|
||||
|
||||
this.sendTelemetryEvent('add', {
|
||||
data_type: dataType,
|
||||
word_count: wordCount,
|
||||
chunks_count: countNewChunks,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public async addLocal(dataType: DataType, content: LocalInput) {
|
||||
const loader = EmbedChain.getLoader(dataType);
|
||||
const chunker = EmbedChain.getChunker(dataType);
|
||||
this.userAsks.push([dataType, content]);
|
||||
const { documents, countNewChunks } = await this.loadAndEmbed(
|
||||
loader,
|
||||
chunker,
|
||||
content
|
||||
);
|
||||
|
||||
if (this.collectMetrics) {
|
||||
const wordCount = documents.reduce(
|
||||
(sum, document) => sum + document.split(' ').length,
|
||||
0
|
||||
);
|
||||
|
||||
this.sendTelemetryEvent('add_local', {
|
||||
data_type: dataType,
|
||||
word_count: wordCount,
|
||||
chunks_count: countNewChunks,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
protected async loadAndEmbed(
|
||||
loader: any,
|
||||
chunker: BaseChunker,
|
||||
src: Input
|
||||
): Promise<{
|
||||
documents: string[];
|
||||
metadatas: Metadata[];
|
||||
ids: string[];
|
||||
countNewChunks: number;
|
||||
}> {
|
||||
const embeddingsData = await chunker.createChunks(loader, src);
|
||||
let { documents, ids, metadatas } = embeddingsData;
|
||||
|
||||
const existingDocs = await this.collection.get({ ids });
|
||||
const existingIds = new Set(existingDocs.ids);
|
||||
|
||||
if (existingIds.size > 0) {
|
||||
const dataDict: DataDict = {};
|
||||
for (let i = 0; i < ids.length; i += 1) {
|
||||
const id = ids[i];
|
||||
if (!existingIds.has(id)) {
|
||||
dataDict[id] = { doc: documents[i], meta: metadatas[i] };
|
||||
}
|
||||
}
|
||||
|
||||
if (Object.keys(dataDict).length === 0) {
|
||||
console.log(`All data from ${src} already exists in the database.`);
|
||||
return { documents: [], metadatas: [], ids: [], countNewChunks: 0 };
|
||||
}
|
||||
ids = Object.keys(dataDict);
|
||||
const dataValues = Object.values(dataDict);
|
||||
documents = dataValues.map(({ doc }) => doc);
|
||||
metadatas = dataValues.map(({ meta }) => meta);
|
||||
}
|
||||
|
||||
const countBeforeAddition = await this.count();
|
||||
await this.collection.add({ documents, metadatas, ids });
|
||||
const countNewChunks = (await this.count()) - countBeforeAddition;
|
||||
console.log(
|
||||
`Successfully saved ${src}. New chunks count: ${countNewChunks}`
|
||||
);
|
||||
return { documents, metadatas, ids, countNewChunks };
|
||||
}
|
||||
|
||||
static async formatResult(
|
||||
results: QueryResponse
|
||||
): Promise<FormattedResult[]> {
|
||||
return results.documents[0].map((document: any, index: number) => {
|
||||
const metadata = results.metadatas[0][index] || {};
|
||||
// TODO: Add proper error handling
|
||||
const distance = results.distances ? results.distances[0][index] : null;
|
||||
return [new Document({ pageContent: document, metadata }), distance];
|
||||
});
|
||||
}
|
||||
|
||||
static async getOpenAiAnswer(prompt: string) {
|
||||
const messages: OpenAI.Chat.CreateChatCompletionRequestMessage[] = [
|
||||
{ role: 'user', content: prompt },
|
||||
];
|
||||
const response = await openai.chat.completions.create({
|
||||
model: 'gpt-3.5-turbo',
|
||||
messages,
|
||||
temperature: 0,
|
||||
max_tokens: 1000,
|
||||
top_p: 1,
|
||||
});
|
||||
return (
|
||||
response.choices[0].message?.content ?? 'Response could not be processed.'
|
||||
);
|
||||
}
|
||||
|
||||
protected async retrieveFromDatabase(inputQuery: string) {
|
||||
const result = await this.collection.query({
|
||||
nResults: 1,
|
||||
queryTexts: [inputQuery],
|
||||
});
|
||||
const resultFormatted = await EmbedChain.formatResult(result);
|
||||
const content = resultFormatted[0][0].pageContent;
|
||||
return content;
|
||||
}
|
||||
|
||||
static generatePrompt(inputQuery: string, context: any) {
|
||||
const prompt = `Use the following pieces of context to answer the query at the end. If you don't know the answer, just say that you don't know, don't try to make up an answer.\n${context}\nQuery: ${inputQuery}\nHelpful Answer:`;
|
||||
return prompt;
|
||||
}
|
||||
|
||||
static async getAnswerFromLlm(prompt: string) {
|
||||
const answer = await EmbedChain.getOpenAiAnswer(prompt);
|
||||
return answer;
|
||||
}
|
||||
|
||||
public async query(inputQuery: string) {
|
||||
const context = await this.retrieveFromDatabase(inputQuery);
|
||||
const prompt = EmbedChain.generatePrompt(inputQuery, context);
|
||||
const answer = await EmbedChain.getAnswerFromLlm(prompt);
|
||||
this.sendTelemetryEvent('query');
|
||||
return answer;
|
||||
}
|
||||
|
||||
public async dryRun(input_query: string) {
|
||||
const context = await this.retrieveFromDatabase(input_query);
|
||||
const prompt = EmbedChain.generatePrompt(input_query, context);
|
||||
return prompt;
|
||||
}
|
||||
|
||||
/**
|
||||
* Count the number of embeddings.
|
||||
* @returns {Promise<number>}: The number of embeddings.
|
||||
*/
|
||||
public count(): Promise<number> {
|
||||
return this.collection.count();
|
||||
}
|
||||
|
||||
protected async sendTelemetryEvent(method: Method, extraMetadata?: object) {
|
||||
if (!this.collectMetrics) {
|
||||
return;
|
||||
}
|
||||
const url = 'https://api.embedchain.ai/api/v1/telemetry/';
|
||||
|
||||
// Read package version from filesystem (because it's not in the ts root dir)
|
||||
const packageJsonPath = path.join(__dirname, '..', 'package.json');
|
||||
const packageJson = JSON.parse(fs.readFileSync(packageJsonPath, 'utf8'));
|
||||
|
||||
const metadata = {
|
||||
s_id: this.sId,
|
||||
version: packageJson.version,
|
||||
method,
|
||||
language: 'js',
|
||||
...extraMetadata,
|
||||
};
|
||||
|
||||
const maxRetries = 3;
|
||||
|
||||
// Retry the fetch
|
||||
for (let i = 0; i < maxRetries; i += 1) {
|
||||
try {
|
||||
// eslint-disable-next-line no-await-in-loop
|
||||
const response = await fetch(url, {
|
||||
method: 'POST',
|
||||
body: JSON.stringify({ metadata }),
|
||||
});
|
||||
|
||||
if (response.ok) {
|
||||
// Break out of the loop if the request was successful
|
||||
break;
|
||||
} else {
|
||||
// Log the unsuccessful response (optional)
|
||||
console.error(
|
||||
`Telemetry: Attempt ${i + 1} failed with status:`,
|
||||
response.status
|
||||
);
|
||||
}
|
||||
} catch (error) {
|
||||
// Log the error (optional)
|
||||
console.error(`Telemetry: Attempt ${i + 1} failed with error:`, error);
|
||||
}
|
||||
|
||||
// If this was the last attempt, throw an error or handle the failure
|
||||
if (i === maxRetries - 1) {
|
||||
console.error('Telemetry: Max retries reached');
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
class EmbedChainApp extends EmbedChain {
|
||||
// The EmbedChain app.
|
||||
// Has two functions: add and query.
|
||||
// adds(dataType, url): adds the data from the given URL to the vector db.
|
||||
// query(query): finds answer to the given query using vector database and LLM.
|
||||
}
|
||||
|
||||
export { EmbedChainApp };
|
||||
@@ -1,7 +0,0 @@
|
||||
import { EmbedChainApp } from './embedchain';
|
||||
|
||||
export const App = async () => {
|
||||
const app = new EmbedChainApp();
|
||||
await app.initApp;
|
||||
return app;
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
import type { Input, LoaderResult } from '../models';
|
||||
|
||||
export abstract class BaseLoader {
|
||||
abstract loadData(src: Input): Promise<LoaderResult>;
|
||||
}
|
||||
@@ -1,21 +0,0 @@
|
||||
import type { LoaderResult, QnaPair } from '../models';
|
||||
import { BaseLoader } from './BaseLoader';
|
||||
|
||||
class LocalQnaPairLoader extends BaseLoader {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async loadData(content: QnaPair): Promise<LoaderResult> {
|
||||
const [question, answer] = content;
|
||||
const contentText = `Q: ${question}\nA: ${answer}`;
|
||||
const metaData = {
|
||||
url: 'local',
|
||||
};
|
||||
return [
|
||||
{
|
||||
content: contentText,
|
||||
metaData,
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
export { LocalQnaPairLoader };
|
||||
@@ -1,58 +0,0 @@
|
||||
import type { TextContent } from 'pdfjs-dist/types/src/display/api';
|
||||
|
||||
import type { LoaderResult, Metadata } from '../models';
|
||||
import { cleanString } from '../utils';
|
||||
import { BaseLoader } from './BaseLoader';
|
||||
|
||||
const pdfjsLib = require('pdfjs-dist');
|
||||
|
||||
interface Page {
|
||||
page_content: string;
|
||||
}
|
||||
|
||||
class PdfFileLoader extends BaseLoader {
|
||||
static async getPagesFromPdf(url: string): Promise<Page[]> {
|
||||
const loadingTask = pdfjsLib.getDocument(url);
|
||||
const pdf = await loadingTask.promise;
|
||||
const { numPages } = pdf;
|
||||
|
||||
const promises = Array.from({ length: numPages }, async (_, i) => {
|
||||
const page = await pdf.getPage(i + 1);
|
||||
const pageText: TextContent = await page.getTextContent();
|
||||
const pageContent: string = pageText.items
|
||||
.map((item) => ('str' in item ? item.str : ''))
|
||||
.join(' ');
|
||||
|
||||
return {
|
||||
page_content: pageContent,
|
||||
};
|
||||
});
|
||||
|
||||
return Promise.all(promises);
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async loadData(url: string): Promise<LoaderResult> {
|
||||
const pages: Page[] = await PdfFileLoader.getPagesFromPdf(url);
|
||||
const output: LoaderResult = [];
|
||||
|
||||
if (!pages.length) {
|
||||
throw new Error('No data found');
|
||||
}
|
||||
|
||||
pages.forEach((page) => {
|
||||
let content: string = page.page_content;
|
||||
content = cleanString(content);
|
||||
const metaData: Metadata = {
|
||||
url,
|
||||
};
|
||||
output.push({
|
||||
content,
|
||||
metaData,
|
||||
});
|
||||
});
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
export { PdfFileLoader };
|
||||
@@ -1,51 +0,0 @@
|
||||
import axios from 'axios';
|
||||
import { JSDOM } from 'jsdom';
|
||||
|
||||
import { cleanString } from '../utils';
|
||||
import { BaseLoader } from './BaseLoader';
|
||||
|
||||
class WebPageLoader extends BaseLoader {
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
async loadData(url: string) {
|
||||
const response = await axios.get(url);
|
||||
const html = response.data;
|
||||
const dom = new JSDOM(html);
|
||||
const { document } = dom.window;
|
||||
const unwantedTags = [
|
||||
'nav',
|
||||
'aside',
|
||||
'form',
|
||||
'header',
|
||||
'noscript',
|
||||
'svg',
|
||||
'canvas',
|
||||
'footer',
|
||||
'script',
|
||||
'style',
|
||||
];
|
||||
unwantedTags.forEach((tagName) => {
|
||||
const elements = document.getElementsByTagName(tagName);
|
||||
Array.from(elements).forEach((element) => {
|
||||
// eslint-disable-next-line no-param-reassign
|
||||
(element as HTMLElement).textContent = ' ';
|
||||
});
|
||||
});
|
||||
|
||||
const output = [];
|
||||
let content = document.body.textContent;
|
||||
if (!content) {
|
||||
throw new Error('Web page content is empty.');
|
||||
}
|
||||
content = cleanString(content);
|
||||
const metaData = {
|
||||
url,
|
||||
};
|
||||
output.push({
|
||||
content,
|
||||
metaData,
|
||||
});
|
||||
return output;
|
||||
}
|
||||
}
|
||||
|
||||
export { WebPageLoader };
|
||||
@@ -1,6 +0,0 @@
|
||||
import { BaseLoader } from './BaseLoader';
|
||||
import { LocalQnaPairLoader } from './LocalQnaPair';
|
||||
import { PdfFileLoader } from './PdfFile';
|
||||
import { WebPageLoader } from './WebPage';
|
||||
|
||||
export { BaseLoader, LocalQnaPairLoader, PdfFileLoader, WebPageLoader };
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { Metadata } from './Metadata';
|
||||
|
||||
export type ChunkResult = {
|
||||
documents: string[];
|
||||
ids: string[];
|
||||
metadatas: Metadata[];
|
||||
};
|
||||
@@ -1,10 +0,0 @@
|
||||
import type { ChunkResult } from './ChunkResult';
|
||||
|
||||
type Data = {
|
||||
doc: ChunkResult['documents'][0];
|
||||
meta: ChunkResult['metadatas'][0];
|
||||
};
|
||||
|
||||
export type DataDict = {
|
||||
[id: string]: Data;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export type DataType = 'pdf_file' | 'web_page' | 'qna_pair';
|
||||
@@ -1,3 +0,0 @@
|
||||
import type { Document } from 'langchain/document';
|
||||
|
||||
export type FormattedResult = [Document, number | null];
|
||||
@@ -1,7 +0,0 @@
|
||||
import type { QnaPair } from './QnAPair';
|
||||
|
||||
export type RemoteInput = string;
|
||||
|
||||
export type LocalInput = QnaPair;
|
||||
|
||||
export type Input = RemoteInput | LocalInput;
|
||||
@@ -1,3 +0,0 @@
|
||||
import type { Metadata } from './Metadata';
|
||||
|
||||
export type LoaderResult = { content: any; metaData: Metadata }[];
|
||||
@@ -1,3 +0,0 @@
|
||||
export type Metadata = {
|
||||
url: string;
|
||||
};
|
||||
@@ -1 +0,0 @@
|
||||
export type Method = 'init' | 'query' | 'add' | 'add_local';
|
||||
@@ -1,4 +0,0 @@
|
||||
type Question = string;
|
||||
type Answer = string;
|
||||
|
||||
export type QnaPair = [Question, Answer];
|
||||
@@ -1,21 +0,0 @@
|
||||
import { DataDict } from './DataDict';
|
||||
import { DataType } from './DataType';
|
||||
import { FormattedResult } from './FormattedResult';
|
||||
import { Input, LocalInput, RemoteInput } from './Input';
|
||||
import { LoaderResult } from './LoaderResult';
|
||||
import { Metadata } from './Metadata';
|
||||
import { Method } from './Method';
|
||||
import { QnaPair } from './QnAPair';
|
||||
|
||||
export {
|
||||
DataDict,
|
||||
DataType,
|
||||
FormattedResult,
|
||||
Input,
|
||||
LoaderResult,
|
||||
LocalInput,
|
||||
Metadata,
|
||||
Method,
|
||||
QnaPair,
|
||||
RemoteInput,
|
||||
};
|
||||
@@ -1,26 +0,0 @@
|
||||
/**
|
||||
* This function takes in a string and performs a series of text cleaning operations.
|
||||
* @param {str} text: The text to be cleaned. This is expected to be a string.
|
||||
* @returns {str}: The cleaned text after all the cleaning operations have been performed.
|
||||
*/
|
||||
export function cleanString(text: string): string {
|
||||
// Replacement of newline characters:
|
||||
let cleanedText = text.replace(/\n/g, ' ');
|
||||
|
||||
// Stripping and reducing multiple spaces to single:
|
||||
cleanedText = cleanedText.trim().replace(/\s+/g, ' ');
|
||||
|
||||
// Removing backslashes:
|
||||
cleanedText = cleanedText.replace(/\\/g, '');
|
||||
|
||||
// Replacing hash characters:
|
||||
cleanedText = cleanedText.replace(/#/g, ' ');
|
||||
|
||||
// Eliminating consecutive non-alphanumeric characters:
|
||||
// This regex identifies consecutive non-alphanumeric characters (i.e., not a word character [a-zA-Z0-9_] and not a whitespace) in the string
|
||||
// and replaces each group of such characters with a single occurrence of that character.
|
||||
// For example, "!!! hello !!!" would become "! hello !".
|
||||
cleanedText = cleanedText.replace(/([^\w\s])\1*/g, '$1');
|
||||
|
||||
return cleanedText;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
class BaseVectorDB {
|
||||
initDb: Promise<void>;
|
||||
|
||||
constructor() {
|
||||
this.initDb = this.getClientAndCollection();
|
||||
}
|
||||
|
||||
// eslint-disable-next-line class-methods-use-this
|
||||
protected async getClientAndCollection(): Promise<void> {
|
||||
throw new Error('getClientAndCollection() method is not implemented');
|
||||
}
|
||||
}
|
||||
|
||||
export { BaseVectorDB };
|
||||
@@ -1,38 +0,0 @@
|
||||
import type { Collection } from 'chromadb';
|
||||
import { ChromaClient, OpenAIEmbeddingFunction } from 'chromadb';
|
||||
|
||||
import { BaseVectorDB } from './BaseVectorDb';
|
||||
|
||||
const embedder = new OpenAIEmbeddingFunction({
|
||||
openai_api_key: process.env.OPENAI_API_KEY ?? '',
|
||||
});
|
||||
|
||||
class ChromaDB extends BaseVectorDB {
|
||||
client: ChromaClient | undefined;
|
||||
|
||||
collection: Collection | null = null;
|
||||
|
||||
// eslint-disable-next-line @typescript-eslint/no-useless-constructor
|
||||
constructor() {
|
||||
super();
|
||||
}
|
||||
|
||||
protected async getClientAndCollection(): Promise<void> {
|
||||
this.client = new ChromaClient({ path: 'http://localhost:8000' });
|
||||
try {
|
||||
this.collection = await this.client.getCollection({
|
||||
name: 'embedchain_store',
|
||||
embeddingFunction: embedder,
|
||||
});
|
||||
} catch (err) {
|
||||
if (!this.collection) {
|
||||
this.collection = await this.client.createCollection({
|
||||
name: 'embedchain_store',
|
||||
embeddingFunction: embedder,
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export { ChromaDB };
|
||||
@@ -1,3 +0,0 @@
|
||||
import { ChromaDB } from './ChromaDb';
|
||||
|
||||
export { ChromaDB };
|
||||
@@ -1,9 +0,0 @@
|
||||
const { EmbedChainApp } = require("./embedchain/embedchain");
|
||||
|
||||
async function App() {
|
||||
const app = new EmbedChainApp();
|
||||
await app.init_app;
|
||||
return app;
|
||||
}
|
||||
|
||||
module.exports = { App };
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
preset: 'ts-jest',
|
||||
testEnvironment: 'node',
|
||||
testPathIgnorePatterns: ['.d.ts'],
|
||||
};
|
||||
@@ -1,5 +0,0 @@
|
||||
module.exports = {
|
||||
'*.{js,ts}': ['eslint --fix', 'eslint'],
|
||||
'**/*.ts?(x)': () => 'npm run check-types',
|
||||
'*.json': ['prettier --write'],
|
||||
};
|
||||
@@ -1,53 +0,0 @@
|
||||
{
|
||||
"name": "embedchain",
|
||||
"version": "0.0.8",
|
||||
"description": "embedchain is a framework to easily create LLM powered bots over any dataset",
|
||||
"main": "dist/index.js",
|
||||
"types": "types/index.d.ts",
|
||||
"files": [
|
||||
"dist",
|
||||
"types"
|
||||
],
|
||||
"scripts": {
|
||||
"build": "tsc -p tsconfig.build.json --listFiles",
|
||||
"prepare": "husky install",
|
||||
"test": "jest",
|
||||
"check-types": "tsc --noEmit --pretty"
|
||||
},
|
||||
"author": "Taranjeet Singh",
|
||||
"license": "Apache-2.0",
|
||||
"dependencies": {
|
||||
"axios": "^1.4.0",
|
||||
"chromadb": "^1.5.6",
|
||||
"jsdom": "^22.1.0",
|
||||
"langchain": "^0.0.136",
|
||||
"openai": "^4.3.1",
|
||||
"pdfjs-dist": "^3.8.162",
|
||||
"uuid": "^9.0.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@commitlint/cli": "^17.1.2",
|
||||
"@commitlint/config-conventional": "^17.1.0",
|
||||
"@commitlint/cz-commitlint": "^17.1.2",
|
||||
"@types/jest": "^29.5.1",
|
||||
"@types/jsdom": "^21.1.1",
|
||||
"@typescript-eslint/eslint-plugin": "^5.41.0",
|
||||
"@typescript-eslint/parser": "^5.41.0",
|
||||
"eslint": "^8.34.0",
|
||||
"eslint-config-airbnb-base": "^15.0.0",
|
||||
"eslint-config-airbnb-typescript": "^17.0.0",
|
||||
"eslint-config-prettier": "^8.5.0",
|
||||
"eslint-plugin-import": "^2.27.5",
|
||||
"eslint-plugin-prettier": "^4.2.1",
|
||||
"eslint-plugin-simple-import-sort": "^8.0.0",
|
||||
"eslint-plugin-testing-library": "^5.9.1",
|
||||
"eslint-plugin-unused-imports": "^2.0.0",
|
||||
"husky": "^8.0.1",
|
||||
"jest": "^29.5.0",
|
||||
"lint-staged": "^13.0.3",
|
||||
"prettier": "^2.7.1",
|
||||
"ts-jest": "^29.1.0",
|
||||
"ts-loader": "^9.4.2",
|
||||
"typescript": "^5.2.2"
|
||||
}
|
||||
}
|
||||
@@ -1,4 +0,0 @@
|
||||
{
|
||||
"extends": "./tsconfig.json",
|
||||
"exclude": ["embedchain/__tests__"]
|
||||
}
|
||||
@@ -1,15 +0,0 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"target": "es6",
|
||||
"module": "CommonJS",
|
||||
"strict": true,
|
||||
"outDir": "dist",
|
||||
"rootDir": "embedchain",
|
||||
"sourceMap": true,
|
||||
"declaration": true,
|
||||
"declarationDir": "types",
|
||||
"esModuleInterop": true
|
||||
},
|
||||
"include": ["embedchain/**/*.ts"],
|
||||
"exclude": ["node_modules", "dist"]
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
# Contributing to embedchain
|
||||
|
||||
Let us make contributing easy, collaborative and fun.
|
||||
Let us make contribution easy, collaborative and fun.
|
||||
|
||||
## Submit your Contribution through PR
|
||||
|
||||
To make a contribution, follow the following steps:
|
||||
To make a contribution, follow these steps:
|
||||
|
||||
1. Fork and clone this repository
|
||||
2. Do the changes on your fork with dedicated feature branch `feature/f1`
|
||||
@@ -24,9 +24,7 @@ We use `poetry` as our package manager. You can install poetry by following the
|
||||
Please DO NOT use pip or conda to install the dependencies. Instead, use poetry:
|
||||
|
||||
```bash
|
||||
poetry install --all-extras
|
||||
or
|
||||
poetry install --with dev
|
||||
make install_all
|
||||
|
||||
#activate
|
||||
|
||||
@@ -35,7 +33,7 @@ poetry shell
|
||||
|
||||
### 📌 Pre-commit
|
||||
|
||||
To ensure our standards, make sure to install pre-commit before star to contribute.
|
||||
To ensure our standards, make sure to install pre-commit before starting to contribute.
|
||||
|
||||
```bash
|
||||
pre-commit install
|
||||
@@ -51,7 +49,7 @@ make lint
|
||||
|
||||
Make sure that the linter does not report any errors or warnings before submitting a pull request.
|
||||
|
||||
### Code Format with `black`
|
||||
### Code Formatting with `black`
|
||||
|
||||
We use `black` to reformat the code by running the following command:
|
||||
|
||||
@@ -67,6 +65,10 @@ We use `pytest` to test our code. You can run the tests by running the following
|
||||
poetry run pytest
|
||||
```
|
||||
|
||||
|
||||
Several packages have been removed from Poetry to make the package lighter. Therefore, it is recommended to run `make install_all` to install the remaining packages and ensure all tests pass.
|
||||
|
||||
|
||||
Make sure that all tests pass before submitting a pull request.
|
||||
|
||||
## 🚀 Release Process
|
||||
@@ -186,7 +186,7 @@
|
||||
same "printed page" as the copyright notice for easier
|
||||
identification within third-party archives.
|
||||
|
||||
Copyright [yyyy] [name of copyright owner]
|
||||
Copyright [2023] [Taranjeet Singh]
|
||||
|
||||
Licensed under the Apache License, Version 2.0 (the "License");
|
||||
you may not use this file except in compliance with the License.
|
||||
@@ -0,0 +1,56 @@
|
||||
# Variables
|
||||
PYTHON := python3
|
||||
PIP := $(PYTHON) -m pip
|
||||
PROJECT_NAME := embedchain
|
||||
|
||||
# Targets
|
||||
.PHONY: install format lint clean test ci_lint ci_test coverage
|
||||
|
||||
install:
|
||||
poetry install
|
||||
|
||||
# TODO: use a more efficient way to install these packages
|
||||
install_all:
|
||||
poetry install --all-extras
|
||||
poetry run pip install pinecone-text pinecone-client langchain-anthropic "unstructured[local-inference, all-docs]" ollama langchain_together==0.1.3 \
|
||||
langchain_cohere==0.1.5 deepgram-sdk==3.2.7 langchain-huggingface psutil clarifai==10.0.1 flask==2.3.3 twilio==8.5.0 fastapi-poe==0.0.16 discord==2.3.2 \
|
||||
slack-sdk==3.21.3 huggingface_hub==0.23.0 gitpython==3.1.38 yt_dlp==2023.11.14 PyGithub==1.59.1 feedparser==6.0.10 newspaper3k==0.2.8 listparser==0.19 \
|
||||
modal==0.56.4329 dropbox==11.36.2 boto3==1.34.20 youtube-transcript-api==0.6.1 pytube==15.0.0 beautifulsoup4==4.12.3
|
||||
|
||||
install_es:
|
||||
poetry install --extras elasticsearch
|
||||
|
||||
install_opensearch:
|
||||
poetry install --extras opensearch
|
||||
|
||||
install_milvus:
|
||||
poetry install --extras milvus
|
||||
|
||||
shell:
|
||||
poetry shell
|
||||
|
||||
py_shell:
|
||||
poetry run python
|
||||
|
||||
format:
|
||||
$(PYTHON) -m black .
|
||||
$(PYTHON) -m isort .
|
||||
|
||||
clean:
|
||||
rm -rf dist build *.egg-info
|
||||
|
||||
lint:
|
||||
poetry run ruff .
|
||||
|
||||
build:
|
||||
poetry build
|
||||
|
||||
publish:
|
||||
poetry publish
|
||||
|
||||
# for example: make test file=tests/test_factory.py
|
||||
test:
|
||||
poetry run pytest $(file)
|
||||
|
||||
coverage:
|
||||
poetry run pytest --cov=$(PROJECT_NAME) --cov-report=xml
|
||||