question-answer-advisor

QuestionAnswerAdvisor

  • 의존성
implementation "org.springframework.ai:spring-ai-advisors-vector-store"
  • vector store에는 llm이 모르는 정보가 들어있다. user query가 들어왔을때, QuestionAnswerAdvisor는 vector store에 query를 날려서 user query에 관련된 documents를 찾아온다.
    • documents는 llm이 답변을 생성하기 위한 context로써 사용된다.
ChatResponse response = ChatClient.builder(chatModel)
        .build().prompt()
       
.advisors(QuestionAnswerAdvisor.builder(vectorStore).build())
        .user(userText)
        .call()
        .chatResponse();
  • QuestionAnswerAdvisor는 vector store의 모든 document를 대상으로 유사도 검색을 수행한다. SearchRequest를 사용해서 SQL 형식의 filtering을 할 수 있다.
var qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
        .searchRequest(SearchRequest.builder().similarityThreshold(0.8d).topK(6).build()) // 80% 이상 유사한 document 상위 6개로 filtering
        .build();

Dynamic Filter Expressions

  • FILTER_EXPRESSION를 사용해서 runtime이 유연한 filtering을 할 수 있다.
ChatClient chatClient = ChatClient.builder(chatModel)
    .defaultAdvisors(QuestionAnswerAdvisor.builder(vectorStore)
        .searchRequest(SearchRequest.builder().build())
        .build())
    .build();

// Update filter expression at runtime
String content = this.chatClient.prompt()
    .user("Please answer my question XYZ")
    .advisors(a -> a.param(QuestionAnswerAdvisor.FILTER_EXPRESSION, "type == 'Spring'"))
    .call()
    .content();

Custom Template

  • QuestionAnswerAdvisor는 기본 prompt template을 제공하지만 .promptTemplate() 빌더 메서드를 통해서 Custom을 할 수 있다.
  • placeholder
    • query: user query
    • quersion_answer_context: 검색 결과 documents
PromptTemplate customPromptTemplate = PromptTemplate.builder()
    .renderer(StTemplateRenderer.builder().startDelimiterToken('<').endDelimiterToken('>').build())
    .template("""
            <query>

            Context information is below.

			---------------------
			<question_answer_context>
			---------------------

			Given the context information and no prior knowledge, answer the query.

			Follow these rules:

			1. If the answer is not in the context, just say that you don't know.
			2. Avoid statements like "Based on the context..." or "The provided information...".
            """)
    .build();

    String question = "Where does the adventure of Anacletus and Birba take place?";

    QuestionAnswerAdvisor qaAdvisor = QuestionAnswerAdvisor.builder(vectorStore)
        .promptTemplate(customPromptTemplate)
        .build();

    String response = ChatClient.builder(chatModel).build()
        .prompt(question)
        .advisors(qaAdvisor)
        .call()
        .content();