Sometimes when I refactor, I do this manually with an LLM. It is useful in at least two ways: it can reveal better (more canonical) terminology for names (eg: 'antiparallel_line' instead of 'parallel_line_opposite_direction'), and it can also reveal names that could be generalized (eg: 'find_instance_in_list' instead of 'find_animal_instance_in_animals').
1. I ask LLM to describe what the meaning of the variable in the surrounding code
2. Given just the description, I ask the LLM to come up with the best possible variable name
You can check the source code for the actual prompts:
https://github.com/jehna/humanify/blob/eeff3f8b4f76d40adb116...
I'm still waiting for the AST level version control tbh
Asking it to do it on the whole thing, then parsing the output and checking that the AST still matches?
1. It asks the LLM to write a description of what the variable does
2. It asks for a good variable name based on the description from 1.
3. It uses a custom Babel plugin to do a scope-aware rename
This way the LLM only decides the name, but the actual renaming is done with traditional and reliable tools.
Based on it, I went and read the readme. The readme was also excellent, and answered every question I had. Great job, thank you, I'll be trying this.
Edit: I'm currently trying it with a mere 1.2k JS file (openai mode) it's only 70% done after 20 minutes. Even if it works therodically with 50k LOC file, I don't think you should try.
I'm currently working on parallelizing the rename process, which should give orders of magnitude faster processing times for large files.
> Large files may take some time to process and use a lot of tokens if you use ChatGPT. For a rough estimate, the tool takes about 2 tokens per character to process a file:
> echo "$((2 * $(wc -c < yourscript.min.js)))" > So for refrence: a minified bootstrap.min.js would take about $0.5 to un-minify using ChatGPT.
> Using humanify local is of course free, but may take more time, be less accurate and not possible with your existing hardware.
I'm more concerned about if it can actually deobfuscate such large file (context) and generate useful results.
https://arxiv.org/pdf/2405.15793
It uses smart feedback to fix the code when LLMs occasionally do hiccups with the code. You could also have a "supervisor LLM" that asserts that the resulting code matches the specification, and gives feedback if it doesn't.
for (var index = 0; index < inputLength; index += chunkSize) {
Comparing the ASTs is useful though. Perhaps there's a way to combine the approaches - have the LLM convert, compare the ASTs, have the LLM explain the practical differences (if any) in context of the actual implementation and give it a chance to make any changes "more correct". Still not guaranteed to be perfect but significantly more "natural" resulting code.Making the code, fully commenting it and also giving an example after that might cost three times as much
Knowing this raises the question, which is better to feed an LLM source code of ASTs?
The answer is really it depends on the use case, there are tradeoffs. For example keeping comments intact possibly gives the model hints to reason better. On the other side, it can be argued that a pure AST has less noise for the model to be confused by.
There are other tradeoffs as well. For example, any analysis relating to coding styles would require the full source code.
Babel first parses the code to AST, and for each variable the tool:
1. Gets the variable name and surrounding scope as code
2. Asks the LLM to come up with a good name for the given variable name, by looking at the scope where the variable is
3. Uses Babel to make the context-aware rename to AST based on the LLM's response
properties and strings aren't renamed
API access of ChatGPT mode is needed as there are many round trips and it uses advanced API-only tricks to force the LLM output.
For small scripts I've found the output to be very similar between small local models and GPT-4o (judging by a human eye).
+1