Commit graph

1165 commits

Author SHA1 Message Date
Paul Gauthier
e608a351f0 standardize on abs_root_path(), simplify get/apply_edit 2023-08-18 07:20:15 -07:00
Paul Gauthier
f45bcbf8eb make reference to repo conditional 2023-08-18 07:11:42 -07:00
Paul Gauthier
8f26c27921 just diff the named files on commit 2023-08-18 07:09:16 -07:00
Paul Gauthier
389bf9310c commit just the edited files, treat named files outside git as dirty 2023-08-18 07:05:48 -07:00
Paul Gauthier
d89316147a do not add new files to git 2023-08-17 16:31:21 -07:00
Paul Gauthier
fbc4a49c24 Removed support for func based coders 2023-08-17 11:19:49 -07:00
Paul Gauthier
3401395e61 fix wholefile tests 2023-08-17 11:08:50 -07:00
Paul Gauthier
fef5a7b917 only check tracked files if there is a repo 2023-08-17 10:44:33 -07:00
Paul Gauthier
0a653d34d3 cleanup 2023-08-17 10:40:56 -07:00
Paul Gauthier
d981de5f5f do the commit before applying edits 2023-08-17 10:40:01 -07:00
Paul Gauthier
2455676a44 refactor to enumerate files to be edited, then make the edits 2023-08-17 10:07:22 -07:00
Paul Gauthier
6e9fbdcb6a fixed spurious "Adding to git" messages when running aider in subdir of repo 2023-08-17 08:32:44 -07:00
Paul Gauthier
f62e3e2c90 copy 2023-08-14 15:09:29 -03:00
Paul Gauthier
ef764fefc8 default to auto 2023-08-14 15:07:08 -03:00
Paul Gauthier
c07013abf4 finished roughing in --voice-language 2023-08-14 14:18:37 -03:00
Paul Gauthier
bddcdd39a8 Refactor record_and_transcribe method in voice.py to accept a language parameter. 2023-08-14 14:11:31 -03:00
Paul Gauthier
23579d4741 Refactor voice recording and transcription to allow for specifying the language. 2023-08-14 14:11:03 -03:00
Paul Gauthier
f4e1c1010b aider: Accept voice_language param in __init__, pass to Commands.
# Aider chat conversation:

USER: accept voice_language param in __ini__, pass to Commands

ASSISTANT: To implement this change, we need to modify the following files:

1. `aider/coders/base_coder.py`: We need to modify the `__init__` method of the `Coder` class to accept a new parameter `voice_language`. We also need to pass this new parameter to the `Commands` class.

Here are the changes:

```python
aider/coders/base_coder.py
<<<<<<< HEAD
    def __init__(
        self,
        main_model,
        io,
        fnames=None,
        git_dname=None,
        pretty=True,
        show_diffs=False,
        auto_commits=True,
        dirty_commits=True,
        dry_run=False,
        map_tokens=1024,
        verbose=False,
        assistant_output_color="blue",
        code_theme="default",
        stream=True,
        use_git=True,
    ):
=======
    def __init__(
        self,
        main_model,
        io,
        fnames=None,
        git_dname=None,
        pretty=True,
        show_diffs=False,
        auto_commits=True,
        dirty_commits=True,
        dry_run=False,
        map_tokens=1024,
        verbose=False,
        assistant_output_color="blue",
        code_theme="default",
        stream=True,
        use_git=True,
        voice_language=None,
    ):
>>>>>>> updated
```

```python
aider/coders/base_coder.py
<<<<<<< HEAD
        self.commands = Commands(self.io, self)
=======
        self.commands = Commands(self.io, self, voice_language)
>>>>>>> updated
```

Please confirm these changes.
2023-08-14 14:09:45 -03:00
Paul Gauthier
625b251530 Change help message for voice language option to include "use auto to detect". 2023-08-14 14:08:38 -03:00
Paul Gauthier
8749adf511 aider: Add --voice-language switch with default "en" and pass it into Coder.
# Aider chat conversation:

USER: add --voice-language switch with default "en" and pass it into `Coder`

ASSISTANT: To add the `--voice-language` switch, we need to modify the `aider/main.py` file. We will add the argument in the `core_group` section of the argument parser. Then, we will pass this argument to the `Coder` class.

Here are the changes:

