Skip to content

Commit

Permalink
reduce commands to run, add logging, refactor a bit
Browse files Browse the repository at this point in the history
  • Loading branch information
rsheyd committed Jan 28, 2024
1 parent ef4a276 commit 11ae8b3
Show file tree
Hide file tree
Showing 31 changed files with 1,749 additions and 11 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
.env
personal/
.vscode/
.DS_Store

2 changes: 2 additions & 0 deletions .pylintrc
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
[MASTER]
init-hook="from pylint.config import find_pylintrc; import os, sys; sys.path.append(os.path.dirname(find_pylintrc()))"
7 changes: 4 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -8,8 +8,9 @@ Create `.env` file with an [OpenAI API key](https://help.openai.com/en/articles/
`OPENAI_API_KEY=copy_api_key_here`

## Run AI
`source openai-env/bin/activate`

`python3 jarvis.py`
`./run_jarvis.sh`

Type `bye` to exit.
If you get a 'permission denied' error, run: `chmod +x run_jarvis.sh`

Type `bye` to exit the program.
30 changes: 22 additions & 8 deletions jarvis.py
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
import time
import logging
from openai import OpenAI
from dotenv import load_dotenv

# load local .env file for the OPENAI_APY_KEY
load_dotenv()
client = OpenAI()

# summarize and log our conversations
# keep the system assistant descriptions updated and previous descriptions logged
# add config and log files
# add config

def main():
logging.basicConfig(filename='personal/history.log', level=logging.INFO, format='%(asctime)s - %(levelname)s - %(message)s')
human = 'Roman'
prompt_for_input = '> Hello '+human+'. How are you?\n'
messages = []
Expand Down Expand Up @@ -35,14 +38,25 @@ def parse(instruction, messages):
return '', messages

def bye_sequence(messages, human):
instruction = "Can you give me a summary, which is shorter than 50 words, of our conversation? Also, was there anything I asked you to change about your responses, such as making them shorter, or present them in a different way? If yes, please also write a description, which is shorter than 50 words, of a perfect assistant for someone who requests the type of changes I asked you to make. And please write it from a 'you' perspective, so the description should start out with 'You are an assistant for...'"
print('> Summarizing conversation and checking for requested changes...')
instruction = "Can you give me a summary, which is shorter than 50 words, of our conversation?"
messages.append({"role": "user", "content": instruction})
completion = client.chat.completions.create(
model="gpt-3.5-turbo", messages=messages
)
answer = completion.choices[0].message.content
print('> '+answer)
)
summary = completion.choices[0].message.content
log(f'Summary of our conversation: {summary}')
instruction = "Was there anything I asked you to change about your responses, such as making them shorter, or presenting them in a different way? If yes, please also write a description, which is shorter than 50 words, of a perfect assistant for someone who requests the type of changes I asked you to make. And please write it from a 'you' perspective, so the description should start out with 'You are an assistant for...' If no, please write 'No changes were requested for my responses.'"
messages.append({"role": "user", "content": instruction})
completion = client.chat.completions.create(
model="gpt-3.5-turbo", messages=messages
)
requested_changes = completion.choices[0].message.content
log(f'Requested changes: {requested_changes}')
print('> Bye '+human)
exit()
return

def log(text):
logging.info(text)

main()
10 changes: 10 additions & 0 deletions openai-env/bin/dotenv
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
#!/bin/sh
'''exec' "/Users/roman/My Drive/Dropbox/dev/jarvis-2024/openai-env/bin/python3.11" "$0" "$@"
' '''
# -*- coding: utf-8 -*-
import re
import sys
from dotenv.__main__ import cli
if __name__ == '__main__':
sys.argv[0] = re.sub(r'(-script\.pyw|\.exe)?$', '', sys.argv[0])
sys.exit(cli())
49 changes: 49 additions & 0 deletions openai-env/lib/python3.11/site-packages/dotenv/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
from typing import Any, Optional

