Skip to content
Permalink

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also or learn more about diff comparisons.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also . Learn more about diff comparisons here.
base repository: shinichi-takayanagi/oregpt
Failed to load repositories. Confirm that selected base ref is valid, then try again.
Loading
base: 0.1.1
Choose a base ref
...
head repository: shinichi-takayanagi/oregpt
Failed to load repositories. Confirm that selected head ref is valid, then try again.
Loading
compare: master
Choose a head ref

Commits on May 7, 2023

  1. Fix bugs (#9)

    * Upda
    
    * Isorted
    
    * recover black
    shinichi-takayanagi authored May 7, 2023
    Copy the full SHA
    9c671f1 View commit details
  2. Copy the full SHA
    74d2df4 View commit details
  3. 0.1.2 (#11)

    * Fix minor bug
    
    * Update
    shinichi-takayanagi authored May 7, 2023
    Copy the full SHA
    02d5dd5 View commit details
  4. Copy the full SHA
    89570d4 View commit details

Commits on May 13, 2023

  1. Copy the full SHA
    ec926b7 View commit details

Commits on May 15, 2023

  1. Copy the full SHA
    1ac6fb0 View commit details
  2. ⬆ Bump mypy from 1.2.0 to 1.3.0

    Bumps [mypy](https://github.com/python/mypy) from 1.2.0 to 1.3.0.
    - [Commits](python/mypy@v1.2.0...v1.3.0)
    
    ---
    updated-dependencies:
    - dependency-name: mypy
      dependency-type: direct:development
      update-type: version-update:semver-minor
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored May 15, 2023
    Copy the full SHA
    bac4cad View commit details
  3. Merge pull request #16 from shinichi-takayanagi/dependabot/pip/mypy-1…

    ….3.0
    
    ⬆ Bump mypy from 1.2.0 to 1.3.0
    shinichi-takayanagi authored May 15, 2023
    Copy the full SHA
    8b2cd99 View commit details
  4. Copy the full SHA
    7e63615 View commit details
  5. Release

    shinichi-takayanagi committed May 15, 2023
    Copy the full SHA
    23d3f31 View commit details
  6. Copy the full SHA
    acab253 View commit details

Commits on May 22, 2023

  1. ⬆ Bump openai from 0.27.6 to 0.27.7

    Bumps [openai](https://github.com/openai/openai-python) from 0.27.6 to 0.27.7.
    - [Release notes](https://github.com/openai/openai-python/releases)
    - [Commits](openai/openai-python@v0.27.6...v0.27.7)
    
    ---
    updated-dependencies:
    - dependency-name: openai
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored May 22, 2023
    Copy the full SHA
    0caeb9c View commit details
  2. ⬆ Bump pre-commit from 3.3.1 to 3.3.2

    Bumps [pre-commit](https://github.com/pre-commit/pre-commit) from 3.3.1 to 3.3.2.
    - [Release notes](https://github.com/pre-commit/pre-commit/releases)
    - [Changelog](https://github.com/pre-commit/pre-commit/blob/main/CHANGELOG.md)
    - [Commits](pre-commit/pre-commit@v3.3.1...v3.3.2)
    
    ---
    updated-dependencies:
    - dependency-name: pre-commit
      dependency-type: direct:development
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored May 22, 2023
    Copy the full SHA
    3f71dfa View commit details
  3. Merge pull request #18 from shinichi-takayanagi/dependabot/pip/openai…

    …-0.27.7
    
    ⬆ Bump openai from 0.27.6 to 0.27.7
    shinichi-takayanagi authored May 22, 2023
    Copy the full SHA
    0c5eeaa View commit details
  4. Merge pull request #19 from shinichi-takayanagi/dependabot/pip/pre-co…

    …mmit-3.3.2
    
    ⬆ Bump pre-commit from 3.3.1 to 3.3.2
    shinichi-takayanagi authored May 22, 2023
    Copy the full SHA
    b8579e1 View commit details
  5. Copy the full SHA
    81d5e99 View commit details
  6. ⬆ Bump requests from 2.29.0 to 2.31.0

    Bumps [requests](https://github.com/psf/requests) from 2.29.0 to 2.31.0.
    - [Release notes](https://github.com/psf/requests/releases)
    - [Changelog](https://github.com/psf/requests/blob/main/HISTORY.md)
    - [Commits](psf/requests@v2.29.0...v2.31.0)
    
    ---
    updated-dependencies:
    - dependency-name: requests
      dependency-type: indirect
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored May 22, 2023
    Copy the full SHA
    fb13ebc View commit details
  7. Update document

    shinichi-takayanagi committed May 22, 2023
    Copy the full SHA
    bab9e20 View commit details
  8. Copy the full SHA
    f47fd00 View commit details

Commits on May 23, 2023

  1. Update document

    shinichi-takayanagi committed May 23, 2023
    Copy the full SHA
    8a356af View commit details
  2. Update

    shinichi-takayanagi committed May 23, 2023
    Copy the full SHA
    fe87cdb View commit details
  3. Update document

    shinichi-takayanagi committed May 23, 2023
    Copy the full SHA
    b793ad0 View commit details
  4. Copy the full SHA
    e05fdf0 View commit details
  5. Update document

    shinichi-takayanagi committed May 23, 2023
    Copy the full SHA
    b07011a View commit details
  6. Copy the full SHA
    dbd1722 View commit details

Commits on May 24, 2023

  1. Merge pull request #21 from shinichi-takayanagi/dependabot/pip/reques…

    …ts-2.31.0
    
    ⬆ Bump requests from 2.29.0 to 2.31.0
    shinichi-takayanagi authored May 24, 2023
    Copy the full SHA
    fbcf698 View commit details

Commits on Jun 12, 2023

  1. ⬆ Bump openai from 0.27.7 to 0.27.8

    Bumps [openai](https://github.com/openai/openai-python) from 0.27.7 to 0.27.8.
    - [Release notes](https://github.com/openai/openai-python/releases)
    - [Commits](openai/openai-python@v0.27.7...v0.27.8)
    
    ---
    updated-dependencies:
    - dependency-name: openai
      dependency-type: direct:production
      update-type: version-update:semver-patch
    ...
    
    Signed-off-by: dependabot[bot] <support@github.com>
    dependabot[bot] authored Jun 12, 2023
    Copy the full SHA
    c5a0f22 View commit details

Commits on Jul 27, 2023

  1. Merge pull request #25 from shinichi-takayanagi/dependabot/pip/openai…

    …-0.27.8
    
    ⬆ Bump openai from 0.27.7 to 0.27.8
    shinichi-takayanagi authored Jul 27, 2023
    Copy the full SHA
    ca1a4e1 View commit details
Showing with 627 additions and 145 deletions.
  1. +5 −2 .github/workflows/main.yml
  2. +30 −0 .pre-commit-config.yaml
  3. +30 −3 README.md
  4. +22 −16 oregpt/chat_bot.py
  5. +132 −0 oregpt/command.py
  6. +56 −25 oregpt/main.py
  7. +4 −3 { → oregpt/resources}/config.yml
  8. +4 −5 oregpt/stdinout.py
  9. +182 −69 poetry.lock
  10. +18 −2 pyproject.toml
  11. +54 −0 tests/conftest.py
  12. +49 −20 tests/test_chat_bot.py
  13. +41 −0 tests/test_command.py
7 changes: 5 additions & 2 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
@@ -64,11 +64,14 @@ jobs:
- name: black
run: poetry run black . --check

- name: autoflake
run: poetry run poetry run autoflake -r -c .

- name: isort
run: poetry run isort . --check-only

- name: Run mypy
- name: mypy
run: poetry run mypy . --explicit-package-bases

- name: Run pytest
- name: pytest
run: poetry run pytest -vv
30 changes: 30 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v4.4.0
hooks:
- id: trailing-whitespace
- id: end-of-file-fixer
- id: check-added-large-files
- id: check-toml
- id: check-yaml
- id: check-json
- repo: https://github.com/psf/black
rev: 23.3.0
hooks:
- id: black
- repo: https://github.com/pycqa/isort
rev: 5.12.0
hooks:
- id: isort
- repo: https://github.com/PyCQA/autoflake
rev: v2.1.1
hooks:
- id: autoflake
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v1.2.0
hooks:
- id: mypy
args: [
--explicit-package-bases
]
exclude: 'test_*'
33 changes: 30 additions & 3 deletions README.md
Original file line number Diff line number Diff line change
@@ -8,7 +8,7 @@
A tiny GPT CLI tool.
You can chat with the GPT model developped by OpenAI and save the conversation as json.

![oregpt](https://user-images.githubusercontent.com/24406372/236609166-0f2385b1-fd9e-4810-b80d-c19c44d13411.gif)
<img src="https://github.com/shinichi-takayanagi/oregpt/assets/24406372/91969861-9f29-4c81-9505-620ef5567a5b" width="800px">

## Installation
### Get your own OpenAI API Key
@@ -33,14 +33,40 @@ Once you have installed oregpt, you can run it by typing:
$ oregpt
```

There are a few options:
```bash
$ oregpt --help
Usage: oregpt [OPTIONS]

Options:
-V, -v, --version Show the version and exit.
-m, --model_name TEXT Model name in OpenAI (e.g, gpt-3.5-turbo, gpt-4)
-a, --assistant_role TEXT Role setting for Assistant (AI)
--help Show this message and exit.
```

## Supported commands on chat
Commands such as saving and loading conversations are available as the following:

| Command | Description |
| ---- | ---- |
| `/exit` | Exit from this chat tool |
| `/quit` | Exit from this chat tool |
| `/q` | Exit from this chat tool |
| `/clear` | Clear chat history all |
| `/history` | Show chat history in json format |
| `/save` | Save chat history in json format |
| `/load` | Load chat history from a json file |
| `/help` | Show all commands which you can use in this chat tool |

## Configuration
You can specify the place of conversation `log`,
[style (color etc)](https://python-prompt-toolkit.readthedocs.io/en/master/pages/advanced_topics/styling.html)
and
[the model supported in /v1/chat/completions endpoint provided by OpenAI](https://platform.openai.com/docs/models/overview)
in `~/.oregpt/config.yml`
in `~/.config/oregpt/config.yml`
```yaml
❯ cat ~/.oregpt/config.yml
❯ cat ~/.config/oregpt/config.yml
log: /tmp/oregpt/
openai:
model: gpt-3.5-turbo
@@ -53,6 +79,7 @@ character:
assistant:
name: AI
style: "#87CEEB"
role: "You are a chat bot"
system:
name: System
style: "#cc0000"
38 changes: 22 additions & 16 deletions oregpt/chat_bot.py
Original file line number Diff line number Diff line change
@@ -1,33 +1,38 @@
import json
import pathlib
from datetime import datetime
from typing import Callable
from copy import deepcopy

import openai

from oregpt.stdinout import StdInOut


class ChatBot:
def __init__(self, model: str, std_in_out: StdInOut):
def __init__(self, model: str, assistant_role: str, std_in_out: StdInOut):
self._std_in_out = std_in_out
# Model list: gpt-4, gpt-4-0314, gpt-4-32k, gpt-4-32k-0314, gpt-3.5-turbo, gpt-3.5-turbo-0301
# https://platform.openai.com/docs/models/overview
self._model = model

self._assistant_role = [{"role": "system", "content": assistant_role}]
self._initialize_log()

def _initialize_log(self) -> None:
self._log: list[dict[str, str]] = deepcopy(self._assistant_role)

@property
def model(self) -> str:
return self._model

@property
def assistant_role(self) -> list[dict[str, str]]:
return deepcopy(self._assistant_role)

@property
def log(self) -> list[dict[str, str]]:
return self._log

def _initialize_log(self) -> None:
# TODO
# Make system role
# https://community.openai.com/t/the-system-role-how-it-influences-the-chat-behavior/87353
# https://learn.microsoft.com/ja-jp/azure/cognitive-services/openai/how-to/chatgpt?pivots=programming-language-chat-completions#system-role
# self._log = [{"role": "system", "content": f"You are a chat bot."}]
self._log: list[dict[str, str]] = []
@property
def std_in_out(self) -> StdInOut:
return self._std_in_out

def respond(self, message: str) -> str:
self._log.append({"role": "user", "content": message})
@@ -50,13 +55,14 @@ def respond(self, message: str) -> str:
self._log.append({"role": "assistant", "content": content})
return content

def save(self, directory: str) -> str:
path = pathlib.Path(directory)
path.mkdir(parents=True, exist_ok=True)
file_name = str(path / datetime.now().strftime("log_%Y-%m-%d-%H-%M-%S.json"))
def save(self, file_name: str) -> str:
with open(file_name, "w", encoding="utf-8") as file:
json.dump(self._log, file, indent=4, ensure_ascii=False)
return file_name

def load(self, file_name: str) -> None:
with open(file_name, "r", encoding="utf-8") as file:
self._log = json.load(file)

def clear(self) -> None:
self._initialize_log()
132 changes: 132 additions & 0 deletions oregpt/command.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,132 @@
import os
import pathlib
import sys
from abc import ABC, abstractmethod
from datetime import datetime
from typing import Any, Optional, Type

from oregpt.chat_bot import ChatBot


class CommandBuilder:
command_classes: dict[str, Type["Command"]] = dict({})

def __init__(self, config: dict[str, Any], bot: ChatBot):
self._config = config
self._bot = bot

def build(self, message: str) -> Optional["Command"]:
messages = message.split(" ")
command = messages[0].strip()
args = messages[1:] if len(messages) >= 2 else []
args = list(filter(None, args))
return (
class_type(self._config, self._bot, args)
if (class_type := CommandBuilder.command_classes.get(command))
else None
)

def looks_like_command(self, message: str) -> bool:
if len(message) == 0:
return False
return "/" == message[0]


def register(cls: Type["Command"]) -> Type["Command"]:
for representation in cls.representations:
CommandBuilder.command_classes["/" + representation] = cls
return cls


class Command(ABC):
representations: list[str] = []

def __init__(self, config: dict[str, Any], bot: ChatBot, args: list[str]):
self._config = config
self._bot = bot
self._args = args

@abstractmethod
def execute(self) -> None:
pass


@register
class ExitCommand(Command):
"""Exit from this chat tool"""

representations: list[str] = ["exit", "quit", "q"]

def execute(self) -> None:
sys.exit()


@register
class ClearCommand(Command):
"""Clear chat history all"""

representations: list[str] = ["clear"]

def execute(self) -> None:
self._bot.clear()
self._bot.std_in_out.print_system("Clear all conversation history")


@register
class HistoryCommand(Command):
"""Show chat history in json format"""

representations: list[str] = ["history"]

def execute(self) -> None:
self._bot.std_in_out.print_system(str(self._bot.log))


def _abspath(x: str) -> str:
return os.path.abspath(os.path.expanduser(x))


@register
class SaveCommand(Command):
"""Save chat history in json format"""

representations: list[str] = ["save"]

def execute(self) -> None:
file_name = ""
if len(self._args) == 1:
file_name = _abspath(self._args[0].strip())
directory = pathlib.Path(os.path.dirname(file_name))
if file_name == "":
directory = pathlib.Path(_abspath(self._config["log"]))
file_name = str(directory / datetime.now().strftime("log_%Y-%m-%d-%H-%M-%S.json"))
directory.mkdir(parents=True, exist_ok=True)
self._bot.save(file_name)
self._bot.std_in_out.print_system(f"Save all conversation history in {file_name}")


@register
class LoadCommand(Command):
"""Load chat history from a json file"""

representations: list[str] = ["load"]

def execute(self) -> None:
print(self._args)
if len(self._args) != 1:
self._bot.std_in_out.print_system("Loaded file was not specified as an argument")
return
file_name = _abspath(self._args[0])
self._bot.load(file_name)
self._bot.std_in_out.print_system(f"Loaded chat history from {file_name}")


@register
class HelpCommand(Command):
"""Show all commands which you can use in this chat tool"""

representations: list[str] = ["help"]

def execute(self) -> None:
for k, v in CommandBuilder.command_classes.items():
self._bot.std_in_out.print_system(f"{k}: {v.__doc__}")
Loading