```python
aider/main.py
<<<<<<< HEAD
    core_group.add_argument(
        "-3",
        action="store_const",
        dest="model",
        const=models.GPT35_16k.name,
        help=f"Use {models.GPT35_16k.name} model for the main chat (gpt-4 is better)",
    )
=======
    core_group.add_argument(
        "-3",
        action="store_const",
        dest="model",
        const=models.GPT35_16k.name,
        help=f"Use {models.GPT35_16k.name} model for the main chat (gpt-4 is better)",
    )
    core_group.add_argument(
        "--voice-language",
        metavar="VOICE_LANGUAGE",
        default="en",
        help="Specify the language for voice (default: en)",
    )
>>>>>>> updated
```

```python
aider/main.py
<<<<<<< HEAD
    try:
        coder = Coder.create(
            main_model,
            args.edit_format,
            io,
            ##
            fnames=fnames,
            git_dname=git_dname,
            pretty=args.pretty,
            show_diffs=args.show_diffs,
            auto_commits=args.auto_commits,
            dirty_commits=args.dirty_commits,
            dry_run=args.dry_run,
            map_tokens=args.map_tokens,
            verbose=args.verbose,
            assistant_output_color=args.assistant_output_color,
            code_theme=args.code_theme,
            stream=args.stream,
            use_git=args.git,
        )
    except ValueError as err:
        io.tool_error(str(err))
        return 1
=======
    try:
        coder = Coder.create(
            main_model,
            args.edit_format,
            io,
            ##
            fnames=fnames,
            git_dname=git_dname,
            pretty=args.pretty,
            show_diffs=args.show_diffs,
            auto_commits=args.auto_commits,
            dirty_commits=args.dirty_commits,
            dry_run=args.dry_run,
            map_tokens=args.map_tokens,
            verbose=args.verbose,
            assistant_output_color=args.assistant_output_color,
            code_theme=args.code_theme,
            stream=args.stream,
            use_git=args.git,
            voice_language=args.voice_language,
        )
    except ValueError as err:
        io.tool_error(str(err))
        return 1
>>>>>>> updated
```

Please note that the `Coder` class and its subclasses (`EditBlockCoder`, `EditBlockFunctionCoder`, `SingleWholeFileFunctionCoder`, `WholeFileCoder`, `WholeFileFunctionCoder`) need to be updated to accept and use the `voice_language` argument. These changes are not shown here as the `Coder` class and its subclasses are not provided in the *read-write* files.
2023-08-14 14:08:04 -03:00
Paul Gauthier
fcb209c5aa refac 2023-08-11 11:16:31 -03:00
Paul Gauthier
b6b271b70c pass the input history as a prompt to whisper 2023-08-11 11:03:37 -03:00
Paul Gauthier
9815d14368 rename 2023-08-11 10:49:27 -03:00
Paul Gauthier
c38a877d81 clip low volumes to 0 2023-08-11 10:33:20 -03:00
Paul Gauthier
fe73df9a42 set version to 0.12.1-dev 2023-08-11 08:58:43 -03:00
Paul Gauthier
374b0c20ca version bump to 0.12.0 2023-08-11 08:58:18 -03:00
Paul Gauthier
233433cc11 properly handle ^c in /voice 2023-08-11 08:45:06 -03:00
Paul Gauthier
b59e5bf298 copy 2023-08-10 22:27:18 -03:00
Paul Gauthier
24f574a7dc better bar 2023-08-10 22:21:39 -03:00
Paul Gauthier
bfa7fedd18 catch ^c 2023-08-10 22:18:41 -03:00
Paul Gauthier
053751cb43 show loudness bar 2023-08-10 22:17:31 -03:00
Paul Gauthier
4dc704272e aider: Updated callback function to calculate the root mean square (RMS) of the input audio data.
# Aider chat conversation:

USER: what is `indata` ?

ASSISTANT: `indata` is a parameter in the callback function defined within the `record_and_transcribe` function in the `aider/voice.py` file. This parameter represents the input audio data that is being recorded.

In the context of the `sounddevice` library, which is used for audio recording in this script, `indata` is a 2D numpy array containing the recorded audio data. The rows in the array represent individual frames, while the columns represent channels.

In this specific script, the audio is being recorded in mono (single channel), so there will be only one column. The data in `indata` is being put into a queue and also being dumped for debugging purposes.

USER: how can i estimate the avg volume based on indata?

ASSISTANT: To estimate the average volume of the audio data, you can calculate the root mean square (RMS) of the `indata` array. The RMS represents the square root of the average of the squares of the values, and it's a common way to measure the magnitude of a varying quantity, such as audio signals.

Here's how you can modify the `record_and_transcribe` function to calculate the RMS:

