Skip to content

Commit

Permalink
Initial prompt/response log, closes #2
Browse files Browse the repository at this point in the history
  • Loading branch information
simonw committed Apr 1, 2023
1 parent 93ebb96 commit 1a840cd
Show file tree
Hide file tree
Showing 3 changed files with 65 additions and 6 deletions.
16 changes: 15 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ You need an OpenAI API key, which should either be set in the `OPENAI_API_KEY` e

## Usage

So far this tool only has one command - `llm chatgpt`. You can just use `llm` as this is the default command.
The default command for this is `llm chatgpt` - you can use `llm` instead if you prefer.

To run a prompt:

Expand All @@ -33,6 +33,20 @@ To switch from ChatGPT 3.5 (the default) to GPT-4 if you have access:

Pass `--model <model name>` to use a different model.

## Logging to SQLite

If a SQLite database file exists in `~/.llm/log.db` then the tool will log all prompts and responses to it.

You can create that file by running the `init-db` command:

llm init-db

Now any prompts you run will be logged to that database.

To avoid logging a prompt, pass `--no-log` or `-n` to the command:

llm 'Ten names for cheesecakes' -n

## Help

For help, run:
Expand Down
53 changes: 49 additions & 4 deletions llm/cli.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,9 @@
import click
from click_default_group import DefaultGroup
import datetime
import openai
import os
import sqlite_utils
import sys


Expand All @@ -21,7 +23,8 @@ def cli():
@click.option("-4", "--gpt4", is_flag=True, help="Use GPT-4")
@click.option("-m", "--model", help="Model to use")
@click.option("-s", "--stream", is_flag=True, help="Stream output")
def chatgpt(prompt, system, gpt4, model, stream):
@click.option("-n", "--no-log", is_flag=True, help="Don't log to database")
def chatgpt(prompt, system, gpt4, model, stream, no_log):
"Execute prompt against ChatGPT"
openai.api_key = get_openai_api_key()
if gpt4:
Expand All @@ -33,30 +36,72 @@ def chatgpt(prompt, system, gpt4, model, stream):
messages.append({"role": "system", "content": system})
messages.append({"role": "user", "content": prompt})
if stream:
response = []
for chunk in openai.ChatCompletion.create(
model=model,
messages=messages,
stream=True,
):
content = chunk["choices"][0].get("delta", {}).get("content")
if content is not None:
response.append(content)
print(content, end="")
sys.stdout.flush()
print("")
log(no_log, "chatgpt", system, prompt, "".join(response), model)
else:
response = openai.ChatCompletion.create(
model=model,
messages=messages,
)
print(response.choices[0].message.content)
content = response.choices[0].message.content
print(content)
log(no_log, "chatgpt", system, prompt, content, model)


@cli.command()
def init_db():
"Ensure ~/.llm/log.db SQLite database exists"
path = get_log_db_path()
if os.path.exists(path):
return
# Ensure directory exists
os.makedirs(os.path.dirname(path), exist_ok=True)
db = sqlite_utils.Database(path)
db.vacuum()


def get_openai_api_key():
# Expand this to home directory / ~.openai-api-key.txt
if "OPENAI_API_KEY" in os.environ:
return os.environ["OPENAI_API_KEY"]
path = os.path.expanduser('~/.openai-api-key.txt')
path = os.path.expanduser("~/.openai-api-key.txt")
# If the file exists, read it
if os.path.exists(path):
return open(path).read().strip()
raise click.ClickException("No OpenAI API key found. Set OPENAI_API_KEY environment variable or create ~/.openai-api-key.txt")
raise click.ClickException(
"No OpenAI API key found. Set OPENAI_API_KEY environment variable or create ~/.openai-api-key.txt"
)


def get_log_db_path():
return os.path.expanduser("~/.llm/log.db")


def log(no_log, provider, system, prompt, response, model):
if no_log:
return
log_path = get_log_db_path()
if not os.path.exists(log_path):
return
db = sqlite_utils.Database(log_path)
db["log"].insert(
{
"provider": provider,
"system": system,
"prompt": prompt,
"response": response,
"model": model,
"timestamp": str(datetime.datetime.utcnow()),
}
)
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def get_long_description():
[console_scripts]
llm=llm.cli:cli
""",
install_requires=["click", "openai", "click-default-group-wheel"],
install_requires=["click", "openai", "click-default-group-wheel", "sqlite-utils"],
extras_require={"test": ["pytest"]},
python_requires=">=3.7",
)

0 comments on commit 1a840cd

Please sign in to comment.