Closed andreadimaio closed 1 month ago
cc @cescoffier
If instead of injecting the ChatMemoryStore
, we inject a list of ChatMessage
, can't we use plain Qute to format the prompt?
{#for m in chatHistory}
{#if m.type.name() == "USER"}
User: {m.text()}
{/if}
{#if m.type.name() == "AI"}
Assistant: {m.text()}
{/if}
{/for}
I vonluntary filtered out system and tools.
Being able to use something like Jinja is very interesting, but from my point of view, I prefer to keep the prompt simple and just use a placeholder.
We could imagine a fragment or an include to achieve this. HEre is an example using an "include":
@SystemMessage("""
Given the following conversation and a follow-up question, rephrase the follow-up question to be a
standalone question, in its original language. Return the follow-up question VERBATIM if the
question is changing the topic with respect to the conversation. It is **VERY IMPORTANT** to only
output the rephrased standalone question; do not add notes or comments in the output.
Chat History:
{#include history limit=10}""")
public String rephrase(ChatMemoryStore chatHistory, @UserMessage String question);
The "included" template named "history" would have access to the chatHistory
object. In my example, I passed an extra optional parameter, if, for example, we want to limit the number of messages.
The history template would be a separated file:
{#for m in chatHistory}
{#if m.type.name() == "USER"}
User: {m.text()}
{/if}
{#if m.type.name() == "AI"}
Assistant: {m.text()}
{/if}
{/for}
(I didn't include the limit
support, but you see the idea).
I'm not against using a toString
on the chat memory object, but we need to be very careful with this approach as it can end badly (object reference, cycles, etc.). The template approach is similar to what quarks langchain4j is already doing.
BTW, the quarkus-langchain4j prompts are already templates. So, what I proposed should work already.
It uses Qute.
I tried this prompt and it works:
@SystemMessage("""
Given the following conversation and a follow-up question, rephrase the follow-up question to be a
standalone question, in its original language. Return the follow-up question VERBATIM if the
question is changing the topic with respect to the conversation. It is **VERY IMPORTANT** to only
output the rephrased standalone question; do not add notes or comments in the output.
Chat History:
{#for m in chatHistory}
{#if m.type.name() == "USER"}
User: {m.text()}
{/if}
{#if m.type.name() == "AI"}
Assistant: {m.text()}
{/if}
{/for}""")
public String rephrase(List<ChatMessage> chatHistory, @UserMessage String question);
This is not exactly what I wrote in my proposal, but in the end it works just fine (without adding any more complexity).
We could even make chatHistory
available by default to the template.
WDYT?
Something like {response_schema}
? Cool!
Something like {response_schema}
Sorry, I am not following this :). Care to elaborate?
{response_schema}
is a placeholder that you can use directly in the template. If I understand you correctly, you want to give the developers a new placeholder like chat_history
, which will automatically be converted to the user/assistant format. If the developer wants to change the format they can use Qute. Is that right? :)
Oh, I didn't remember we had that placeholder!
Yeah, that's exactly the intent of what I proposed.
I like it! :)
@geoand you learn very quickly about {response_schema} as soon you do not use OpenAI:-)
😄
I have opened https://github.com/quarkiverse/quarkus-langchain4j/pull/887. Would you like to add a commit that adds a test and the docs you have in mind for your use case?
Thanks
Discussed in https://github.com/quarkiverse/quarkus-langchain4j/discussions/879