4个版本
0.6.4 | 2024年5月22日 |
---|---|
0.6.3 | 2024年5月12日 |
0.6.2 | 2024年5月12日 |
0.1.3 | 2023年10月3日 |
#1381 在 过程宏
用于 chatdbg
14KB
ChatDBG
作者:Emery Berger,Stephen Freund,Kyla Levin,Nicolas van Kempen(按字母顺序排列)
ChatDBG是一个基于AI的调试助手,用于C/C++/Python/Rust代码,它将大型语言模型集成到标准调试器(pdb
、lldb
、gdb
和windbg
)中,以帮助您调试代码。使用ChatDBG,您可以与调试器进行对话,对程序提出开放式问题,例如为什么x为null?
。ChatDBG将接管调试器以回答您的查询。ChatDBG可以提供错误诊断和建议修复。
据我们所知,ChatDBG是第一个自动执行根本原因分析并提供建议修复的调试器。
观看ChatDBG的实际应用!
在 test-overflow.cpp 上的LLDB | 在 test-overflow.cpp 上的GDB | 在 bootstrap.py 上的Pdb |
---|---|---|
有关技术细节和完整评估,请参阅我们的arXiv论文,ChatDBG:人工智能调试助手(PDF)。
[!注意]
ChatDBG支持
pdb
、lldb
和gdb
,功能已完善;我们目前正在将这些调试器的功能移植到其他调试器。
安装
[!重要]
ChatDBG目前需要连接到OpenAI账户。您的账户需要有正余额才能使用(查看余额)。如果您从未购买过积分,您需要购买至少1美元的积分(如果您在2023年8月13日之前创建了API账户)或0.50美元(如果您有较新的API账户),以便访问ChatDBG使用的GPT-4。在此获取密钥。
一旦您有了API密钥,将其设置为名为
OPENAI_API_KEY
的环境变量。export OPENAI_API_KEY=<your-api-key>
使用pip
安装ChatDBG(如果您正在调试Python、C或C++代码,都需要这样做)
python3 -m pip install chatdbg
如果您使用ChatDBG调试Python程序,则已完成。如果您想使用ChatDBG通过gdb
或lldb
调试原生代码,请按照以下安装说明操作。
作为lldb
扩展安装
lldb安装说明
通过运行以下命令将ChatDBG安装到lldb调试器中
Linux
python3 -m pip install ChatDBG
python3 -c 'import chatdbg; print(f"command script import {chatdbg.__path__[0]}/chatdbg_lldb.py")' >> ~/.lldbinit
如果您遇到错误,您可能正在使用较旧的LLVM版本。按照以下步骤更新到最新版本
sudo apt install -y lsb-release wget software-properties-common gnupg
curl -sSf https://apt.llvm.org/llvm.sh | sudo bash -s -- 18 all
# LLDB now available as `lldb-18`.
Mac
xcrun python3 -m pip install ChatDBG
xcrun python3 -c 'import chatdbg; print(f"command script import {chatdbg.__path__[0]}/chatdbg_lldb.py")' >> ~/.lldbinit
这将把ChatDBG作为LLVM扩展安装。
作为gdb
扩展安装
gdb安装说明
通过运行以下命令将ChatDBG安装到gdb调试器中
python3 -m pip install ChatDBG
python3 -c 'import chatdbg; print(f"source {chatdbg.__path__[0]}/chatdbg_gdb.py")' >> ~/.gdbinit
这将把ChatDBG作为GDB扩展安装。
作为WinDBG
扩展安装
WinDBG安装说明
- 安装WinDBG:如果尚未安装WinDBG,请按照此处的说明操作。
- 安装
vcpkg
:如果尚未安装vcpkg,请按照此处的说明操作。 - 安装Windows调试工具:从此处安装Windows SDK并勾选复选框
Debugging Tools for Windows
。 - 导航到
src\chatdbg
目录:cd src\chatdbg
- 安装所需依赖项:运行
vcpkg install
- 构建chatdbg.dll扩展:运行
mkdir build & cd build & cmake .. & cmake --build . & cd ..
使用ChatDBG:
- 在WinDBGX中加载
- 运行
windbgx your_executable_here.exe
- 点击菜单项
查看
->命令浏览器
- 在命令浏览器中输入
.load debug\chatdbg.dll
- 运行
- 在运行代码并遇到异常/信号后
- 在命令浏览器中输入
!why
- 在命令浏览器中输入
用法
调试Python
要使用ChatDBG调试Python程序,只需按照以下方式运行Python脚本
chatdbg -c continue yourscript.py
ChatDBG 是标准 Python 调试器 pdb
的扩展。与 pdb
类似,当您的脚本遇到未捕获的异常时,ChatDBG 将进入事后调试模式。
与其他调试器不同,您可以使用 why
命令来询问 ChatDBG 为什么您的程序失败,并获得建议的修复方案。在 LLM 响应后,您可以发出附加的调试命令或通过输入任何其他文本继续对话。
IPython 和 Jupyter 支持
要将 ChatDBG 作为 IPython 或 Jupyter Notebook 的默认调试器,请创建一个 IPython 配置文件,然后在启动时添加必要的扩展。(如果您已经有了自定义的配置文件,则需要根据需要修改这些行。)
ipython profile create
echo "c.InteractiveShellApp.extensions = ['chatdbg.chatdbg_pdb', 'ipyflow']" >> ~/.ipython/profile_default/ipython_config.py
在命令行中,您可以运行
ipython --pdb yourscript.py
在 Jupyter 中,使用 ipyflow 内核 运行您的笔记本,并在文件顶部包含此行魔法。
%pdb
调试原生代码(C、C++ 或 Rust)lldb / gdb)
要使用 ChatDBG 与 lldb
或 gdb
,只需用您的选择调试器运行原生代码(带有 -g
选项进行调试符号编译),当它崩溃时,询问 why
。这也适用于事后调试(当您使用 -c
选项加载核心时)。
原生调试器的工作方式与 Pdb 略有不同。在调试器对您的提问做出响应后,您将进入 ChatDBG 的命令循环,如 (ChatDBG chatting)
提示所示。您可以继续发出调试命令,并且可以通过以 "chat" 开始的消息向 LLM 发送额外消息。完成时,键入 quit
返回到调试器的主命令循环。
调试 Rust 程序
要使用 ChatDBG 与 Rust,您需要执行两个步骤:修改您的 Cargo.toml
文件并在您的源程序中添加一行。
- 将此添加到您的
Cargo.toml
文件
[dependencies]
chatdbg = "0.6.2"
[profile.dev]
panic = "abort"
[profile.release]
panic = "abort"
- 在您的程序中,将
#[chatdbg::main]
属性应用于main
函数
#[chatdbg::main]
fn main() {
现在您可以使用 gdb
或 lldb
调试您的 Rust 代码。
示例
ChatDBG 示例在lldb
(ChatDBG lldb) run
Process 85494 launched: '/Users/emery/git/ChatDBG/test/a.out' (arm64)
TEST 1
TEST -422761288
TEST 0
TEST 0
TEST 0
TEST 0
TEST 0
TEST 0
Process 85494 stopped
* thread #1, queue = 'com.apple.main-thread', stop reason = EXC_BAD_ACCESS (code=1, address=0x100056200)
frame #0: 0x0000000100002f64 a.out`foo(n=8, b=1) at test.cpp:7:22
4 int x[] = { 1, 2, 3, 4, 5 };
5
6 void foo(int n, float b) {
-> 7 cout << "TEST " << x[n * 10000] << endl;
8 }
9
10 int main()
Target 0: (a.out) stopped.
询问 why
让 ChatDBG 提供一个有用的解释为什么这个程序失败,并建议一个修复方案
(ChatDBG lldb) why
The root cause of this error is accessing an index of the array `x`
that is out of bounds. In `foo()`, the index is calculated as `n *
10000`, which can be much larger than the size of the array `x` (which
is only 5 elements). In the given trace, the program is trying to
access the memory address `0x100056200`, which is outside of the range
of allocated memory for the array `x`.
To fix this error, we need to ensure that the index is within the
bounds of the array. One way to do this is to check the value of `n`
before calculating the index, and ensure that it is less than the size
of the array divided by the size of the element. For example, we can
modify `foo()` as follows:
```
void foo(int n, float b) {
if (n < 0 || n >= sizeof(x)/sizeof(x[0])) {
cout << "ERROR: Invalid index" << endl;
return;
}
cout << "TEST " << x[n] << endl;
}
```
This code checks if `n` is within the valid range, and prints an error
message if it is not. If `n` is within the range, the function prints
the value of the element at index `n` of `x`. With this modification,
the program will avoid accessing memory outside the bounds of the
array, and will print the expected output for valid indices.
ChatDBG 示例在 Python(pdb)
Traceback (most recent call last):
File "yourscript.py", line 9, in <module>
print(tryme(100))
File "yourscript.py", line 4, in tryme
if x / i > 2:
ZeroDivisionError: division by zero
Uncaught exception. Entering post mortem debugging
Running 'cont' or 'step' will restart the program
> yourscript.py(4)tryme()
-> if x / i > 2:
询问 why
让 ChatDBG 提供一个有用的解释为什么这个程序失败,并建议一个修复方案
(ChatDBG Pdb) why
The root cause of the error is that the code is attempting to
divide by zero in the line "if x / i > 2". As i ranges from 0 to 99,
it will eventually reach the value of 0, causing a ZeroDivisionError.
A possible fix for this would be to add a check for i being equal to
zero before performing the division. This could be done by adding an
additional conditional statement, such as "if i == 0: continue", to
skip over the iteration when i is zero. The updated code would look
like this:
def tryme(x):
count = 0
for i in range(100):
if i == 0:
continue
if x / i > 2:
count += 1
return count
if __name__ == '__main__':
print(tryme(100))
依赖项
~260–700KB
~17K SLoC