Replies: 7 comments 13 replies
|
I think 2 is the most reasonable way forward. I've been doing this for spectroscopy-lib and dynamics-app (except I haven't reached the human review stage) and it is so much faster and better than handcrafting that I don't think we can justify not doing it. Based on my progress on dynamics-lib, LLMs have in a week produced what would take me more than a year. Perhaps this is what you mean by sign-off, but just wanted to clarify: I think it's important that the human who used the LLM should take full responsibility for the code they produced. That should also encourage us to scrutinize our own LLM-generatede code. As for the questions:
Some thoughts from my last few weeks of vibes: it requires quite a bit of expert guidance to produce good results, so we are not (yet) obsolete. The templates and asking LLMs to use similar structures as existing libraries/apps helps a lot. For spectroscopy-lib, I have the luxury that I'm essentially reproducing Horace functionality, so I can test the code extensively against well-tested human-written code in a different language. Such tests will become ever more important, also so that our users will trust our code. An adjacent but important thought: right now we each own one product. This needs to change as soon as possible, because right now, reviewing someone else's code can feel bad, because it means taking away time from "our own" work. In contrast, every time someone has written code for corelib that I use, or when Andrew has done work on dynamics-lib/ helped me with templates, I've been very motivated to review it, since I need it and it helps me. |
|
FWIW: My personal approach is a complex version of 2 - Mixture of LLM and human. I am trying to address the non-deterministic nature of LLM results by having them converge on both the design document and code implemented. I start with writing requirements and asking Fable to create a detailed design document (as an md file) Only then will I start implementation - based on the design doc I write the general structure of the classes/modules/methods, functionality and layout. Then, ask Fable to fill this structure with docstrings, comments, typehints and address edge cases etc. The docs/unit tests are entirely LLM written. The implementation review follows the design doc review, with multiple stages until convergence. (Only then, I hand it over to Christian, who, after 120 comments and a complete rewrite agrees to merge it... 😆 ) The following chart shows what would the fully black-box project pipeline be: flowchart TD
A[HUMAN: Write requirements] --> B[Fable: draft detailed design `doc.md`]
B --> C[Reviewer LLM: find problems<br/>DeepSeek / Qwen / Grok / GPT]
C --> D[Fable: scrutinize review,<br/>update design doc]
D --> E{Both LLMs agree:<br/>all issues solved<br/>or non-existent?}
E -- no --> C
E -- yes --> F[Fable: write structure —<br/>classes, modules, methods,<br/>functionality, layout]
F --> G[Fable: fill structure —<br/>docstrings, comments,<br/>typehints, edge cases]
G --> H[LLM: write unit tests + docs]
H --> I[Reviewer LLM: review implementation]
I --> J[Fable: scrutinize review,<br/>update code]
J --> K{Convergence?}
K -- no --> I
K -- yes --> L[HUMAN: accept and consider done]
|
|
I agree that a human must take responsibility for the final result. However, I do not think this has to mean that human reviews all the final code and tests line by line. The scale and speed of development have changed. In this discussion, we already have an example where LLMs produced in one week what would previously have taken more than a year. A complete human review may still work for a small project, but it will not scale to large projects or when one person needs to contribute to several projects growing in parallel. I can no longer keep track of all the diffraction-related code I wrote myself, and the project is still far from its planned scope. Human reading speed will become the main bottleneck, while reading everything still does not guarantee that every problem will be found. I am in favour of the following model:
This is not about blindly trusting a black box. It means moving human control to a level that can scale: specifications, architecture, independent verification, and final sign-off. Reading selected parts of the code is still useful for learning, debugging, and checking critical areas, but it should not be the only mandatory quality check for every LLM-generated line of code. We should also not keep an inefficient process today simply because LLMs may become unavailable or too expensive in the future. We do not organise our work around the possibility that computers or compilers may disappear. LLMs are becoming a normal part of software development, and our role is gradually changing from writing and reading every line of code to writing precise specifications and verifying that the result satisfies them. |
|
After thinking more about potential ramification, I don't think we can justify choosing a single methodology. For our technique-specific libs/apps the fully AI-autonomous solution might be useful in terms of huge productivity boost and well defined requirement list, which leads itself to a more or less "black box" solution. For modules which we all use and rely on, like |
We cannot assume, that we will have the same level of access to LLMs in the future (or at least to good models at good prices). So we need to be cautious with its outputs: we need to handhold LLMs during design and review iterations, somehow find a way to stay openminded and outside of LLMs suggestions during these iterations and maybe formalize/review our code specification? |
|
I think having only 1 way of mixing LLM with human work is a harsh over-simplification. I am personally not in favour of your proposed mixed way of coding, too much LLM for me, but I still want to use LLMs where I believe it is beneficial. How I think LLM's should be used in code:
I think this is the only way to use LLMs to write code which can still be maintained by humans. And until LLMs become deterministic (they never will be) I think we NEED to write code which CAN be maintained by humans. |
|
From https://blog.rust-lang.org/inside-rust/2026/08/05/rust-langrust-is-adopting-an-llm-policy/ as posted in the scipp slack and forwarded by Torben: Which on the surface sounds fine, but what does If I create a top level module/class/method structure and ask LLM to fill it with code - is this creation or merely suggestion? |
Uh oh!
There was an error while loading. Please reload this page.
We started this discussion recently, so let's formalize it with everyone's opinion.
We DO need a consensus, since we review each other's code and it will become more and more difficult when the bulk of it comes from the non-deterministic LLM engines.
Let's assume we have three ways of writing code with LLMs:
Vibecoding for the win
Humans create the list of requirements.
LLMs create the design, the code, the tests and the docs.
Humans only interact on the receiving end by scrutinizing the ready product for functionality and functional tests for scientific correctness.
Unit tests and code itself are assumed to be internally consistent.
Mixture of LLMs and handcrafted code (PR pipeline)
Humans create the list of requirements
LLMs create the design.
Humans review the design and sign it off
LLMs write the code, unit tests and docs
(other) LLMs review the code, unit tests and docs
Humans review LLM's reviewed/corrected code and docs
Humans implement functional tests for scientific correctness
Handcrafted code. As done back in the stone age of 2023.
These can be summarised in a simple table.
The questions to be answered:
Maybe we should be assigning risks for each row, in terms of the LLM reliance?
All reactions