```python
aider/voice.py
<<<<<<< HEAD
    def callback(indata, frames, time, status):
        """This is called (from a separate thread) for each audio block."""
        q.put(indata.copy())
        dump(indata)
        dump(indata.mean())
=======
    import numpy as np

    def callback(indata, frames, time, status):
        """This is called (from a separate thread) for each audio block."""
        q.put(indata.copy())
        rms = np.sqrt(np.mean(indata**2))
        dump(rms)
>>>>>>> updated
```

In this change, we import the numpy library and replace the line `dump(indata.mean())` with `rms = np.sqrt(np.mean(indata**2))` and `dump(rms)`. This calculates the RMS of the `indata` and dumps it for debugging purposes.
2023-08-10 21:57:42 -03:00
Paul Gauthier
aba2bb610d proper temp file 2023-08-10 21:54:04 -03:00
Paul Gauthier
3ff2cb8dbe append voice messages to input history 2023-08-10 17:17:51 -03:00
Paul Gauthier
4812d17372 prettier 2023-08-10 17:12:19 -03:00
Paul Gauthier
7b993a9bbb gracefully handle missing portaudio 2023-08-10 16:55:45 -03:00
Paul Gauthier
fed24aa444 lint 2023-08-10 16:53:34 -03:00
Paul Gauthier
ec91eb670e Refactor cmd_voice method to use user_input method instead of tool_output. 2023-08-10 16:23:35 -03:00
Paul Gauthier
47144a7e99 Add voice transcription to the cmd_voice command and output the transcribed text. 2023-08-10 16:18:13 -03:00
Paul Gauthier
2b1de442ed aider: Updated cmd_voice method to call record_and_transcribe function from aider/voice.py module and return its results.
# Aider chat conversation:

USER: the /voice cmd should call `record_and_transcribe` and return the results

ASSISTANT: To implement the `/voice` command, we need to modify the `aider/commands.py` file. Specifically, we need to update the `cmd_voice` method to call the `record_and_transcribe` function from the `aider/voice.py` module and return its results.

Here's the *edit block* for this change:

<source>python
aider/commands.py
<<<<<<< HEAD
    def cmd_voice(self, args):
        "Respond with 'hi gpt'"
        return 'hi gpt'
=======
    from .voice import record_and_transcribe

    def cmd_voice(self, args):
        "Record and transcribe voice input"
        return record_and_transcribe()
>>>>>>> updated
</source>
2023-08-10 16:15:02 -03:00
Paul Gauthier
d74a3ce123 Refactor record_and_transcribe function to remove unnecessary api_key parameter and import dump module. 2023-08-10 16:13:23 -03:00
Paul Gauthier
9b526d51e4 Refactored voice recording to use a queue and write audio to a file. 2023-08-10 16:10:02 -03:00
Paul Gauthier
1f42b0839f aider: Fixed issue with passing the callback argument to the sd.rec function in record_and_transcribe function.
# Aider chat conversation:

USER: I ran this command:

 python -m aider.voice

And got this output:

