├── .DS_Store ├── .env.example ├── .github └── workflows │ └── ci.yml ├── .gitignore ├── .pre-commit-config.yaml ├── .pylintrc ├── CONTRIBUTING.md ├── LICENSE ├── MANIFEST.in ├── README.md ├── examples ├── data │ ├── Loan payments data.csv │ └── sample_dataframe.py ├── from_csv.py ├── from_dataframe.py ├── show_chart.py └── with_privacy_enforced.py ├── images ├── histogram-chart.png └── pandas-ai.png ├── pandasai ├── __init__.py ├── exceptions.py ├── helpers │ ├── __init__.py │ └── notebook.py └── llm │ ├── __init__.py │ ├── base.py │ ├── fake.py │ ├── open_assistant.py │ └── openai.py ├── poetry.lock ├── poetry.toml ├── pyproject.toml └── tests ├── __init_.py ├── llms └── __init_.py └── test_pandasai.py /.DS_Store: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysbrianlee/pandasai/c566bebd664de3e208e89f9646fa794df240cddf/.DS_Store -------------------------------------------------------------------------------- /.env.example: -------------------------------------------------------------------------------- 1 | HUGGINGFACE_API_KEY= 2 | OPENAI_API_KEY= -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: pandas_ai_ci 2 | 3 | on: 4 | push: 5 | branches: [main] 6 | pull_request: 7 | 8 | jobs: 9 | build: 10 | runs-on: ubuntu-latest 11 | strategy: 12 | matrix: 13 | python-version: ["3.9", "3.10", "3.11"] 14 | 15 | steps: 16 | - uses: actions/checkout@v3 17 | - name: Set up Python ${{ matrix.python-version }} 18 | uses: actions/setup-python@v4 19 | with: 20 | python-version: ${{ matrix.python-version }} 21 | - name: Install poetry 22 | run: pip install poetry==1.4.2 23 | - name: Install dependencies 24 | run: poetry install 25 | - name: Lint with pylint 26 | run: poetry run pylint pandasai examples 27 | continue-on-error: true 28 | - name: Test with pytest 29 | run: poetry run pytest 30 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # .env 2 | .env 3 | 4 | # __pycache__ 5 | __pycache__ 6 | 7 | # build 8 | build 9 | dist 10 | pandasai.egg-info -------------------------------------------------------------------------------- /.pre-commit-config.yaml: -------------------------------------------------------------------------------- 1 | repos: 2 | - repo: https://github.com/psf/black 3 | rev: 23.3.0 4 | hooks: 5 | - id: black 6 | # It is recommended to specify the latest version of Python 7 | # supported by your project here, or alternatively use 8 | # pre-commit's default_language_version, see 9 | # https://pre-commit.com/#top_level-default_language_version 10 | language_version: python3.9 11 | -------------------------------------------------------------------------------- /.pylintrc: -------------------------------------------------------------------------------- 1 | [MASTER] 2 | ignore=test_* 3 | -------------------------------------------------------------------------------- /CONTRIBUTING.md: -------------------------------------------------------------------------------- 1 | # 🐼 Contributing to PandasAI 2 | 3 | Hi there! We're thrilled that you'd like to contribute to this project. Your help is essential for keeping it great. 4 | 5 | ## 🤝 How to submit a contribution 6 | 7 | To make a contribution, follow the following steps: 8 | 9 | 1. Fork and clone this repository 10 | 2. Do the changes on your fork 11 | 3. Submit a pull request 12 | 13 | ### 📦 Package manager 14 | 15 | We use poetry as our package manager. You can install poetry by following the instructions [here](https://python-poetry.org/docs/#installation). 16 | 17 | Please DO NOT use pip or conda to install the dependencies. Instead, use poetry: 18 | 19 | ```bash 20 | poetry install 21 | ``` 22 | 23 | ### 🧹 Linting 24 | 25 | We use `pylint` to lint our code. You can run the linter by running the following command: 26 | 27 | ```bash 28 | pylint pandasai examples 29 | ``` 30 | 31 | Make sure that the linter does not report any errors or warnings before submitting a pull request. 32 | 33 | ### 🧪 Testing 34 | 35 | We use `pytest` to test our code. You can run the tests by running the following command: 36 | 37 | ```bash 38 | pytest 39 | ``` 40 | 41 | Make sure that all tests pass before submitting a pull request. 42 | 43 | ## 🚀 Release Process 44 | 45 | At the moment, the release process is manual. We try to make frequent releases. Usually, we release a new version when we have a new feature or bugfix. A developer with admin rights to the repository will create a new release on GitHub, and then publish the new version to PyPI. 46 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Copyright (c) Gabriele Venturi 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. 23 | -------------------------------------------------------------------------------- /MANIFEST.in: -------------------------------------------------------------------------------- 1 | recursive-include pandasai * -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # PandasAI 🐼 2 | 3 | [![lint](https://github.com/gventuri/pandas-ai/actions/workflows/ci.yml/badge.svg)](https://github.com/gventuri/pandas-ai/actions/workflows/ci.yml/badge.svg) 4 | [![](https://dcbadge.vercel.app/api/server/kF7FqH2FwS?style=flat&compact=true)](https://discord.gg/kF7FqH2FwS) 5 | [![Downloads](https://static.pepy.tech/badge/pandasai/month)](https://pepy.tech/project/pandasai) [![License: MIT](https://img.shields.io/badge/License-MIT-yellow.svg)](https://opensource.org/licenses/MIT) 6 | [![Open in Colab](https://camo.githubusercontent.com/84f0493939e0c4de4e6dbe113251b4bfb5353e57134ffd9fcab6b8714514d4d1/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667)](https://colab.research.google.com/drive/1rKz7TudOeCeKGHekw7JFNL4sagN9hon-?usp=sharing) 7 | 8 | Pandas AI is a Python library that adds generative artificial intelligence capabilities to Pandas, the popular data analysis and manipulation tool. It is designed to be used in conjunction with Pandas, and is not a replacement for it. 9 | 10 | 11 | 12 | ![PandasAI](images/pandas-ai.png?raw=true) 13 | 14 | ## Demo 15 | 16 | Try out PandasAI in your browser: 17 | 18 | [![Open in Colab](https://camo.githubusercontent.com/84f0493939e0c4de4e6dbe113251b4bfb5353e57134ffd9fcab6b8714514d4d1/68747470733a2f2f636f6c61622e72657365617263682e676f6f676c652e636f6d2f6173736574732f636f6c61622d62616467652e737667)](https://colab.research.google.com/drive/1rKz7TudOeCeKGHekw7JFNL4sagN9hon-?usp=sharing) 19 | 20 | ## Installation 21 | 22 | ```bash 23 | pip install pandasai 24 | ``` 25 | 26 | ## Usage 27 | 28 | PandasAI is designed to be used in conjunction with Pandas. It makes Pandas conversational, allowing you to ask questions about your data and get answers back, in the form of Pandas DataFrames. For example, you can ask PandasAI to find all the rows in a DataFrame where the value of a column is greater than 5, and it will return a DataFrame containing only those rows: 29 | 30 | ```python 31 | import pandas as pd 32 | from pandasai import PandasAI 33 | 34 | # Sample DataFrame 35 | df = pd.DataFrame({ 36 | "country": ["United States", "United Kingdom", "France", "Germany", "Italy", "Spain", "Canada", "Australia", "Japan", "China"], 37 | "gdp": [21400000, 2940000, 2830000, 3870000, 2160000, 1350000, 1780000, 1320000, 516000, 14000000], 38 | "happiness_index": [7.3, 7.2, 6.5, 7.0, 6.0, 6.3, 7.3, 7.3, 5.9, 5.0] 39 | }) 40 | 41 | # Instantiate a LLM 42 | from pandasai.llm.openai import OpenAI 43 | llm = OpenAI() 44 | 45 | pandas_ai = PandasAI(llm) 46 | pandas_ai.run(df, prompt='Which are the 5 happiest countries?') 47 | ``` 48 | 49 | The above code will return the following: 50 | 51 | ``` 52 | 0 United States 53 | 6 Canada 54 | 7 Australia 55 | 1 United Kingdom 56 | 3 Germany 57 | Name: country, dtype: object 58 | ``` 59 | 60 | Of course, you can also ask PandasAI to perform more complex queries. For example, you can ask PandasAI to find the sum of the GDPs of the 2 unhappiest countries: 61 | 62 | ```python 63 | pandas_ai.run(df, prompt='What is the sum of the GDPs of the 2 unhappiest countries?') 64 | ``` 65 | 66 | The above code will return the following: 67 | 68 | ``` 69 | 14516000 70 | ``` 71 | 72 | You can also ask PandasAI to draw a graph: 73 | 74 | ```python 75 | pandas_ai.run( 76 | df, 77 | "Plot the histogram of countries showing for each the gpd, using different colors for each bar", 78 | ) 79 | ``` 80 | 81 | ![Chart](images/histogram-chart.png?raw=true) 82 | 83 | You can find more examples in the [examples](examples) directory. 84 | 85 | ## Environment Variables 86 | 87 | In order to set the API key for the LLM (Hugging Face Hub, OpenAI), you need to set the appropriate environment variables. You can do this by copying the `.env.example` file to `.env`: 88 | 89 | ```bash 90 | cp .env.example .env 91 | ``` 92 | 93 | Then, edit the `.env` file and set the appropriate values. 94 | 95 | As an alternative, you can also pass the environment variables directly to the constructor of the LLM: 96 | 97 | ```python 98 | # OpenAI 99 | llm = OpenAI(api_token="YOUR_OPENAI_API_KEY") 100 | 101 | # OpenAssistant 102 | llm = OpenAssistant(api_token="YOUR_HF_API_KEY") 103 | ``` 104 | 105 | ## License 106 | 107 | PandasAI is licensed under the MIT License. See the LICENSE file for more details. 108 | 109 | ## Contributing 110 | 111 | Contributions are welcome! Please check out the todos below, and feel free to open a pull request. 112 | For more information, please see the [contributing guidelines](CONTRIBUTING.md). 113 | 114 | ### Todo 115 | 116 | - [ ] Add support for more LLMs 117 | - [ ] Make PandasAI available from a CLI 118 | - [ ] Create a web interface for PandasAI 119 | - [ ] Add unit tests 120 | - [ ] Add contributing guidelines 121 | - [x] Add CI 122 | - [x] Add support for conversational responses 123 | -------------------------------------------------------------------------------- /examples/data/Loan payments data.csv: -------------------------------------------------------------------------------- 1 | Loan_ID,loan_status,Principal,terms,effective_date,due_date,paid_off_time,past_due_days,age,education,Gender 2 | xqd20166231,PAIDOFF,1000,30,9/8/2016,10/7/2016,9/14/2016 19:31,,45,High School or Below,male 3 | xqd20168902,PAIDOFF,1000,30,9/8/2016,10/7/2016,10/7/2016 9:00,,50,Bechalor,female 4 | xqd20160003,PAIDOFF,1000,30,9/8/2016,10/7/2016,9/25/2016 16:58,,33,Bechalor,female 5 | xqd20160004,PAIDOFF,1000,15,9/8/2016,9/22/2016,9/22/2016 20:00,,27,college,male 6 | xqd20160005,PAIDOFF,1000,30,9/9/2016,10/8/2016,9/23/2016 21:36,,28,college,female 7 | xqd20160706,PAIDOFF,300,7,9/9/2016,9/15/2016,9/9/2016 13:45,,35,Master or Above,male 8 | xqd20160007,PAIDOFF,1000,30,9/9/2016,10/8/2016,10/7/2016 23:07,,29,college,male 9 | xqd20160008,PAIDOFF,1000,30,9/9/2016,10/8/2016,10/5/2016 20:33,,36,college,male 10 | xqd20160909,PAIDOFF,1000,30,9/9/2016,10/8/2016,10/8/2016 16:00,,28,college,male 11 | xqd20160010,PAIDOFF,800,15,9/10/2016,9/24/2016,9/24/2016 13:00,,26,college,male 12 | xqd20160011,PAIDOFF,300,7,9/10/2016,9/16/2016,9/11/2016 19:11,,29,college,male 13 | xqd20160012,PAIDOFF,1000,15,9/10/2016,10/9/2016,10/9/2016 16:00,,39,High School or Below,male 14 | xqd20160013,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/7/2016 23:32,,26,college,male 15 | xqd20160014,PAIDOFF,900,7,9/10/2016,9/16/2016,9/13/2016 21:57,,26,college,female 16 | xqd20160015,PAIDOFF,1000,7,9/10/2016,9/16/2016,9/15/2016 14:27,,27,High School or Below,male 17 | xqd20160016,PAIDOFF,800,15,9/10/2016,9/24/2016,9/24/2016 16:00,,26,college,male 18 | xqd20160017,PAIDOFF,1000,30,9/10/2016,10/9/2016,9/27/2016 14:21,,40,High School or Below,male 19 | xqd20160018,PAIDOFF,1000,15,9/10/2016,9/24/2016,9/23/2016 18:49,,32,High School or Below,male 20 | xqd20160019,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/5/2016 22:05,,32,High School or Below,male 21 | xqd20160020,PAIDOFF,800,30,9/10/2016,10/9/2016,9/23/2016 7:42,,26,college,male 22 | xqd20160021,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/9/2016 9:00,,26,college,male 23 | xqd20160022,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/8/2016 17:09,,43,High School or Below,female 24 | xqd20160023,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/9/2016 23:00,,25,High School or Below,male 25 | xqd20160024,PAIDOFF,1000,15,9/10/2016,9/24/2016,9/24/2016 13:00,,26,college,male 26 | xqd20160025,PAIDOFF,1000,30,9/10/2016,10/9/2016,10/3/2016 12:50,,26,college,male 27 | xqd20160026,PAIDOFF,1000,30,9/10/2016,10/9/2016,9/29/2016 12:18,,29,High School or Below,male 28 | xqd20160027,PAIDOFF,800,15,9/10/2016,9/24/2016,9/21/2016 20:16,,39,Bechalor,male 29 | xqd20170088,PAIDOFF,1000,15,9/10/2016,9/24/2016,9/23/2016 8:21,,34,Bechalor,male 30 | xqd20160029,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/22/2016 19:17,,31,college,male 31 | xqd20160030,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 17:33,,33,college,male 32 | xqd88160031,PAIDOFF,800,15,9/11/2016,9/25/2016,9/24/2016 14:41,,33,High School or Below,male 33 | xqd20160032,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/7/2016 21:48,,37,college,male 34 | xqd20160033,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 17:44,,27,college,male 35 | xqd22169034,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 7:24,,37,college,male 36 | xqd20160035,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 21:49,,33,college,male 37 | xqd20160036,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 9:00,,29,Bechalor,male 38 | xqd20160037,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:00,,27,High School or Below,male 39 | xqd20160038,PAIDOFF,700,15,9/11/2016,9/25/2016,9/25/2016 13:00,,33,High School or Below,male 40 | xqd20160039,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,24,college,male 41 | xqd20160040,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 11:33,,21,Bechalor,male 42 | xqd20160041,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,32,college,female 43 | xqd20160042,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 14:36,,30,college,male 44 | xqd20160043,PAIDOFF,1000,7,9/11/2016,9/24/2016,9/24/2016 9:00,,31,Bechalor,male 45 | xqd20160044,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/20/2016 15:00,,30,college,male 46 | xqd20160045,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/21/2016 22:29,,24,Bechalor,female 47 | xqd20160046,PAIDOFF,800,7,9/11/2016,9/17/2016,9/12/2016 22:17,,35,High School or Below,male 48 | xqd20160047,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 14:14,,22,High School or Below,male 49 | xqd20160048,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 8:53,,32,college,male 50 | xqd20160049,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,32,Bechalor,male 51 | xqd20160050,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 19:21,,50,High School or Below,male 52 | xqd20160051,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 13:00,,27,college,female 53 | xqd20160052,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,35,Bechalor,female 54 | xqd20160053,PAIDOFF,800,15,9/11/2016,9/25/2016,9/13/2016 4:34,,35,Bechalor,female 55 | xqd20160054,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,34,High School or Below,male 56 | xqd20160055,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:00,,21,High School or Below,male 57 | xqd20160056,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 16:00,,25,college,male 58 | xqd20160057,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,27,High School or Below,male 59 | xqd20160058,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/7/2016 2:33,,26,Bechalor,male 60 | xqd20160059,PAIDOFF,800,15,9/11/2016,9/25/2016,9/24/2016 11:40,,44,High School or Below,female 61 | xqd20160060,PAIDOFF,800,15,9/11/2016,9/25/2016,9/22/2016 6:38,,39,Master or Above,male 62 | xqd20160061,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/30/2016 21:12,,34,Bechalor,male 63 | xqd20160062,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/24/2016 13:42,,37,college,male 64 | xqd20160063,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 7:25,,34,High School or Below,male 65 | xqd20160064,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/12/2016 11:40,,45,college,male 66 | xqd20160065,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 14:38,,24,High School or Below,male 67 | xqd20160066,PAIDOFF,900,15,9/11/2016,9/25/2016,9/25/2016 23:00,,28,college,male 68 | xqd20160067,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 12:04,,28,Bechalor,male 69 | xqd20160068,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,37,High School or Below,male 70 | xqd20160069,PAIDOFF,300,7,9/11/2016,9/17/2016,9/14/2016 22:05,,35,college,male 71 | xqd20160070,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/24/2016 13:27,,43,Bechalor,male 72 | xqd20160071,PAIDOFF,800,15,9/11/2016,9/25/2016,9/22/2016 21:18,,29,college,male 73 | xqd20160072,PAIDOFF,800,15,9/11/2016,9/25/2016,9/24/2016 22:53,,29,High School or Below,male 74 | xqd20160073,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:00,,33,Bechalor,female 75 | xqd20160074,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,34,college,male 76 | xqd20160075,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,25,college,male 77 | xqd20160076,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 13:12,,30,High School or Below,male 78 | xqd20160077,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 13:49,,31,Bechalor,male 79 | xqd20160078,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,35,college,male 80 | xqd20160079,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/30/2016 14:29,,37,college,female 81 | xqd20160080,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,44,High School or Below,female 82 | xqd20160081,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/21/2016 16:18,,28,High School or Below,male 83 | xqd20160082,PAIDOFF,1000,7,9/11/2016,9/17/2016,9/13/2016 14:53,,25,college,male 84 | xqd20160083,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,29,college,male 85 | xqd20160084,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 13:00,,33,college,male 86 | xqd20160085,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 13:00,,37,High School or Below,female 87 | xqd20160086,PAIDOFF,1000,30,9/11/2016,11/9/2016,11/9/2016 9:00,,33,college,male 88 | xqd20160087,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:00,,24,High School or Below,female 89 | xqd20160088,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/17/2016 13:01,,27,college,female 90 | xqd20160089,PAIDOFF,800,15,9/11/2016,9/25/2016,9/21/2016 9:35,,43,Bechalor,male 91 | xqd90160090,PAIDOFF,800,15,9/11/2016,9/25/2016,9/24/2016 20:33,,46,High School or Below,female 92 | xqd91160291,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 9:00,,34,college,female 93 | xqd90160092,PAIDOFF,1000,7,9/11/2016,9/17/2016,9/17/2016 9:00,,32,Bechalor,female 94 | xqd90163093,PAIDOFF,800,15,9/11/2016,9/25/2016,9/24/2016 0:12,,38,High School or Below,male 95 | xqd20160094,PAIDOFF,800,15,9/11/2016,9/25/2016,9/21/2016 12:43,,27,High School or Below,male 96 | xqd20167095,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 13:00,,33,High School or Below,male 97 | xqd20160096,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 20:49,,36,college,male 98 | xqd20160097,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/20/2016 5:38,,26,High School or Below,male 99 | xqd20160098,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:01,,34,college,male 100 | xqd20160099,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:01,,22,High School or Below,male 101 | xqd20160100,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 16:55,,31,Bechalor,female 102 | xqd20160101,PAIDOFF,1000,7,9/11/2016,9/17/2016,9/17/2016 9:00,,29,High School or Below,male 103 | xqd20160102,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 9:00,,38,college,male 104 | xqd20160103,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:00,,30,college,male 105 | xqd20160104,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 23:48,,45,High School or Below,male 106 | xqd20160105,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/22/2016 13:15,,35,college,male 107 | xqd20160106,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/23/2016 13:31,,30,college,male 108 | xqd20160107,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 17:19,,31,High School or Below,male 109 | xqd20160108,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:01,,31,High School or Below,male 110 | xqd20160109,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 13:05,,28,college,male 111 | xqd20160110,PAIDOFF,1000,7,9/11/2016,9/24/2016,9/24/2016 13:00,,29,college,male 112 | xqd20160111,PAIDOFF,800,15,9/11/2016,9/25/2016,9/20/2016 20:47,,29,college,male 113 | xqd20160112,PAIDOFF,1000,30,9/11/2016,11/9/2016,11/9/2016 9:00,,27,college,female 114 | xqd20160113,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 9:01,,27,college,male 115 | xqd20160114,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 13:01,,33,college,male 116 | xqd20160115,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 21:39,,28,college,male 117 | xqd20160116,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 23:00,,25,High School or Below,male 118 | xqd20160117,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/7/2016 14:23,,40,college,male 119 | xqd20160118,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/6/2016 15:25,,23,High School or Below,male 120 | xqd20160119,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/8/2016 6:56,,35,Bechalor,male 121 | xqd20160120,PAIDOFF,800,15,9/11/2016,9/25/2016,9/16/2016 11:58,,24,college,male 122 | xqd20160121,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:01,,34,college,male 123 | xqd20160122,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/27/2016 7:02,,22,High School or Below,male 124 | xqd20160123,PAIDOFF,1000,15,9/11/2016,10/25/2016,10/25/2016 9:00,,20,college,male 125 | xqd20160124,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/24/2016 11:02,,23,college,male 126 | xqd20160125,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/29/2016 18:57,,33,college,male 127 | xqd20160126,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 13:01,,26,college,male 128 | xqd20160127,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 9:00,,28,High School or Below,male 129 | xqd20160128,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 12:24,,43,High School or Below,male 130 | xqd78160129,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/25/2016 13:00,,34,Bechalor,male 131 | xqd20160130,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/26/2016 4:41,,38,Bechalor,male 132 | xqd20160131,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/22/2016 15:44,,26,High School or Below,male 133 | xqd20160132,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 16:00,,43,High School or Below,male 134 | xqd20160133,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/10/2016 16:13,,26,High School or Below,male 135 | xqd20160134,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/30/2016 7:12,,33,college,female 136 | xqd20160135,PAIDOFF,800,15,9/11/2016,9/25/2016,9/23/2016 11:26,,24,college,male 137 | xqd20160136,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/12/2016 10:26,,30,High School or Below,male 138 | xqd20160137,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 13:00,,32,High School or Below,female 139 | xqd20160138,PAIDOFF,1000,15,9/11/2016,10/25/2016,10/25/2016 9:00,,22,college,male 140 | xqd20160139,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/22/2016 21:45,,47,High School or Below,male 141 | xqd56160140,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/9/2016 20:28,,20,High School or Below,male 142 | xqd20160141,PAIDOFF,1000,30,9/11/2016,10/10/2016,10/1/2016 16:48,,28,High School or Below,male 143 | xqd20160142,PAIDOFF,800,15,9/11/2016,9/25/2016,9/25/2016 9:01,,35,college,male 144 | xqd20160143,PAIDOFF,1000,7,9/11/2016,9/17/2016,9/15/2016 20:36,,27,High School or Below,male 145 | xqd20160144,PAIDOFF,800,15,9/11/2016,9/25/2016,9/21/2016 15:33,,33,college,female 146 | xqd20160145,PAIDOFF,1000,30,9/11/2016,10/10/2016,9/29/2016 13:36,,30,High School or Below,male 147 | xqd20160146,PAIDOFF,1000,15,9/11/2016,9/25/2016,9/22/2016 20:51,,31,college,male 148 | xqd20160147,PAIDOFF,1000,30,9/11/2016,11/9/2016,11/9/2016 23:00,,26,college,female 149 | xqd20160148,PAIDOFF,300,7,9/12/2016,9/18/2016,9/18/2016 9:00,,37,Master or Above,male 150 | xqd20160149,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,26,Bechalor,male 151 | xqd20160150,PAIDOFF,800,15,9/12/2016,9/26/2016,9/24/2016 10:14,,35,Bechalor,male 152 | xqd20160151,PAIDOFF,1000,15,9/12/2016,10/26/2016,10/26/2016 9:00,,29,college,male 153 | xqd34160152,PAIDOFF,800,15,9/12/2016,9/26/2016,9/23/2016 20:30,,23,college,male 154 | xqd20160153,PAIDOFF,500,15,9/12/2016,9/26/2016,9/13/2016 20:17,,23,college,female 155 | xqd20160154,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,30,college,male 156 | xqd20160155,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 7:01,,34,college,male 157 | xqd20160156,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:00,,36,High School or Below,female 158 | xqd20160157,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,26,Bechalor,male 159 | xqd20160158,PAIDOFF,800,15,9/12/2016,9/26/2016,9/24/2016 14:55,,29,High School or Below,male 160 | xqd12160159,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,28,college,female 161 | xqd20160160,PAIDOFF,1000,30,9/12/2016,10/11/2016,9/25/2016 20:56,,27,High School or Below,male 162 | xqd20160161,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/22/2016 10:49,,24,High School or Below,male 163 | xqd20160162,PAIDOFF,800,15,9/12/2016,9/26/2016,9/25/2016 22:09,,31,Bechalor,male 164 | xqd20160163,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:00,,28,High School or Below,male 165 | xqd28160164,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,27,college,female 166 | xqd20160165,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 19:33,,25,High School or Below,male 167 | xqd20160166,PAIDOFF,1000,30,9/12/2016,11/10/2016,11/10/2016 16:00,,24,High School or Below,male 168 | xqd20160167,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 16:00,,28,college,male 169 | xqd20160168,PAIDOFF,800,30,9/12/2016,10/11/2016,10/11/2016 16:00,,28,college,male 170 | xqd20160169,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 13:00,,35,High School or Below,male 171 | xqd27160170,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:00,,38,college,male 172 | xqd20160171,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 16:00,,38,High School or Below,male 173 | xqd20160172,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 16:00,,29,college,male 174 | xqd20160173,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 13:00,,35,High School or Below,male 175 | xqd20160174,PAIDOFF,1000,30,9/12/2016,10/11/2016,9/17/2016 7:39,,24,college,male 176 | xqd20160175,PAIDOFF,800,15,9/12/2016,9/26/2016,9/22/2016 10:30,,39,High School or Below,male 177 | xqd20160176,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 13:00,,25,college,male 178 | xqd20160177,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 16:00,,38,High School or Below,male 179 | xqd20160178,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 20:41,,30,college,male 180 | xqd20160179,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:00,,21,High School or Below,male 181 | xqd20160180,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 8:04,,46,college,male 182 | xqd20160181,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/24/2016 11:00,,31,High School or Below,female 183 | xqd20160182,PAIDOFF,300,7,9/12/2016,9/18/2016,9/17/2016 9:25,,29,High School or Below,male 184 | xqd20160183,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/7/2016 11:53,,35,High School or Below,male 185 | xqd20160184,PAIDOFF,800,15,9/12/2016,9/26/2016,9/25/2016 8:39,,30,High School or Below,male 186 | xqd20160185,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:00,,27,High School or Below,male 187 | xqd20160186,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 20:28,,31,High School or Below,female 188 | xqd20160187,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/1/2016 10:18,,33,Bechalor,male 189 | xqd20160188,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 16:00,,34,High School or Below,male 190 | xqd20160189,PAIDOFF,800,15,9/12/2016,9/26/2016,9/19/2016 21:07,,28,college,male 191 | xqd20160190,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 9:00,,42,college,male 192 | xqd20160191,PAIDOFF,1000,30,9/12/2016,10/11/2016,9/30/2016 14:38,,32,college,male 193 | xqd20160192,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:00,,30,High School or Below,male 194 | xqd20160193,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/14/2016 20:31,,25,High School or Below,female 195 | xqd20160194,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:00,,27,High School or Below,female 196 | xqd20160195,PAIDOFF,800,15,9/12/2016,9/26/2016,9/24/2016 16:15,,21,college,male 197 | xqd20160196,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 15:49,,24,college,male 198 | xqd20160197,PAIDOFF,1000,30,9/12/2016,11/10/2016,11/10/2016 13:00,,29,college,male 199 | xqd20160198,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/23/2016 10:32,,40,college,male 200 | xqd20160199,PAIDOFF,1000,30,9/12/2016,10/11/2016,9/30/2016 14:03,,29,High School or Below,male 201 | xqd20160200,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/9/2016 14:17,,29,college,male 202 | xqd20160201,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/20/2016 8:26,,30,college,male 203 | xqd20160202,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 23:00,,26,High School or Below,female 204 | xqd20160203,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/24/2016 20:47,,36,High School or Below,male 205 | xqd20160204,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 16:00,,27,college,male 206 | xqd20160205,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:01,,20,college,male 207 | xqd20160206,PAIDOFF,1000,7,9/12/2016,9/18/2016,9/16/2016 14:52,,26,Bechalor,female 208 | xqd20160207,PAIDOFF,1000,30,9/12/2016,11/10/2016,11/10/2016 13:00,,26,college,male 209 | xqd20160208,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/9/2016 10:00,,27,college,male 210 | xqd20160209,PAIDOFF,300,7,9/12/2016,9/18/2016,9/12/2016 14:40,,23,High School or Below,male 211 | xqd20160210,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 16:00,,39,High School or Below,male 212 | xqd20160211,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/23/2016 21:58,,27,High School or Below,male 213 | xqd20160212,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/8/2016 18:48,,30,High School or Below,male 214 | xqd20160213,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/10/2016 16:41,,33,High School or Below,female 215 | xqd20160214,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:01,,27,High School or Below,male 216 | xqd20160215,PAIDOFF,1000,30,9/12/2016,10/11/2016,9/16/2016 2:34,,35,High School or Below,male 217 | xqd20160216,PAIDOFF,1000,30,9/12/2016,11/10/2016,11/10/2016 16:00,,29,college,female 218 | xqd20160217,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/21/2016 8:11,,50,High School or Below,male 219 | xqd20160218,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 9:00,,31,High School or Below,female 220 | xqd20160219,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 13:00,,31,High School or Below,male 221 | xqd20160220,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:01,,29,High School or Below,male 222 | xqd20160221,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 23:00,,35,college,male 223 | xqd20160222,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 9:01,,39,college,male 224 | xqd20160223,PAIDOFF,1000,30,9/12/2016,11/10/2016,11/10/2016 13:00,,29,college,male 225 | xqd20160224,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 23:00,,30,High School or Below,male 226 | xqd20160225,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/9/2016 10:00,,33,Bechalor,male 227 | xqd20160226,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 13:01,,26,High School or Below,male 228 | xqd20160227,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/23/2016 14:01,,25,High School or Below,male 229 | xqd20160228,PAIDOFF,800,15,9/12/2016,9/26/2016,9/25/2016 13:29,,37,Bechalor,male 230 | xqd20160229,PAIDOFF,800,15,9/12/2016,9/26/2016,9/25/2016 14:50,,26,High School or Below,male 231 | xqd20160230,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 9:00,,26,college,male 232 | xqd20160231,PAIDOFF,1000,15,9/12/2016,10/26/2016,10/26/2016 9:00,,27,college,male 233 | xqd20160232,PAIDOFF,1000,7,9/12/2016,9/25/2016,9/25/2016 9:01,,34,college,female 234 | xqd20160233,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/8/2016 15:35,,37,college,male 235 | xqd20160234,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/11/2016 16:01,,36,High School or Below,male 236 | xqd20160235,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 19:35,,33,High School or Below,male 237 | xqd20160236,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/9/2016 21:28,,30,High School or Below,male 238 | xqd20160237,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/7/2016 16:45,,30,college,male 239 | xqd20160238,PAIDOFF,800,15,9/12/2016,9/26/2016,9/24/2016 12:13,,36,High School or Below,male 240 | xqd20160239,PAIDOFF,1000,15,9/12/2016,10/11/2016,10/11/2016 9:01,,29,college,male 241 | xqd20160240,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/14/2016 23:02,,36,High School or Below,male 242 | xqd20160241,PAIDOFF,1000,30,9/12/2016,10/11/2016,10/8/2016 11:03,,32,High School or Below,male 243 | xqd20160242,PAIDOFF,1000,15,9/12/2016,9/26/2016,9/26/2016 9:00,,29,High School or Below,female 244 | xqd20160243,PAIDOFF,800,15,9/12/2016,9/26/2016,9/26/2016 23:00,,36,Bechalor,male 245 | xqd20160244,PAIDOFF,800,15,9/12/2016,9/26/2016,9/25/2016 19:31,,30,High School or Below,female 246 | xqd20160245,PAIDOFF,1000,7,9/13/2016,9/19/2016,9/14/2016 19:48,,31,college,male 247 | xqd20160246,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/12/2016 23:00,,19,High School or Below,female 248 | xqd20160247,PAIDOFF,800,15,9/13/2016,9/27/2016,9/25/2016 12:48,,26,college,male 249 | xqd20160248,PAIDOFF,800,15,9/13/2016,9/27/2016,9/26/2016 21:18,,34,High School or Below,male 250 | xqd20160249,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/7/2016 10:22,,35,High School or Below,male 251 | xqd20160250,PAIDOFF,1000,15,9/13/2016,9/27/2016,9/26/2016 6:17,,35,Bechalor,female 252 | xqd20160251,PAIDOFF,800,15,9/13/2016,9/27/2016,9/22/2016 16:57,,38,college,male 253 | xqd20160252,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/9/2016 21:57,,29,college,male 254 | xqd20160253,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/4/2016 12:59,,28,High School or Below,male 255 | xqd20160254,PAIDOFF,500,7,9/13/2016,9/19/2016,9/17/2016 20:51,,22,High School or Below,male 256 | xqd20160255,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/12/2016 23:00,,32,college,male 257 | xqd20160256,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/8/2016 15:51,,31,college,male 258 | xqd20160257,PAIDOFF,800,15,9/13/2016,9/27/2016,9/27/2016 9:00,,28,college,male 259 | xqd20160258,PAIDOFF,1000,15,9/13/2016,9/27/2016,9/27/2016 9:00,,37,college,female 260 | xqd20160259,PAIDOFF,1000,7,9/13/2016,9/19/2016,9/16/2016 15:57,,25,college,male 261 | xqd20160260,PAIDOFF,1000,30,9/13/2016,10/12/2016,10/12/2016 9:00,,19,High School or Below,male 262 | xqd20160261,PAIDOFF,800,15,9/13/2016,9/27/2016,9/26/2016 7:48,,51,college,male 263 | xqd20160262,PAIDOFF,1000,15,9/13/2016,9/27/2016,9/21/2016 16:53,,29,High School or Below,male 264 | xqd20160263,PAIDOFF,800,30,9/13/2016,10/12/2016,10/11/2016 0:29,,23,college,female 265 | xqd20160264,PAIDOFF,1000,15,9/13/2016,9/27/2016,9/25/2016 10:37,,30,High School or Below,male 266 | xqd20160265,PAIDOFF,800,15,9/13/2016,9/27/2016,9/27/2016 13:00,,23,college,male 267 | xqd20160266,PAIDOFF,1000,15,9/13/2016,9/27/2016,9/26/2016 15:10,,34,Bechalor,female 268 | xqd20160267,PAIDOFF,800,15,9/13/2016,9/27/2016,9/24/2016 12:46,,31,Bechalor,female 269 | xqd20160268,PAIDOFF,1000,15,9/14/2016,9/28/2016,9/28/2016 9:00,,24,High School or Below,male 270 | xqd20160269,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,42,High School or Below,male 271 | xqd20160270,PAIDOFF,800,30,9/14/2016,10/13/2016,10/6/2016 12:09,,40,college,female 272 | xqd20160271,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/14/2016 11:03,,29,High School or Below,male 273 | xqd20160272,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/8/2016 17:12,,32,college,female 274 | xqd20160273,PAIDOFF,1000,30,9/14/2016,11/12/2016,11/12/2016 9:00,,28,college,male 275 | xqd20160274,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,35,High School or Below,male 276 | xqd20160275,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 13:00,,30,Bechalor,male 277 | xqd20160276,PAIDOFF,800,15,9/14/2016,9/28/2016,9/27/2016 15:52,,44,college,male 278 | xqd20160277,PAIDOFF,800,15,9/14/2016,9/28/2016,9/28/2016 13:00,,37,High School or Below,male 279 | xqd20160278,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,31,college,male 280 | xqd20160279,PAIDOFF,800,15,9/14/2016,9/28/2016,9/15/2016 0:43,,36,college,male 281 | xqd20160280,PAIDOFF,800,30,9/14/2016,10/13/2016,10/10/2016 10:25,,31,college,male 282 | xqd20160281,PAIDOFF,800,15,9/14/2016,9/28/2016,9/27/2016 20:41,,42,High School or Below,male 283 | xqd20160282,PAIDOFF,1000,15,9/14/2016,9/28/2016,9/28/2016 9:00,,28,Bechalor,male 284 | xqd20160283,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/6/2016 6:51,,30,college,male 285 | xqd20160284,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/12/2016 6:25,,30,High School or Below,male 286 | xqd20160285,PAIDOFF,1000,15,9/14/2016,9/28/2016,9/27/2016 22:50,,24,Bechalor,male 287 | xqd20160286,PAIDOFF,1000,30,9/14/2016,11/12/2016,11/12/2016 9:00,,34,Bechalor,male 288 | xqd20160287,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/12/2016 12:30,,29,college,male 289 | xqd20160288,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/12/2016 3:49,,38,High School or Below,female 290 | xqd20160289,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 13:00,,34,Bechalor,male 291 | xqd20160290,PAIDOFF,800,15,9/14/2016,9/28/2016,9/27/2016 7:48,,28,High School or Below,male 292 | xqd20160291,PAIDOFF,1000,15,9/14/2016,9/28/2016,9/22/2016 9:28,,30,college,female 293 | xqd20160292,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/11/2016 16:33,,41,High School or Below,male 294 | xqd20160293,PAIDOFF,1000,30,9/14/2016,10/13/2016,9/18/2016 16:56,,29,college,male 295 | xqd20160294,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,37,High School or Below,male 296 | xqd20160295,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 13:00,,36,Bechalor,male 297 | xqd20160296,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 13:00,,30,college,female 298 | xqd20160297,PAIDOFF,800,15,9/14/2016,9/28/2016,9/21/2016 4:42,,27,college,male 299 | xqd20160298,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,29,High School or Below,male 300 | xqd20160299,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 9:00,,40,High School or Below,male 301 | xqd20160300,PAIDOFF,1000,30,9/14/2016,10/13/2016,10/13/2016 11:00,,28,college,male 302 | xqd20160301,COLLECTION,1000,15,9/9/2016,9/23/2016,,76,29,college,male 303 | xqd20160302,COLLECTION,1000,30,9/9/2016,10/8/2016,,61,37,High School or Below,male 304 | xqd20160303,COLLECTION,1000,30,9/9/2016,10/8/2016,,61,33,High School or Below,male 305 | xqd20160304,COLLECTION,800,15,9/9/2016,9/23/2016,,76,27,college,male 306 | xqd20160305,COLLECTION,800,15,9/9/2016,9/23/2016,,76,24,Bechalor,male 307 | xqd20160306,COLLECTION,1000,15,9/10/2016,9/24/2016,,75,31,High School or Below,female 308 | xqd20160307,COLLECTION,800,15,9/10/2016,10/9/2016,,60,28,college,male 309 | xqd20160308,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,40,High School or Below,male 310 | xqd20160309,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,33,college,male 311 | xqd20160310,COLLECTION,800,15,9/10/2016,9/24/2016,,75,41,college,male 312 | xqd20160311,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,30,college,male 313 | xqd20160312,COLLECTION,800,15,9/10/2016,9/24/2016,,75,26,High School or Below,female 314 | xqd20160313,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,27,High School or Below,male 315 | xqd20160314,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,20,High School or Below,male 316 | xqd20160315,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,24,college,male 317 | xqd20160316,COLLECTION,1000,15,9/10/2016,10/9/2016,,60,26,High School or Below,male 318 | xqd20160317,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,30,High School or Below,male 319 | xqd20160318,COLLECTION,1000,15,9/10/2016,9/24/2016,,75,29,High School or Below,male 320 | xqd20160319,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,22,Bechalor,male 321 | xqd20160320,COLLECTION,1000,15,9/10/2016,9/24/2016,,75,24,Bechalor,male 322 | xqd20160321,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,25,college,male 323 | xqd20160322,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,28,High School or Below,male 324 | xqd20160323,COLLECTION,1000,30,9/10/2016,10/9/2016,,60,37,college,male 325 | xqd20160324,COLLECTION,800,15,9/10/2016,9/24/2016,,75,32,college,male 326 | xqd20160325,COLLECTION,1000,15,9/10/2016,9/24/2016,,75,34,college,male 327 | xqd20160326,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,28,Bechalor,male 328 | xqd20160327,COLLECTION,800,15,9/11/2016,9/25/2016,,74,35,Bechalor,male 329 | xqd20160328,COLLECTION,1000,30,9/11/2016,11/9/2016,,29,27,college,male 330 | xqd20160329,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,24,High School or Below,female 331 | xqd20160330,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,44,Bechalor,male 332 | xqd20160331,COLLECTION,1000,15,9/11/2016,10/25/2016,,44,31,college,male 333 | xqd20160332,COLLECTION,800,15,9/11/2016,9/25/2016,,74,27,college,male 334 | xqd20160333,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,21,High School or Below,male 335 | xqd20160334,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,30,High School or Below,female 336 | xqd20160335,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,38,college,female 337 | xqd20160336,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,34,High School or Below,male 338 | xqd20160337,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,31,college,male 339 | xqd20160338,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,23,High School or Below,male 340 | xqd20160339,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,27,college,female 341 | xqd20160340,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,39,High School or Below,male 342 | xqd20160341,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,30,High School or Below,female 343 | xqd20160342,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,25,college,male 344 | xqd20160343,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,50,Master or Above,male 345 | xqd20160344,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,23,High School or Below,male 346 | xqd20160345,COLLECTION,800,15,9/11/2016,9/25/2016,,74,38,Bechalor,male 347 | xqd20160346,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,27,High School or Below,male 348 | xqd20160347,COLLECTION,1000,30,9/11/2016,11/9/2016,,29,31,High School or Below,male 349 | xqd20160348,COLLECTION,800,15,9/11/2016,9/25/2016,,74,40,college,male 350 | xqd20160349,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,32,High School or Below,male 351 | xqd20160350,COLLECTION,800,15,9/11/2016,9/25/2016,,74,29,college,male 352 | xqd20160351,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,26,High School or Below,male 353 | xqd20160352,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,25,college,male 354 | xqd20160353,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,35,High School or Below,male 355 | xqd20160354,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,41,High School or Below,male 356 | xqd20160355,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,37,High School or Below,male 357 | xqd20160356,COLLECTION,1000,15,9/11/2016,10/10/2016,,59,34,college,male 358 | xqd20160357,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,45,High School or Below,male 359 | xqd20160358,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,26,Bechalor,male 360 | xqd20160359,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,32,college,male 361 | xqd20160360,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,28,High School or Below,male 362 | xqd20160361,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,34,college,male 363 | xqd20160362,COLLECTION,800,15,9/11/2016,9/25/2016,,74,29,High School or Below,male 364 | xqd20160363,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,26,High School or Below,male 365 | xqd20160364,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,26,college,male 366 | xqd20160365,COLLECTION,800,15,9/11/2016,9/25/2016,,74,22,college,male 367 | xqd20160366,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,27,High School or Below,female 368 | xqd20160367,COLLECTION,800,30,9/11/2016,10/10/2016,,59,33,High School or Below,male 369 | xqd20160368,COLLECTION,800,15,9/11/2016,9/25/2016,,74,28,Bechalor,male 370 | xqd20160369,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,24,college,male 371 | xqd20160370,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,37,High School or Below,male 372 | xqd20160371,COLLECTION,800,15,9/11/2016,9/25/2016,,74,36,High School or Below,male 373 | xqd20160372,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,18,college,male 374 | xqd20160373,COLLECTION,800,15,9/11/2016,9/25/2016,,74,25,High School or Below,male 375 | xqd20160374,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,40,High School or Below,male 376 | xqd20182575,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,29,college,male 377 | xqd20160376,COLLECTION,800,15,9/11/2016,9/25/2016,,74,26,High School or Below,female 378 | xqd20151038,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,30,college,male 379 | xqd20160378,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,33,college,male 380 | xqd20197340,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,30,college,male 381 | xqd20160380,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,32,college,male 382 | xqd20160381,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,25,High School or Below,male 383 | xqd20160382,COLLECTION,800,15,9/11/2016,9/25/2016,,74,35,High School or Below,male 384 | xqd20175721,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,30,Bechalor,male 385 | xqd20160384,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,26,High School or Below,male 386 | xqd20160385,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,29,High School or Below,male 387 | xqd20160386,COLLECTION,1000,30,9/11/2016,11/9/2016,,29,26,High School or Below,male 388 | xqd20160387,COLLECTION,800,15,9/11/2016,9/25/2016,,74,46,High School or Below,male 389 | xqd20160388,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,36,High School or Below,male 390 | xqd20160389,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,38,Bechalor,male 391 | xqd20160390,COLLECTION,1000,15,9/11/2016,10/25/2016,,44,32,High School or Below,male 392 | xqd20160391,COLLECTION,1000,15,9/11/2016,9/25/2016,,74,30,college,male 393 | xqd20125284,COLLECTION,800,15,9/11/2016,9/25/2016,,74,35,High School or Below,male 394 | xqd20160393,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,29,college,female 395 | xqd20160394,COLLECTION,1000,30,9/11/2016,11/9/2016,,29,26,college,male 396 | xqd20160395,COLLECTION,800,15,9/11/2016,9/25/2016,,74,32,High School or Below,male 397 | xqd20160396,COLLECTION,1000,30,9/11/2016,10/10/2016,,59,25,High School or Below,male 398 | xqd20160397,COLLECTION,1000,30,9/12/2016,10/11/2016,,58,33,High School or Below,male 399 | xqd20160398,COLLECTION,800,15,9/12/2016,9/26/2016,,73,39,college,male 400 | xqd20160399,COLLECTION,1000,30,9/12/2016,11/10/2016,,28,28,college,male 401 | xqd20160400,COLLECTION,1000,30,9/12/2016,10/11/2016,,58,26,college,male 402 | xqd20160401,COLLECTION_PAIDOFF,1000,30,9/9/2016,10/8/2016,10/10/2016 11:45,2,26,college,male 403 | xqd20160402,COLLECTION_PAIDOFF,1000,15,9/9/2016,9/23/2016,9/27/2016 17:00,4,28,college,male 404 | xqd20320403,COLLECTION_PAIDOFF,1000,30,9/9/2016,11/7/2016,11/20/2016 14:10,13,39,college,male 405 | xqd20160404,COLLECTION_PAIDOFF,1000,15,9/9/2016,9/23/2016,9/28/2016 15:38,5,29,Bechalor,male 406 | xqd20190405,COLLECTION_PAIDOFF,800,15,9/9/2016,9/23/2016,9/26/2016 17:22,3,33,High School or Below,male 407 | xqd20160406,COLLECTION_PAIDOFF,1000,30,9/10/2016,10/9/2016,10/21/2016 14:00,12,27,college,male 408 | xqd20160407,COLLECTION_PAIDOFF,800,15,9/10/2016,9/24/2016,9/26/2016 11:03,2,34,college,male 409 | xqd20160408,COLLECTION_PAIDOFF,1000,30,9/10/2016,10/9/2016,11/5/2016 15:39,27,26,High School or Below,male 410 | xqd20110409,COLLECTION_PAIDOFF,1000,30,9/10/2016,10/9/2016,11/22/2016 15:53,44,28,High School or Below,male 411 | xqd20160410,COLLECTION_PAIDOFF,1000,15,9/10/2016,9/24/2016,9/29/2016 10:30,5,32,Bechalor,male 412 | xqd20160411,COLLECTION_PAIDOFF,800,15,9/10/2016,10/9/2016,10/10/2016 15:18,1,27,college,female 413 | xqd20160412,COLLECTION_PAIDOFF,1000,30,9/10/2016,10/9/2016,11/5/2016 10:49,27,21,college,male 414 | xqd20160413,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/27/2016 17:10,2,39,college,male 415 | xqd20169083,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/26/2016 11:35,1,38,college,male 416 | xqd20160415,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/12/2016 9:59,2,36,High School or Below,female 417 | xqd20160416,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/27/2016 17:14,2,33,college,male 418 | xqd20160417,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 12:45,1,21,college,female 419 | xqd20160418,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/28/2016 11:38,3,25,High School or Below,male 420 | xqd20160419,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,10/7/2016 13:21,12,29,college,male 421 | xqd20160420,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/4/2016 15:37,25,33,High School or Below,male 422 | xqd20160421,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/28/2016 17:39,3,47,High School or Below,female 423 | xqd20160422,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/12/2016 9:52,2,33,college,male 424 | xqd20160423,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/29/2016 15:12,4,23,High School or Below,male 425 | xqd20160424,COLLECTION_PAIDOFF,1000,15,9/11/2016,10/10/2016,10/12/2016 11:17,2,24,college,male 426 | xqd20880425,COLLECTION_PAIDOFF,1000,30,9/11/2016,11/9/2016,11/10/2016 22:58,1,27,High School or Below,male 427 | xqd20160426,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/3/2016 15:23,24,32,Bechalor,male 428 | xqd20160427,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 16:44,1,33,college,male 429 | xqd20160428,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 11:02,2,27,college,female 430 | xqd20160429,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/12/2016 13:17,2,35,High School or Below,male 431 | xqd20160430,COLLECTION_PAIDOFF,500,15,9/11/2016,10/10/2016,10/11/2016 17:22,1,37,Bechalor,male 432 | xqd20160431,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/28/2016 14:02,3,28,Bechalor,male 433 | xqd20160432,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/29/2016 13:42,4,33,college,male 434 | xqd20160433,COLLECTION_PAIDOFF,800,7,9/11/2016,9/17/2016,9/19/2016 15:00,2,34,Bechalor,female 435 | xqd20160434,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/12/2016 14:32,2,29,college,male 436 | xqd20160435,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 11:33,1,34,Bechalor,male 437 | xqd20160436,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 16:27,1,29,Bechalor,male 438 | xqd20790437,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/15/2016 15:27,36,24,High School or Below,male 439 | xqd20160438,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 16:13,1,34,High School or Below,male 440 | xqd20160439,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/17/2016 10:06,7,25,college,female 441 | xqd20160440,COLLECTION_PAIDOFF,1000,30,9/11/2016,11/9/2016,11/14/2016 13:15,5,24,college,male 442 | xqd20160441,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/24/2016 16:20,14,30,college,male 443 | xqd20160442,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/27/2016 16:35,2,28,college,male 444 | xqd20160443,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 11:48,1,24,High School or Below,male 445 | xqd20160444,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/7/2016 19:21,28,26,college,female 446 | xqd20160445,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/12/2016 16:22,2,24,High School or Below,male 447 | xqd20160446,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/27/2016 17:24,2,29,college,male 448 | xqd20420447,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/4/2016 11:07,25,31,college,male 449 | xqd20160448,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,11/2/2016 9:39,23,26,college,male 450 | xqd20160449,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/13/2016 18:18,3,25,High School or Below,male 451 | xqd20160450,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/11/2016 11:29,1,29,college,male 452 | xqd20160451,COLLECTION_PAIDOFF,1000,30,9/11/2016,10/10/2016,10/13/2016 16:27,3,38,college,male 453 | xqd20160452,COLLECTION_PAIDOFF,800,15,9/11/2016,9/25/2016,9/29/2016 11:19,4,41,college,male 454 | xqd20390453,COLLECTION_PAIDOFF,1000,15,9/11/2016,9/25/2016,9/28/2016 11:17,3,26,High School or Below,male 455 | xqd20160454,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/14/2016 11:04,3,26,High School or Below,male 456 | xqd20160455,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/17/2016 17:40,6,35,High School or Below,male 457 | xqd20160456,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,9/28/2016 9:42,2,37,college,male 458 | xqd20160457,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,11/18/2016 15:52,38,25,college,male 459 | xqd20160458,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/30/2016 14:19,19,24,college,male 460 | xqd20160459,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/13/2016 15:10,2,34,college,male 461 | xqd20160460,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,9/28/2016 13:36,2,33,college,male 462 | xqd20490461,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,9/28/2016 15:34,2,38,Bechalor,male 463 | xqd20160462,COLLECTION_PAIDOFF,1000,30,9/12/2016,11/10/2016,11/17/2016 11:55,7,38,High School or Below,male 464 | xqd20160463,COLLECTION_PAIDOFF,1000,30,9/12/2016,11/10/2016,11/15/2016 18:51,5,26,college,male 465 | xqd20870464,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,9/30/2016 10:23,4,37,Bechalor,male 466 | xqd20160465,COLLECTION_PAIDOFF,1000,30,9/12/2016,11/10/2016,11/11/2016 17:17,1,42,High School or Below,female 467 | xqd20169466,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/12/2016 12:54,1,49,High School or Below,female 468 | xqd20160467,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/15/2016 9:48,4,26,High School or Below,male 469 | xqd20160468,COLLECTION_PAIDOFF,1000,15,9/12/2016,10/26/2016,10/27/2016 11:14,1,41,High School or Below,male 470 | xqd20160469,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/15/2016 14:14,4,38,High School or Below,male 471 | xqd25660470,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,12/2/2016 9:45,52,26,High School or Below,male 472 | xqd20160471,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,9/28/2016 15:02,2,32,High School or Below,male 473 | xqd20160472,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,11/4/2016 14:46,24,27,Bechalor,male 474 | xqd20160473,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,11/16/2016 12:12,51,33,college,male 475 | xqd20160474,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/14/2016 19:02,3,30,High School or Below,male 476 | xqd20160475,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,9/28/2016 11:34,2,26,High School or Below,female 477 | xqd20160476,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,11/9/2016 18:12,29,35,college,female 478 | xqd20160477,COLLECTION_PAIDOFF,800,15,9/12/2016,10/26/2016,10/31/2016 13:07,5,46,college,female 479 | xqd20160478,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/20/2016 17:38,9,27,college,male 480 | xqd20160479,COLLECTION_PAIDOFF,1000,15,9/12/2016,10/11/2016,11/7/2016 8:55,27,22,High School or Below,male 481 | xqd20160480,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/12/2016 18:26,1,27,Bechalor,male 482 | xqd20160481,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,10/25/2016 13:44,29,30,Bechalor,male 483 | xqd20160482,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,9/29/2016 15:07,3,27,High School or Below,male 484 | xqd20160483,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,9/27/2016 11:40,1,47,college,male 485 | xqd20160484,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/18/2016 19:08,7,30,college,male 486 | xqd20160485,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/15/2016 9:23,4,26,college,male 487 | xqd20160486,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/14/2016 10:07,3,38,High School or Below,male 488 | xqd20160487,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,11/21/2016 11:36,56,46,High School or Below,male 489 | xqd20160488,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/13/2016 12:02,2,35,Bechalor,male 490 | xqd20160489,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,10/9/2016 19:30,13,45,college,male 491 | xqd20160490,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/12/2016 18:04,1,36,college,male 492 | xqd20160491,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/17/2016 10:53,6,38,High School or Below,male 493 | xqd20160492,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,11/9/2016 13:41,29,27,college,male 494 | xqd20160493,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/25/2016 17:44,14,27,Bechalor,male 495 | xqd20160494,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,9/29/2016 12:45,3,29,college,male 496 | xqd20160495,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/13/2016 14:45,2,30,High School or Below,male 497 | xqd20160496,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/14/2016 19:08,3,28,High School or Below,male 498 | xqd20160497,COLLECTION_PAIDOFF,1000,15,9/12/2016,9/26/2016,10/10/2016 20:02,14,26,High School or Below,male 499 | xqd20160498,COLLECTION_PAIDOFF,800,15,9/12/2016,9/26/2016,9/29/2016 11:49,3,30,college,male 500 | xqd20160499,COLLECTION_PAIDOFF,1000,30,9/12/2016,11/10/2016,11/11/2016 22:40,1,38,college,female 501 | xqd20160500,COLLECTION_PAIDOFF,1000,30,9/12/2016,10/11/2016,10/19/2016 11:58,8,28,High School or Below,male 502 | -------------------------------------------------------------------------------- /examples/data/sample_dataframe.py: -------------------------------------------------------------------------------- 1 | """Sample data for dataframe examples.""" 2 | 3 | dataframe = { 4 | "country": [ 5 | "United States", 6 | "United Kingdom", 7 | "France", 8 | "Germany", 9 | "Italy", 10 | "Spain", 11 | "Canada", 12 | "Australia", 13 | "Japan", 14 | "China", 15 | ], 16 | "gdp": [ 17 | 21400000, 18 | 2940000, 19 | 2830000, 20 | 3870000, 21 | 2160000, 22 | 1350000, 23 | 1780000, 24 | 1320000, 25 | 516000, 26 | 14000000, 27 | ], 28 | "happiness_index": [7.3, 7.2, 6.5, 7.0, 6.0, 6.3, 7.3, 7.3, 5.9, 5.0], 29 | } 30 | -------------------------------------------------------------------------------- /examples/from_csv.py: -------------------------------------------------------------------------------- 1 | """Example of using PandasAI with a CSV file.""" 2 | 3 | import pandas as pd 4 | from pandasai import PandasAI 5 | from pandasai.llm.openai import OpenAI 6 | 7 | df = pd.read_csv("data/Loan payments data.csv") 8 | 9 | llm = OpenAI() 10 | pandas_ai = PandasAI(llm, verbose=True) 11 | response = pandas_ai.run(df, "How many loans are from men and have been paid off?") 12 | print(response) 13 | # Output: 247 loans have been paid off by men. 14 | -------------------------------------------------------------------------------- /examples/from_dataframe.py: -------------------------------------------------------------------------------- 1 | """Example of using PandasAI with a Pandas DataFrame""" 2 | 3 | from data.sample_dataframe import dataframe 4 | import pandas as pd 5 | from pandasai import PandasAI 6 | from pandasai.llm.openai import OpenAI 7 | 8 | df = pd.DataFrame(dataframe) 9 | 10 | llm = OpenAI() 11 | pandas_ai = PandasAI(llm, verbose=True, conversational=False) 12 | response = pandas_ai.run(df, "Calculate the sum of the gdp of north american countries") 13 | print(response) 14 | # Output: 26200000 15 | -------------------------------------------------------------------------------- /examples/show_chart.py: -------------------------------------------------------------------------------- 1 | """Example of using PandasAI to generate a chart from a Pandas DataFrame""" 2 | 3 | from data.sample_dataframe import dataframe 4 | import pandas as pd 5 | from pandasai import PandasAI 6 | from pandasai.llm.openai import OpenAI 7 | 8 | df = pd.DataFrame(dataframe) 9 | 10 | llm = OpenAI() 11 | pandas_ai = PandasAI(llm) 12 | response = pandas_ai.run( 13 | df, 14 | "Plot the histogram of countries showing for each the gpd, using different colors for each bar", 15 | ) 16 | print(response) 17 | # Output: check out images/histogram-chart.png 18 | -------------------------------------------------------------------------------- /examples/with_privacy_enforced.py: -------------------------------------------------------------------------------- 1 | """Example of using PandasAI with a Pandas DataFrame""" 2 | 3 | from data.sample_dataframe import dataframe 4 | import pandas as pd 5 | from pandasai import PandasAI 6 | from pandasai.llm.openai import OpenAI 7 | 8 | df = pd.DataFrame(dataframe) 9 | 10 | llm = OpenAI() 11 | pandas_ai = PandasAI(llm, verbose=True, conversational=False, enforce_privacy=True) 12 | response = pandas_ai.run( 13 | df, 14 | "Calculate the sum of the gdp of north american countries", 15 | ) 16 | print(response) 17 | # Output: 26200000 18 | -------------------------------------------------------------------------------- /images/histogram-chart.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysbrianlee/pandasai/c566bebd664de3e208e89f9646fa794df240cddf/images/histogram-chart.png -------------------------------------------------------------------------------- /images/pandas-ai.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysbrianlee/pandasai/c566bebd664de3e208e89f9646fa794df240cddf/images/pandas-ai.png -------------------------------------------------------------------------------- /pandasai/__init__.py: -------------------------------------------------------------------------------- 1 | """ PandasAI is a wrapper around a LLM to make dataframes convesational """ 2 | import io 3 | import sys 4 | import pandas as pd 5 | from .llm.base import LLM 6 | from .helpers.notebook import Notebook 7 | from .exceptions import LLMNotFoundError 8 | 9 | 10 | class PandasAI: 11 | """PandasAI is a wrapper around a LLM to make dataframes convesational""" 12 | 13 | _task_instruction: str = """ 14 | There is a dataframe in pandas (python). 15 | The name of the dataframe is `df`. 16 | This is the result of `print(df.head({rows_to_display}))`: 17 | {df_head}. 18 | 19 | Return the python code (do not import anything) and make sure to prefix the python code with exactly and suffix the code with exactly 20 | to get the answer to the following question : 21 | """ 22 | _response_instruction: str = """ 23 | Question: {question} 24 | Answer: {answer} 25 | 26 | Rewrite the answer to the question in a conversational way. 27 | """ 28 | 29 | _error_correct_instruction: str = """ 30 | For the task defined below: 31 | {orig_task} 32 | you generated this python code: 33 | {code} 34 | and this fails with the following error: 35 | {error_returned} 36 | Correct the python code and return a new python code (do not import anything) that fixes the above mentioned error. 37 | Make sure to prefix the python code with exactly and suffix the code with exactly. 38 | """ 39 | _llm: LLM 40 | _verbose: bool = False 41 | _is_conversational_answer: bool = True 42 | _enforce_privacy: bool = False 43 | _max_retries: int = 3 44 | _original_instruction_and_prompt = None 45 | _is_notebook: bool = False 46 | last_code_generated: str = None 47 | code_output: str = None 48 | 49 | def __init__( 50 | self, 51 | llm=None, 52 | conversational=True, 53 | verbose=False, 54 | enforce_privacy=False, 55 | ): 56 | if llm is None: 57 | raise LLMNotFoundError( 58 | "An LLM should be provided to instantiate a PandasAI instance" 59 | ) 60 | self._llm = llm 61 | self._is_conversational_answer = conversational 62 | self._verbose = verbose 63 | self._enforce_privacy = enforce_privacy 64 | 65 | self.notebook = Notebook() 66 | self._in_notebook = self.notebook.in_notebook() 67 | 68 | def conversational_answer(self, question: str, code: str, answer: str) -> str: 69 | """Return the conversational answer""" 70 | if self._enforce_privacy: 71 | # we don't want to send potentially sensitive data to the LLM server 72 | # if the user has set enforce_privacy to True 73 | return answer 74 | 75 | instruction = self._response_instruction.format( 76 | question=question, code=code, answer=answer 77 | ) 78 | return self._llm.call(instruction, "") 79 | 80 | def run( 81 | self, 82 | data_frame: pd.DataFrame, 83 | prompt: str, 84 | is_conversational_answer: bool = None, 85 | show_code: bool = False, 86 | ) -> str: 87 | """Run the LLM with the given prompt""" 88 | self.log(f"Running PandasAI with {self._llm.type} LLM...") 89 | 90 | rows_to_display = 5 91 | if self._enforce_privacy: 92 | rows_to_display = 0 93 | 94 | code = self._llm.generate_code( 95 | self._task_instruction.format( 96 | df_head=data_frame.head(rows_to_display), 97 | rows_to_display=rows_to_display, 98 | ), 99 | prompt, 100 | ) 101 | self._original_instruction_and_prompt = ( 102 | self._task_instruction.format( 103 | df_head=data_frame.head(rows_to_display), 104 | rows_to_display=rows_to_display, 105 | ) 106 | + prompt 107 | ) 108 | self.last_code_generated = code 109 | self.log( 110 | f""" 111 | Code generated: 112 | ``` 113 | {code} 114 | ```""" 115 | ) 116 | if show_code and self._in_notebook: 117 | self.notebook.create_new_cell(code) 118 | 119 | answer = self.run_code(code, data_frame, False) 120 | self.code_output = answer 121 | self.log(f"Answer: {answer}") 122 | 123 | if is_conversational_answer is None: 124 | is_conversational_answer = self._is_conversational_answer 125 | if is_conversational_answer: 126 | answer = self.conversational_answer(prompt, code, answer) 127 | self.log(f"Conversational answer: {answer}") 128 | return answer 129 | 130 | def run_code( 131 | self, 132 | code: str, 133 | df: pd.DataFrame, # pylint: disable=W0613 disable=C0103 134 | use_error_correction_framework: bool = False, 135 | ) -> str: 136 | # pylint: disable=W0122 disable=W0123 disable=W0702:bare-except 137 | """Run the code in the current context and return the result""" 138 | 139 | # Redirect standard output to a StringIO buffer 140 | output = io.StringIO() 141 | sys.stdout = output 142 | 143 | # Execute the code 144 | if use_error_correction_framework: 145 | count = 0 146 | code_to_run = code 147 | while count < self._max_retries: 148 | try: 149 | exec(code_to_run) 150 | code = code_to_run 151 | break 152 | except Exception as e: # pylint: disable=W0718 disable=C0103 153 | count += 1 154 | error_correcting_instruction = ( 155 | self._error_correct_instruction.format( 156 | orig_task=self._original_instruction_and_prompt, 157 | code=code, 158 | error_returned=e, 159 | ) 160 | ) 161 | code_to_run = self._llm.generate_code( 162 | error_correcting_instruction, "" 163 | ) 164 | else: 165 | exec(code) 166 | 167 | # Restore standard output and get the captured output 168 | sys.stdout = sys.__stdout__ 169 | captured_output = output.getvalue() 170 | 171 | # Evaluate the last line and return its value or the captured output 172 | lines = code.strip().split("\n") 173 | last_line = lines[-1].strip() 174 | if last_line.startswith("print(") and last_line.endswith(")"): 175 | # Last line is already printing 176 | return eval(last_line[6:-1]) 177 | # Evaluate last line and return its value or the captured output 178 | try: 179 | result = eval(last_line) 180 | return result 181 | except: 182 | return captured_output 183 | 184 | def log(self, message: str): 185 | """Log a message""" 186 | if self._verbose: 187 | print(message) 188 | -------------------------------------------------------------------------------- /pandasai/exceptions.py: -------------------------------------------------------------------------------- 1 | """PandasAI's custom exceptions.""" 2 | 3 | 4 | class APIKeyNotFoundError(Exception): 5 | """ 6 | Raised when the API key is not defined/declared. 7 | 8 | Args: 9 | Exception (Exception): APIKeyNotFoundError 10 | """ 11 | 12 | 13 | class LLMNotFoundError(Exception): 14 | """ 15 | Raised when the LLM is not provided. 16 | 17 | Args: 18 | Exception (Exception): LLMNotFoundError 19 | """ 20 | 21 | 22 | class NoCodeFoundError(Exception): 23 | """ 24 | Raised when no code is found in the response. 25 | 26 | Args: 27 | Exception (Exception): NoCodeFoundError 28 | """ 29 | 30 | 31 | class MethodNotImplementedError(Exception): 32 | """ 33 | Raised when a method is not implemented. 34 | 35 | Args: 36 | Exception (Exception): MethodNotImplementedError 37 | """ 38 | 39 | 40 | class UnsupportedOpenAIModelError(Exception): 41 | """ 42 | Raised when an unsupported OpenAI model is used. 43 | 44 | Args: 45 | Exception (Exception): UnsupportedOpenAIModelError 46 | """ 47 | -------------------------------------------------------------------------------- /pandasai/helpers/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysbrianlee/pandasai/c566bebd664de3e208e89f9646fa794df240cddf/pandasai/helpers/__init__.py -------------------------------------------------------------------------------- /pandasai/helpers/notebook.py: -------------------------------------------------------------------------------- 1 | """ Notebook helper functions """ 2 | 3 | from IPython import get_ipython 4 | 5 | 6 | class Notebook: 7 | 8 | """Baseclass to implement Notebook helper functions""" 9 | 10 | def in_notebook(self) -> bool: 11 | """ 12 | Checks whether the code is running inside a notebook environment. 13 | 14 | Returns: 15 | bool: True if the code is running inside a Jupyter notebook, False otherwise. 16 | """ 17 | try: 18 | if "IPKernelApp" not in get_ipython().config: 19 | return False 20 | except ImportError: 21 | return False 22 | except AttributeError: 23 | return False 24 | return True 25 | 26 | def create_new_cell(self, contents: str) -> None: 27 | """ 28 | Creates a new code cell in the Jupyter notebook and populates it with the specified 29 | contents. 30 | 31 | Parameters: 32 | ----------- 33 | contents : str 34 | The contents to be added to the new code cell. 35 | 36 | Raises: 37 | ------- 38 | ImportError: 39 | If the IPython module is not installed. 40 | 41 | AttributeError: 42 | If the 'get_ipython()' call raises an AttributeError, which can happen if the code is 43 | not running inside a Jupyter notebook. 44 | 45 | Returns: 46 | None 47 | """ 48 | payload = {"source": "set_next_input", "text": contents, "replace": False} 49 | try: 50 | get_ipython().payload_manager.write_payload(payload, single=False) 51 | except (ImportError, AttributeError) as exception: 52 | raise exception 53 | -------------------------------------------------------------------------------- /pandasai/llm/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/ysbrianlee/pandasai/c566bebd664de3e208e89f9646fa794df240cddf/pandasai/llm/__init__.py -------------------------------------------------------------------------------- /pandasai/llm/base.py: -------------------------------------------------------------------------------- 1 | """ Base class to implement a new LLM. """ 2 | 3 | import re 4 | import ast 5 | import astor 6 | from ..exceptions import ( 7 | APIKeyNotFoundError, 8 | NoCodeFoundError, 9 | MethodNotImplementedError, 10 | ) 11 | 12 | 13 | class LLM: 14 | """Base class to implement a new LLM.""" 15 | 16 | last_prompt: str = None 17 | 18 | @property 19 | def type(self) -> str: 20 | """ 21 | Return type of LLM. 22 | 23 | Raises: 24 | APIKeyNotFoundError: Type has not been implemented 25 | 26 | Returns: 27 | str: Type of LLM a string 28 | """ 29 | raise APIKeyNotFoundError("Type has not been implemented") 30 | 31 | def _remove_imports(self, code: str) -> str: 32 | tree = ast.parse(code) 33 | new_body = [] 34 | 35 | for node in tree.body: 36 | if not isinstance(node, (ast.Import, ast.ImportFrom)): 37 | new_body.append(node) 38 | 39 | new_tree = ast.Module(body=new_body) 40 | return astor.to_source(new_tree) 41 | 42 | def _polish_code(self, code: str) -> str: 43 | """ 44 | Polish the code by removing the leading "python" or "py", \ 45 | removing the imports and removing trailing spaces and new lines. 46 | 47 | Args: 48 | code (str): Code 49 | 50 | Returns: 51 | str: Polished code 52 | """ 53 | if re.match(r"^(python|py)", code): 54 | code = re.sub(r"^(python|py)", "", code) 55 | if re.match(r"^`.*`$", code): 56 | code = re.sub(r"^`(.*)`$", r"\1", code) 57 | self._remove_imports(code) 58 | code = code.strip() 59 | return code 60 | 61 | def _is_python_code(self, string): 62 | try: 63 | ast.parse(string) 64 | return True 65 | except SyntaxError: 66 | return False 67 | 68 | def _extract_code(self, response: str, separator: str = "```") -> str: 69 | """ 70 | Extract the code from the response. 71 | 72 | Args: 73 | response (str): Response 74 | separator (str, optional): Separator. Defaults to "```". 75 | 76 | Raises: 77 | NoCodeFoundError: No code found in the response 78 | 79 | Returns: 80 | str: Extracted code from the response 81 | """ 82 | code = response 83 | if len(response.split(separator)) > 1: 84 | code = response.split(separator)[1] 85 | if re.match(r"([\s\S]*?)<\/?endCode>", code): 86 | code = re.findall(r"([\s\S]*?)<\/?endCode>", code)[0] 87 | code = self._polish_code(code) 88 | if not self._is_python_code(code): 89 | raise NoCodeFoundError("No code found in the response") 90 | 91 | return code 92 | 93 | def call(self, instruction: str, value: str) -> None: 94 | """ 95 | Execute the LLM with given prompt. 96 | 97 | Args: 98 | instruction (str): Prompt 99 | value (str): Value 100 | 101 | Raises: 102 | MethodNotImplementedError: Call method has not been implemented 103 | """ 104 | raise MethodNotImplementedError("Call method has not been implemented") 105 | 106 | def generate_code(self, instruction: str, prompt: str) -> str: 107 | """ 108 | Generate the code based on the instruction and the given prompt. 109 | 110 | Returns: 111 | str: Code 112 | """ 113 | return self._extract_code(self.call(instruction, prompt)) 114 | -------------------------------------------------------------------------------- /pandasai/llm/fake.py: -------------------------------------------------------------------------------- 1 | """Fake LLM""" 2 | 3 | from .base import LLM 4 | 5 | 6 | class FakeLLM(LLM): 7 | """Fake LLM""" 8 | 9 | _output: str = 'print("Hello world")' 10 | 11 | def __init__(self, output: str = None): 12 | if output is not None: 13 | self._output = output 14 | 15 | def call(self, instruction: str, value: str) -> str: 16 | self.last_prompt = str(instruction) + str(value) 17 | return self._output 18 | 19 | @property 20 | def type(self) -> str: 21 | return "fake" 22 | -------------------------------------------------------------------------------- /pandasai/llm/open_assistant.py: -------------------------------------------------------------------------------- 1 | """ Open Assistant LLM """ 2 | 3 | import os 4 | import requests 5 | from dotenv import load_dotenv 6 | from .base import LLM 7 | from ..exceptions import APIKeyNotFoundError 8 | 9 | load_dotenv() 10 | 11 | 12 | class OpenAssistant(LLM): 13 | """Open Assistant LLM""" 14 | 15 | api_token: str 16 | _api_url: str = ( 17 | "https://api-inference.huggingface.co/models/" 18 | "OpenAssistant/oasst-sft-1-pythia-12b" 19 | ) 20 | 21 | def __init__(self, api_token: str = None): 22 | self.api_token = api_token or os.getenv("HUGGINGFACE_API_KEY") 23 | if self.api_token is None: 24 | raise APIKeyNotFoundError("HuggingFace Hub API key is required") 25 | 26 | def query(self, payload): 27 | """Query the API""" 28 | 29 | headers = {"Authorization": f"Bearer {self.api_token}"} 30 | 31 | response = requests.post( 32 | self._api_url, headers=headers, json=payload, timeout=60 33 | ) 34 | return response.json() 35 | 36 | def call(self, instruction: str, value: str) -> str: 37 | output = self.query( 38 | {"inputs": "<|prompter|>" + instruction + value + "<|endoftext|>"} 39 | ) 40 | return output[0]["generated_text"] 41 | 42 | @property 43 | def type(self) -> str: 44 | return "open-assistant" 45 | -------------------------------------------------------------------------------- /pandasai/llm/openai.py: -------------------------------------------------------------------------------- 1 | """OpenAI LLM""" 2 | 3 | import os 4 | from dotenv import load_dotenv 5 | import openai 6 | from .base import LLM 7 | from ..exceptions import APIKeyNotFoundError, UnsupportedOpenAIModelError 8 | 9 | load_dotenv() 10 | 11 | 12 | class OpenAI(LLM): 13 | """OpenAI LLM""" 14 | 15 | _supported_chat_models = [ 16 | "gpt-4", 17 | "gpt-4-0314", 18 | "gpt-4-32k", 19 | "gpt-4-32k-0314", 20 | "gpt-3.5-turbo", 21 | "gpt-3.5-turbo-0301", 22 | ] 23 | _supported_completion_models = ["text-davinci-003"] 24 | 25 | api_token: str 26 | model: str = "gpt-3.5-turbo" 27 | temperature: float = 0 28 | max_tokens: int = 512 29 | top_p: float = 1 30 | frequency_penalty: float = 0 31 | presence_penalty: float = 0.6 32 | stop: str = None 33 | 34 | def __init__( 35 | self, 36 | api_token: str = None, 37 | **kwargs, 38 | ): 39 | self.api_token = api_token or os.getenv("OPENAI_API_KEY") 40 | if self.api_token is None: 41 | raise APIKeyNotFoundError("OpenAI API key is required") 42 | openai.api_key = self.api_token 43 | 44 | self._set_params(**kwargs) 45 | 46 | def _set_params(self, **kwargs): 47 | valid_params = [ 48 | "model", 49 | "temperature", 50 | "max_tokens", 51 | "top_p", 52 | "frequency_penalty", 53 | "presence_penalty", 54 | "stop", 55 | ] 56 | for key, value in kwargs.items(): 57 | if key in valid_params: 58 | setattr(self, key, value) 59 | 60 | def completion(self, prompt: str) -> str: 61 | """ 62 | Query the completation API 63 | 64 | Args: 65 | prompt (str): Prompt 66 | 67 | Returns: 68 | str: LLM response 69 | """ 70 | params = { 71 | "model": self.model, 72 | "prompt": prompt, 73 | "temperature": self.temperature, 74 | "max_tokens": self.max_tokens, 75 | "top_p": self.top_p, 76 | "frequency_penalty": self.frequency_penalty, 77 | "presence_penalty": self.presence_penalty, 78 | } 79 | 80 | if self.stop is not None: 81 | params["stop"] = [self.stop] 82 | 83 | response = openai.Completion.create(**params) 84 | 85 | return response["choices"][0]["text"] 86 | 87 | def chat_completion(self, value: str) -> str: 88 | """ 89 | Query the chat completion API 90 | 91 | Args: 92 | value (str): Prompt 93 | 94 | Returns: 95 | str: LLM response 96 | """ 97 | params = { 98 | "model": self.model, 99 | "temperature": self.temperature, 100 | "max_tokens": self.max_tokens, 101 | "top_p": self.top_p, 102 | "frequency_penalty": self.frequency_penalty, 103 | "presence_penalty": self.presence_penalty, 104 | "messages": [ 105 | { 106 | "role": "system", 107 | "content": value, 108 | } 109 | ], 110 | } 111 | 112 | if self.stop is not None: 113 | params["stop"] = [self.stop] 114 | 115 | response = openai.ChatCompletion.create(**params) 116 | 117 | return response["choices"][0]["message"]["content"] 118 | 119 | def call(self, instruction: str, value: str) -> str: 120 | """ 121 | Call the OpenAI LLM. 122 | 123 | Args: 124 | instruction (str): Instruction to pass 125 | value (str): Value to pass 126 | 127 | Raises: 128 | UnsupportedOpenAIModelError: Unsupported model 129 | 130 | Returns: 131 | str: Response 132 | """ 133 | self.last_prompt = str(instruction) + str(value) 134 | 135 | if self.model in self._supported_completion_models: 136 | response = self.completion(str(instruction) + str(value)) 137 | elif self.model in self._supported_chat_models: 138 | response = self.chat_completion(str(instruction) + str(value)) 139 | else: 140 | raise UnsupportedOpenAIModelError("Unsupported model") 141 | 142 | return response 143 | 144 | @property 145 | def type(self) -> str: 146 | return "openai" 147 | -------------------------------------------------------------------------------- /poetry.toml: -------------------------------------------------------------------------------- 1 | [virtualenvs] 2 | in-project = true 3 | path = "." -------------------------------------------------------------------------------- /pyproject.toml: -------------------------------------------------------------------------------- 1 | [tool.poetry] 2 | name = "pandasai" 3 | version = "0.2.2" 4 | description = "Pandas AI is a Python library that integrates generative artificial intelligence capabilities into Pandas, making dataframes conversational." 5 | authors = ["Gabriele Venturi"] 6 | license = "MIT" 7 | readme = "README.md" 8 | packages = [{include = "pandasai"}] 9 | 10 | [tool.poetry.dependencies] 11 | python = "^3.9" 12 | python-dotenv = "^1.0.0" 13 | pandas = "^2.0.1" 14 | astor = "^0.8.1" 15 | openai = "^0.27.5" 16 | ipython = "^8.13.1" 17 | matplotlib = "^3.7.1" 18 | 19 | 20 | [tool.poetry.group.dev.dependencies] 21 | black = "^23.3.0" 22 | pre-commit = "^3.2.2" 23 | pylint = "^2.17.3" 24 | pytest = "^7.3.1" 25 | 26 | [build-system] 27 | requires = ["poetry-core"] 28 | build-backend = "poetry.core.masonry.api" 29 | -------------------------------------------------------------------------------- /tests/__init_.py: -------------------------------------------------------------------------------- 1 | """All the tests""" 2 | -------------------------------------------------------------------------------- /tests/llms/__init_.py: -------------------------------------------------------------------------------- 1 | """The LLMs tests""" 2 | -------------------------------------------------------------------------------- /tests/test_pandasai.py: -------------------------------------------------------------------------------- 1 | """Unit tests for the PandasAI class""" 2 | 3 | import unittest 4 | from unittest.mock import patch, Mock 5 | 6 | import pandas as pd 7 | from pandasai import PandasAI 8 | from pandasai.llm.fake import FakeLLM 9 | from pandasai.exceptions import LLMNotFoundError 10 | 11 | 12 | class TestPandasAI(unittest.TestCase): 13 | """Unit tests for the PandasAI class""" 14 | 15 | llm: FakeLLM 16 | pandasai: PandasAI 17 | 18 | def setup(self, output: str = None): 19 | self.llm = FakeLLM(output=output) 20 | self.pandasai = PandasAI(self.llm) 21 | 22 | def test_init(self): 23 | self.setup() 24 | self.assertEqual(self.pandasai._llm, self.llm) 25 | self.assertEqual(self.pandasai._is_conversational_answer, True) 26 | self.assertEqual(self.pandasai._verbose, False) 27 | 28 | def test_init_with_llm(self): 29 | self.setup() 30 | self.assertEqual(self.pandasai._llm, self.llm) 31 | self.assertEqual(self.pandasai._is_conversational_answer, True) 32 | self.assertEqual(self.pandasai._verbose, False) 33 | 34 | def test_init_without_llm(self): 35 | with self.assertRaises(LLMNotFoundError): 36 | PandasAI() 37 | 38 | def test_conversational_answer(self): 39 | result = "2" 40 | self.setup(result) 41 | self.assertEqual( 42 | self.pandasai.conversational_answer( 43 | "What is the sum of 1 + 1?", "1 + 1", 2 44 | ), 45 | result, 46 | ) 47 | 48 | def test_run(self): 49 | df = pd.DataFrame() 50 | self.setup(output="1") 51 | self.assertEqual(self.pandasai.run(df, "What number comes before 2?"), "1") 52 | 53 | def test_run_with_conversational_answer(self): 54 | df = pd.DataFrame() 55 | self.setup(output="1 + 1") 56 | self.assertEqual( 57 | self.pandasai.run( 58 | df, "What is the sum of 1 + 1?", is_conversational_answer=True 59 | ), 60 | "1 + 1", 61 | ) 62 | 63 | def test_run_with_non_conversational_answer(self): 64 | df = pd.DataFrame() 65 | self.setup(output="1 + 1") 66 | self.assertEqual( 67 | self.pandasai.run( 68 | df, "What is the sum of 1 + 1?", is_conversational_answer=False 69 | ), 70 | 2, 71 | ) 72 | 73 | def test_run_with_verbose(self): 74 | df = pd.DataFrame() 75 | self.setup(output="1") 76 | self.pandasai._verbose = True 77 | 78 | # mock print function 79 | with patch("builtins.print") as mock_print: 80 | self.pandasai.run(df, "What number comes before 2?") 81 | mock_print.assert_called() 82 | 83 | def test_run_without_verbose(self): 84 | df = pd.DataFrame() 85 | self.setup(output="1") 86 | self.pandasai._verbose = False 87 | 88 | # mock print function 89 | with patch("builtins.print") as mock_print: 90 | self.pandasai.run(df, "What number comes before 2?") 91 | mock_print.assert_not_called() 92 | 93 | def test_run_code(self): 94 | df = pd.DataFrame() 95 | self.setup() 96 | self.assertEqual(self.pandasai.run_code("1 + 1", df), 2) 97 | 98 | def test_run_code_invalid_code(self): 99 | df = pd.DataFrame() 100 | self.setup() 101 | with self.assertRaises(Exception): 102 | self.pandasai.run_code("1 +", df) 103 | 104 | def test_run_code_with_print(self): 105 | df = pd.DataFrame() 106 | self.setup() 107 | self.assertEqual(self.pandasai.run_code("print(1 + 1)", df), 2) 108 | 109 | def test_conversational_answer_with_privacy_enforcement(self): 110 | self.setup() 111 | self.pandasai._enforce_privacy = True 112 | self.pandasai._llm.call = Mock(return_value="The answer is 2") 113 | self.assertEqual( 114 | self.pandasai.conversational_answer("How much does 1 + 1 do?", "", 2), 2 115 | ) 116 | self.pandasai._llm.call.assert_not_called() 117 | 118 | def test_conversational_answer_without_privacy_enforcement(self): 119 | self.setup() 120 | self.pandasai._enforce_privacy = False 121 | self.pandasai._llm.call = Mock(return_value="The answer is 2") 122 | self.assertEqual( 123 | self.pandasai.conversational_answer("How much does 1 + 1 do?", "", 2), 124 | "The answer is 2", 125 | ) 126 | self.pandasai._llm.call.assert_called() 127 | 128 | def test_run_with_privacy_enforcement(self): 129 | df = pd.DataFrame({"country": ["United States", "United Kingdom", "France"]}) 130 | self.setup() 131 | self.pandasai._enforce_privacy = True 132 | self.pandasai._is_conversational_answer = True 133 | 134 | expected_prompt = """ 135 | There is a dataframe in pandas (python). 136 | The name of the dataframe is `df`. 137 | This is the result of `print(df.head(0))`: 138 | Empty DataFrame 139 | Columns: [country] 140 | Index: []. 141 | 142 | Return the python code (do not import anything) and make sure to prefix the python code with exactly and suffix the code with exactly 143 | to get the answer to the following question : 144 | How many countries are in the dataframe?""" 145 | self.pandasai.run(df, "How many countries are in the dataframe?") 146 | assert self.pandasai._llm.last_prompt == expected_prompt 147 | 148 | def test_run_without_privacy_enforcement(self): 149 | df = pd.DataFrame({"country": ["United States", "United Kingdom", "France"]}) 150 | self.setup() 151 | self.pandasai._enforce_privacy = False 152 | self.pandasai._is_conversational_answer = False 153 | 154 | expected_prompt = """ 155 | There is a dataframe in pandas (python). 156 | The name of the dataframe is `df`. 157 | This is the result of `print(df.head(5))`: 158 | country 159 | 0 United States 160 | 1 United Kingdom 161 | 2 France. 162 | 163 | Return the python code (do not import anything) and make sure to prefix the python code with exactly and suffix the code with exactly 164 | to get the answer to the following question : 165 | How many countries are in the dataframe?""" 166 | self.pandasai.run(df, "How many countries are in the dataframe?") 167 | assert self.pandasai._llm.last_prompt == expected_prompt --------------------------------------------------------------------------------