from .main import (dotenv_values, find_dotenv, get_key, load_dotenv, set_key,
unset_key)


def load_ipython_extension(ipython: Any) -> None:
from .ipython import load_ipython_extension
load_ipython_extension(ipython)


def get_cli_string(
path: Optional[str] = None,
action: Optional[str] = None,
key: Optional[str] = None,
value: Optional[str] = None,
quote: Optional[str] = None,
):
"""Returns a string suitable for running as a shell script.
Useful for converting a arguments passed to a fabric task
to be passed to a `local` or `run` command.
"""
command = ['dotenv']
if quote:
command.append(f'-q {quote}')
if path:
command.append(f'-f {path}')
if action:
command.append(action)
if key:
command.append(key)
if value:
if ' ' in value:
command.append(f'"{value}"')
else:
command.append(value)

return ' '.join(command).strip()


__all__ = ['get_cli_string',
'load_dotenv',
'dotenv_values',
'get_key',
'set_key',
'unset_key',
'find_dotenv',
'load_ipython_extension']
6 changes: 6 additions & 0 deletions openai-env/lib/python3.11/site-packages/dotenv/__main__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
"""Entry point for cli, enables execution with `python -m dotenv`"""

from .cli import cli

if __name__ == "__main__":
cli()
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
199 changes: 199 additions & 0 deletions openai-env/lib/python3.11/site-packages/dotenv/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,199 @@
import json
import os
import shlex
import sys
from contextlib import contextmanager
from subprocess import Popen
from typing import Any, Dict, IO, Iterator, List

try:
import click
except ImportError:
sys.stderr.write('It seems python-dotenv is not installed with cli option. \n'
'Run pip install "python-dotenv[cli]" to fix this.')
sys.exit(1)

from .main import dotenv_values, set_key, unset_key
from .version import __version__


def enumerate_env():
"""
Return a path for the ${pwd}/.env file.
If pwd does not exist, return None.
"""
try:
cwd = os.getcwd()
except FileNotFoundError:
return None
path = os.path.join(cwd, '.env')
return path


@click.group()
@click.option('-f', '--file', default=enumerate_env(),
type=click.Path(file_okay=True),
help="Location of the .env file, defaults to .env file in current working directory.")
@click.option('-q', '--quote', default='always',
type=click.Choice(['always', 'never', 'auto']),
help="Whether to quote or not the variable values. Default mode is always. This does not affect parsing.")
@click.option('-e', '--export', default=False,
type=click.BOOL,
help="Whether to write the dot file as an executable bash script.")
@click.version_option(version=__version__)
@click.pass_context
def cli(ctx: click.Context, file: Any, quote: Any, export: Any) -> None:
"""This script is used to set, get or unset values from a .env file."""
ctx.obj = {'QUOTE': quote, 'EXPORT': export, 'FILE': file}


@contextmanager
def stream_file(path: os.PathLike) -> Iterator[IO[str]]:
"""
Open a file and yield the corresponding (decoded) stream.
Exits with error code 2 if the file cannot be opened.
"""

try:
with open(path) as stream:
yield stream
except OSError as exc:
print(f"Error opening env file: {exc}", file=sys.stderr)
exit(2)


@cli.command()
@click.pass_context
@click.option('--format', default='simple',
type=click.Choice(['simple', 'json', 'shell', 'export']),
help="The format in which to display the list. Default format is simple, "
"which displays name=value without quotes.")
def list(ctx: click.Context, format: bool) -> None:
"""Display all the stored key/value."""
file = ctx.obj['FILE']

with stream_file(file) as stream:
values = dotenv_values(stream=stream)

if format == 'json':
click.echo(json.dumps(values, indent=2, sort_keys=True))
else:
prefix = 'export ' if format == 'export' else ''
for k in sorted(values):
v = values[k]
if v is not None:
if format in ('export', 'shell'):
v = shlex.quote(v)
click.echo(f'{prefix}{k}={v}')


