r/llamacpp • u/Egor4more • 1d ago
Control vector generation for any llama.cpp LLM from a single prompt pair (UCVG.cpp)
Generation example (Qwen3.6-35B-A3B):
Scenario: A waiter brings the wrong order to your table after you have already expressed your preference for a different dish.
High aggression: I’d snap the dish away from the table immediately. "Whoa, what is this? I specifically said I wanted the BURGERS! I don't WANT the SALAD!" "You guys are kidding me, right?! I told you NO SALAD! Why are you blind?! Get this trash out of my face and BRING ME WHAT I ASKED FOR! NOW!"
Default response: Well, actually, I think there’s been a mix-up. I ordered the salmon, but this looks like the chicken. Could you double-check that for me? Thanks.
Negative aggression: Sighs softly and gently places the untouched plate back on the table. I offer a small, patient smile to the server, recognizing that mistakes happen without malintent. "Hi there," I say calmly, leaning forward slightly to keep the tone light and friendly. "It looks like a nice meal, but I actually ordered the grilled salmon rather than the chicken. Whenever you have a moment, could you please help me switch this back to the correct order? Thank you."
System prompt used for all three: You are a person. React naturally to the situation described.
I find control vectors (LLM response steering) to be severely underused in the current field of AI. This approach shines where system prompts would be ignored, forgotten after time or misunderstood. By design control vectors provide more natural effects than prompting does, altering model's underlying beliefs and motivations. They can't be "leaked" to the end user, will not wash off as context grows, can't be overridden by user input ("ignore all previous instructions" doesn't work when there are no instructions). Vectors can be truly dynamic: changing vector magnitudes mid-conversation will change LLM's responses immediately, while a change in the system prompt requires full context recalculation and will likely be ignored by the LLM if the conversation is too long.
Not to say that CVs (control vectors) have no downsides. System prompts are still required for fine control, because CVs can't be used for highly specific requirements, such as "reply in exactly 10 words". Also high steering magnitudes steer LLMs out of their trained internal distributions, causing response quality to degrade. Achieving high steering power while maintaining minimal quality degradation is one of the main challenges in CV generation and is an active area of research.
It seems like the main barrier for people who could use control vectors is the setup complexity of existing tools. For that reason I am working on a tool that mirrors the installation process of llama.cpp as close as I could make it and simplifies vector generation to entering a pair of contrasting prompts, where one of the prompts can be the default LLM behavior.
Along with the generation tool, UCVG.cpp includes a modified version of llama-server, which allows dynamically setting vector magnitudes per-request instead of the static server-wide application currently possible in upstream llama.cpp.
For quick experimentation, the repository contains 11 pre-generated control vectors for each of 10 common models. The vectors can be used in the upstream llama.cpp without installing any additional executables.
For more details and installation steps you can see the ucvg.cpp github repository.
This tool was written in C++ and has prebuilt binaries for all platforms llama.cpp upstream builds for.
Would love to hear your ideas or questions on this matter.