├── .gitignore ├── readme.org ├── requirements.txt └── main.py /.gitignore: -------------------------------------------------------------------------------- 1 | .venv 2 | credentials.json 3 | credentials.pickle 4 | -------------------------------------------------------------------------------- /readme.org: -------------------------------------------------------------------------------- 1 | #+title: llm-review 2 | 3 | * Introduction 4 | This script is used to read my daily journal every night at midnight and email me recommendations to make my next day better. 5 | 6 | * Installation 7 | Create Python virtual environment: 8 | #+begin_src bash :results none 9 | python -m venv .venv --prompt=llm=review 10 | #+end_src 11 | 12 | Activate virtual environment: 13 | #+begin_src bash :results none 14 | source .venv/bin/activate 15 | #+end_src 16 | 17 | Install dependencies: 18 | #+begin_src bash :results none 19 | pip install -r requirements.txt 20 | #+end_src 21 | 22 | Get a ~credentials.json~ from Google Cloud Console and place it in this folder. 23 | 24 | * Run 25 | #+begin_src bash :results none 26 | python main.py 27 | #+end_src 28 | -------------------------------------------------------------------------------- /requirements.txt: -------------------------------------------------------------------------------- 1 | aiohttp==3.8.4 2 | aiosignal==1.3.1 3 | async-timeout==4.0.2 4 | attrs==22.2.0 5 | cachetools==5.3.0 6 | certifi==2022.12.7 7 | charset-normalizer==3.1.0 8 | dataclasses-json==0.5.7 9 | frozenlist==1.3.3 10 | google-api-core==2.11.0 11 | google-api-python-client==2.83.0 12 | google-auth==2.17.1 13 | google-auth-httplib2==0.1.0 14 | google-auth-oauthlib==1.0.0 15 | googleapis-common-protos==1.59.0 16 | httplib2==0.22.0 17 | idna==3.4 18 | langchain==0.0.129 19 | marshmallow==3.19.0 20 | marshmallow-enum==1.5.1 21 | multidict==6.0.4 22 | mypy-extensions==1.0.0 23 | numpy==1.24.2 24 | oauth2client==4.1.3 25 | oauthlib==3.2.2 26 | openai==0.27.2 27 | packaging==23.0 28 | protobuf==4.22.1 29 | pyasn1==0.4.8 30 | pyasn1-modules==0.2.8 31 | pydantic==1.10.7 32 | pyparsing==3.0.9 33 | PyYAML==6.0 34 | requests==2.28.2 35 | requests-oauthlib==1.3.1 36 | rsa==4.9 37 | six==1.16.0 38 | SQLAlchemy==1.4.47 39 | tenacity==8.2.2 40 | tqdm==4.65.0 41 | typing-inspect==0.8.0 42 | typing_extensions==4.5.0 43 | uritemplate==4.1.1 44 | urllib3==1.26.15 45 | yarl==1.8.2 46 | -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | import os 2 | import pickle 3 | import base64 4 | from datetime import datetime 5 | from string import Template 6 | from email.message import EmailMessage 7 | 8 | import google.auth 9 | from google.oauth2.credentials import Credentials 10 | from google_auth_oauthlib.flow import InstalledAppFlow 11 | 12 | from googleapiclient.discovery import build 13 | from googleapiclient.errors import HttpError 14 | 15 | from langchain.chat_models import ChatOpenAI 16 | from langchain.schema import HumanMessage 17 | 18 | SCOPES = ["https://www.googleapis.com/auth/gmail.compose"] 19 | CREDENTIALS_FILE = "credentials.pickle" 20 | 21 | today = datetime.today().strftime("%Y-%m-%d") 22 | 23 | path_template = Template(os.path.expanduser("~") + "/meworg/journal/daily/$today.org") 24 | path = path_template.substitute(today=today) 25 | 26 | file = open(path, "r") 27 | daily_journal = file.read() 28 | file.close() 29 | 30 | content_template = Template( 31 | "Here is my daily journal for today in a Markdown block:\n```\n$daily_journal\n```\nBased on this, how can I make my next day better?" 32 | ) 33 | content = content_template.substitute(daily_journal=daily_journal) 34 | 35 | chat = ChatOpenAI(temperature=0.5) 36 | result = chat([HumanMessage(content=content)]) 37 | 38 | 39 | def get_credentials(): 40 | if os.path.exists(CREDENTIALS_FILE): 41 | with open(CREDENTIALS_FILE, "rb") as f: 42 | creds = pickle.load(f) 43 | else: 44 | flow = InstalledAppFlow.from_client_secrets_file("credentials.json", SCOPES) 45 | creds = flow.run_local_server(port=0) 46 | with open(CREDENTIALS_FILE, "wb") as f: 47 | pickle.dump(creds, f) 48 | 49 | if creds and creds.expired and creds.refresh_token: 50 | creds.refresh(Request()) 51 | 52 | return creds 53 | 54 | 55 | def gmail_send(content): 56 | creds = get_credentials() 57 | 58 | try: 59 | # create gmail api client 60 | service = build("gmail", "v1", credentials=creds) 61 | 62 | message = EmailMessage() 63 | 64 | message.set_content(content) 65 | 66 | email = "damien.gonot@gmail.com" 67 | message["To"] = email 68 | message["From"] = email 69 | message["Subject"] = today + " review" 70 | 71 | # encoded message 72 | encoded_message = base64.urlsafe_b64encode(message.as_bytes()).decode() 73 | 74 | create_message = {"message": {"raw": encoded_message}} 75 | # pylint: disable=E1101 76 | draft = ( 77 | service.users().drafts().create(userId="me", body=create_message).execute() 78 | ) 79 | 80 | except HttpError as error: 81 | print(f"An error occurred: {error}") 82 | draft = None 83 | 84 | service.users().drafts().send(userId="me", body={"id": draft["id"]}).execute() 85 | 86 | 87 | gmail_send(result.content) 88 | --------------------------------------------------------------------------------