@cli.command()
@click.pass_context
@click.argument('key', required=True)
@click.argument('value', required=True)
def set(ctx: click.Context, key: Any, value: Any) -> None:
"""Store the given key/value."""
file = ctx.obj['FILE']
quote = ctx.obj['QUOTE']
export = ctx.obj['EXPORT']
success, key, value = set_key(file, key, value, quote, export)
if success:
click.echo(f'{key}={value}')
else:
exit(1)


@cli.command()
@click.pass_context
@click.argument('key', required=True)
def get(ctx: click.Context, key: Any) -> None:
"""Retrieve the value for the given key."""
file = ctx.obj['FILE']

with stream_file(file) as stream:
values = dotenv_values(stream=stream)

stored_value = values.get(key)
if stored_value:
click.echo(stored_value)
else:
exit(1)


@cli.command()
@click.pass_context
@click.argument('key', required=True)
def unset(ctx: click.Context, key: Any) -> None:
"""Removes the given key."""
file = ctx.obj['FILE']
quote = ctx.obj['QUOTE']
success, key = unset_key(file, key, quote)
if success:
click.echo(f"Successfully removed {key}")
else:
exit(1)


@cli.command(context_settings={'ignore_unknown_options': True})
@click.pass_context
@click.option(
"--override/--no-override",
default=True,
help="Override variables from the environment file with those from the .env file.",
)
@click.argument('commandline', nargs=-1, type=click.UNPROCESSED)
def run(ctx: click.Context, override: bool, commandline: List[str]) -> None:
"""Run command with environment variables present."""
file = ctx.obj['FILE']
if not os.path.isfile(file):
raise click.BadParameter(
f'Invalid value for \'-f\' "{file}" does not exist.',
ctx=ctx
)
dotenv_as_dict = {
k: v
for (k, v) in dotenv_values(file).items()
if v is not None and (override or k not in os.environ)
}

if not commandline:
click.echo('No command given.')
exit(1)
ret = run_command(commandline, dotenv_as_dict)
exit(ret)


def run_command(command: List[str], env: Dict[str, str]) -> int:
"""Run command in sub process.
Runs the command in a sub process with the variables from `env`
added in the current environment variables.
Parameters
----------
command: List[str]
The command and it's parameters
env: Dict
The additional environment variables
Returns
-------
int
The return code of the command
"""
# copy the current environment variables and add the vales from
# `env`
cmd_env = os.environ.copy()
cmd_env.update(env)

p = Popen(command,
universal_newlines=True,
bufsize=0,
shell=False,
env=cmd_env)
_, _ = p.communicate()

return p.returncode
39 changes: 39 additions & 0 deletions openai-env/lib/python3.11/site-packages/dotenv/ipython.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,39 @@
from IPython.core.magic import Magics, line_magic, magics_class # type: ignore
from IPython.core.magic_arguments import (argument, magic_arguments, # type: ignore
parse_argstring) # type: ignore

from .main import find_dotenv, load_dotenv


@magics_class
class IPythonDotEnv(Magics):

@magic_arguments()
@argument(
'-o', '--override', action='store_true',
help="Indicate to override existing variables"
)
@argument(
'-v', '--verbose', action='store_true',
help="Indicate function calls to be verbose"
)
@argument('dotenv_path', nargs='?', type=str, default='.env',
help='Search in increasingly higher folders for the `dotenv_path`')
@line_magic
def dotenv(self, line):
args = parse_argstring(self.dotenv, line)
# Locate the .env file
dotenv_path = args.dotenv_path
try:
dotenv_path = find_dotenv(dotenv_path, True, True)
except IOError:
print("cannot find .env file")
return

# Load the .env file
load_dotenv(dotenv_path, verbose=args.verbose, override=args.override)


def load_ipython_extension(ipython):
"""Register the %dotenv magic."""
ipython.register_magics(IPythonDotEnv)
Loading

0 comments on commit 11ae8b3

Please sign in to comment.