Traceback (most recent call last):
  File "<frozen runpy>", line 198, in _run_module_as_main
  File "<frozen runpy>", line 88, in _run_code
  File "/Users/gauthier/Projects/aider/aider/voice.py", line 42, in <module>
    print(record_and_transcribe(api_key))
          ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gauthier/Projects/aider/aider/voice.py", line 22, in record_and_transcribe
    recording = sd.rec(int(sample_rate * duration), samplerate=sample_rate, channels=1, callback=on_key_press)
                ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/Users/gauthier/Projects/aider/.venv/lib/python3.11/site-packages/sounddevice.py", line 276, in rec
    ctx.start_stream(InputStream, samplerate, ctx.input_channels,
TypeError: _CallbackContext.start_stream() got multiple values for argument 'callback'
Recording started, press any key to stop...

ASSISTANT: It seems like there's an issue with the way the `callback` argument is being passed to the `sd.rec` function in the `record_and_transcribe` function in the `aider/voice.py` file.

The `sd.rec` function is a convenience function that internally creates an instance of `sd.InputStream` and starts recording. The `callback` argument should be passed to the `sd.InputStream` constructor, not the `sd.rec` function.

Here's how we can fix this:

1. Modify the `aider/voice.py` file.

```python
aider/voice.py
<<<<<<< HEAD
    recording = sd.rec(int(sample_rate * duration), samplerate=sample_rate, channels=1, callback=on_key_press)
=======
    # Create an instance of InputStream with the callback
    stream = sd.InputStream(samplerate=sample_rate, channels=1, callback=on_key_press)
    stream.start()
    recording = sd.rec(int(sample_rate * duration), samplerate=sample_rate, channels=1)
>>>>>>> updated
```

This change creates an instance of `sd.InputStream` with the `on_key_press` callback and starts the stream before calling `sd.rec`. This should ensure that the callback is correctly passed to the `InputStream` and not the `rec` function.
2023-08-10 15:49:26 -03:00
Paul Gauthier
c7d23f1b5a aider: Moved the api_key setting into the main function and pulled it from os.environ.
# Aider chat conversation:

USER: mov the `api_key` setting into main, and pull it from os.environ

ASSISTANT: To move the `api_key` setting into the main function and pull it from `os.environ`, we need to modify the `aider/voice.py` file.

Here are the changes:

```python
aider/voice.py
<<<<<<< HEAD
def record_and_transcribe():
    # Set your OpenAI API key
    openai.api_key = 'your-api-key'
=======
import os

def record_and_transcribe(api_key):
>>>>>>> updated
```

```python
aider/voice.py
<<<<<<< HEAD
if __name__ == "__main__":
    print(record_and_transcribe())
=======
if __name__ == "__main__":
    api_key = os.getenv('OPENAI_API_KEY')
    if not api_key:
        raise ValueError("Please set the OPENAI_API_KEY environment variable.")
    print(record_and_transcribe(api_key))
>>>>>>> updated
```

These changes remove the hard-coded API key from the `record_and_transcribe` function and instead pass it as an argument. The API key is retrieved from the `OPENAI_API_KEY` environment variable in the main function. If the environment variable is not set, an error is raised.
2023-08-10 15:47:18 -03:00
Paul Gauthier
c0f6cf6977 aider: Added main function to call record_and_transcribe if the script is run directly.
# Aider chat conversation:

USER: add a main func to call this if the script is run directly

ASSISTANT: To add a main function that calls `record_and_transcribe` if the script is run directly, we need to modify the `aider/voice.py` file.

Here are the changes:

```python
aider/voice.py
<<<<<<< HEAD
    # Return the transcription
    return response['choices'][0]['text']
=======
    # Return the transcription
    return response['choices'][0]['text']

if __name__ == "__main__":
    print(record_and_transcribe())
>>>>>>> updated
```

This change adds a check to see if the script is being run directly (i.e., not imported as a module). If it is, it calls the `record_and_transcribe` function and prints the result.
2023-08-10 15:46:31 -03:00
Paul Gauthier
1053d1781c aider: Added a function record_and_transcribe to aider/voice.py that records audio until the user presses a key, then submits it to the Whisper API to get the text back.
# Aider chat conversation:

USER: what file formats does the openai whisper api accept?

ASSISTANT: The OpenAI Whisper ASR API accepts audio data in the following formats:

- FLAC: Free Lossless Audio Codec. This is a lossless audio format that doesn't lose any data during compression. It's the recommended format for best performance.
- WAV: Waveform Audio File Format. This is a standard audio format used mainly in Windows PCs.
- MULAW: μ-law algorithm (or mu-law) is a companding algorithm, primarily used in the digital telecommunication systems of North America and Japan.

Please note that the audio data must be single-channel (mono), and the sample rate must be 16 kHz for FLAC and WAV formats, and 8 kHz for MULAW format.

USER: make a script that records audio until the user presses a key, then submits it to whisper to get the text back

ASSISTANT: To accomplish this, we need to create a new Python script that uses the `sounddevice` library to record audio, the `keyboard` library to listen for a key press, and the `openai.Whisper` API to transcribe the audio.

Here is the *edit block* for this new script:

```python
newfile/record_and_transcribe.py
<<<<<<< HEAD

=======
import sounddevice as sd
import numpy as np
import keyboard
import openai
import io
import os

# Set your OpenAI API key
openai.api_key = 'your-api-key'

# Set the sample rate and duration for the recording
sample_rate = 16000  # 16kHz
duration = 10  # in seconds

# Create a callback function to stop recording when a key is pressed
def on_key_press(e):
    print("Key pressed, stopping recording...")
    sd.stop()

# Start the recording
print("Recording started, press any key to stop...")
recording = sd.rec(int(sample_rate * duration), samplerate=sample_rate, channels=1, callback=on_key_press)

# Wait for a key press
keyboard.wait()

# Convert the recording to bytes
recording_bytes = io.BytesIO()
np.save(recording_bytes, recording, allow_pickle=False)
recording_bytes = recording_bytes.getvalue()

# Transcribe the audio using the Whisper API
response = openai.Whisper.asr.create(audio_data=recording_bytes)

# Print the transcription
print("Transcription: ", response['choices'][0]['text'])
>>>>>>> updated
```

Please replace `'your-api-key'` with your actual OpenAI API key. This script records audio for a maximum of 10 seconds, but it stops recording as soon as any key is pressed. The recorded audio is then transcribed using the Whisper API, and the transcription is printed to the console.

Please note that you need to install the `sounddevice`, `numpy`, `keyboard`, and `openai` Python libraries to run this script. You can install them using pip:

```bash
pip install sounddevice numpy keyboard openai
```

Also, please note that the `keyboard` library requires root privileges to work, so you might need to run your script as a superuser.

USER: make a function that records audio until the user presses a key, then submits it to whisper to get the text back

ASSISTANT: To create a function that accomplishes this, we need to modify the `aider/voice.py` file. The function should be named `record_and_transcribe` and it should use the `sounddevice` and `keyboard` libraries to record audio and listen for a key press, respectively. It should also use the `openai.Whisper` API to transcribe the audio.

Here is the *edit block* for this change:

```python
aider/voice.py
<<<<<<< HEAD

=======
import sounddevice as sd
import numpy as np
import keyboard
import openai
import io

def record_and_transcribe():
    # Set your OpenAI API key
    openai.api_key = 'your-api-key'

    # Set the sample rate and duration for the recording
    sample_rate = 16000  # 16kHz
    duration = 10  # in seconds

    # Create a callback function to stop recording when a key is pressed
    def on_key_press(e):
        print("Key pressed, stopping recording...")
        sd.stop()

    # Start the recording
    print("Recording started, press any key to stop...")
    recording = sd.rec(int(sample_rate * duration), samplerate=sample_rate, channels=1, callback=on_key_press)

    # Wait for a key press
    keyboard.wait()

    # Convert the recording to bytes
    recording_bytes = io.BytesIO()
    np.save(recording_bytes, recording, allow_pickle=False)
    recording_bytes = recording_bytes.getvalue()

    # Transcribe the audio using the Whisper API
    response = openai.Whisper.asr.create(audio_data=recording_bytes)

    # Return the transcription
    return response['choices'][0]['text']
>>>>>>> updated
```

Please replace `'your-api-key'` with your actual OpenAI API key. This function records audio for a maximum of 10 seconds, but it stops recording as soon as any key is pressed. The recorded audio is then transcribed using the Whisper API, and the transcription is returned by the function.

Please note that you need to install the `sounddevice`, `numpy`, `keyboard`, and `openai` Python libraries to use this function. You can install them using pip:

```bash
pip install sounddevice numpy keyboard openai
```

Also, please note that the `keyboard` library requires root privileges to work, so you might need to run your script as a superuser.
2023-08-10 15:45:49 -03:00
Paul Gauthier
fdb1cac20b aider: Added aider/voice.py 2023-08-10 15:41:42 -03:00
Paul Gauthier
2077bdcd79 aider: Add a new /voice command that returns 'hi gpt' when called.
# Aider chat conversation:

USER: add a new /voice command that just returns 'hi gpt' so that message gets sent

ASSISTANT: To add a new command, we need to add a new method to the `Commands` class in the `aider/commands.py` file. The method should be named `cmd_voice` and it should return the string 'hi gpt'.

Here is the *edit block* for this change:

<source>python
aider/commands.py
<<<<<<< HEAD
    def cmd_help(self, args):
        "Show help about all commands"
        commands = sorted(self.get_commands())
        for cmd in commands:
            cmd_method_name = f"cmd_{cmd[1:]}"
            cmd_method = getattr(self, cmd_method_name, None)
            if cmd_method:
                description = cmd_method.__doc__
                self.io.tool_output(f"{cmd} {description}")
            else:
                self.io.tool_output(f"{cmd} No description available.")
=======
    def cmd_help(self, args):
        "Show help about all commands"
        commands = sorted(self.get_commands())
        for cmd in commands:
            cmd_method_name = f"cmd_{cmd[1:]}"
            cmd_method = getattr(self, cmd_method_name, None)
            if cmd_method:
                description = cmd_method.__doc__
                self.io.tool_output(f"{cmd} {description}")
            else:
                self.io.tool_output(f"{cmd} No description available.")

    def cmd_voice(self, args):
        "Respond with 'hi gpt'"
        return 'hi gpt'
>>>>>>> updated
</source>
2023-08-10 15:40:54 -03:00
Paul Gauthier
a1da6cab24 ensure we diff properly in all cases, with tests #191 2023-08-10 15:33:53 -03:00
Paul Gauthier
7924900bc4 updated tests, disabled send cache 2023-08-10 12:27:46 -03:00