Pular para o conteúdo

Respostas com as suas fontes ​

Tradução automática

Esta página foi traduzida automaticamente do inglês e ainda não foi revisada por um falante nativo; correções são bem-vindas no GitHub. Se algo não bater, vale o original em inglês. O código e os resultados são os mesmos do original, importados dos arquivos testados.

Tarefa: uma página que responde perguntas sobre uma loja a partir dos documentos de política dela, e mostra de qual documento veio cada resposta.

yaml
# Recipe: answers from your own documents, with the sources they came from.
paths:
  components: ./components

# The model server is Ollama at http://localhost:11434 unless
# QUANTUM_LLM_BASE_URL says otherwise; the model is this one unless
# QUANTUM_LLM_DEFAULT_MODEL says otherwise.
llm:
  model: phi3

Três arquivos Markdown em knowledge/:

md
# Returns

Returns are accepted within 30 days of delivery, with the receipt. The refund
goes back to the card used for the order.

q:knowledge lê a pasta, a divide em trechos e calcula os embeddings deles. q:llm knowledge="docs" recupera os trechos mais próximos da pergunta e os envia numerados ao modelo, com a instrução de responder só a partir deles e citá-los como [1]. answer_result.sources lista o que foi recuperado; answer_result.grounded diz se a resposta cita algum deles.

xml
<q:component name="Ask">
  <!-- The documents in knowledge/, split into chunks and embedded when the
       page runs. persist="false" keeps the index in memory; without it, it is
       stored in ./.quantum/knowledge and reused until a document changes. -->
  <q:knowledge name="docs" persist="false" chunkSize="300" chunkOverlap="30">
    <q:source type="directory" path="knowledge" pattern="*.md" />
  </q:knowledge>

  <q:set name="question" value="{query.q}" default="" />

  <q:if condition="question">
    <!-- The question retrieves the closest chunks; they reach the model
         numbered, with the instruction to answer only from them and cite
         them like [1]. -->
    <q:llm name="answer" knowledge="docs" top="2">
      <q:message role="user">{question}</q:message>
    </q:llm>
  </q:if>

  <ui:window title="Ask the store">
    <ui:form>
      <ui:input bind="q" value="{question}" placeholder="Your question" />
      <ui:button variant="primary">Ask</ui:button>
    </ui:form>
    <q:if condition="question">
      <ui:text>{answer}</ui:text>
      <q:if condition="answer_result.grounded">
        <ui:text>Sources:</ui:text>
        <q:loop items="{answer_result.sources}" var="s">
          <ui:text>[{s.n}] {s.name}</ui:text>
        </q:loop>
        <q:else>
          <ui:alert variant="warning">This answer cites none of the documents.</ui:alert>
        </q:else>
      </q:if>
    </q:if>
  </ui:window>
</q:component>
xml
<!-- Structural checks, never the model's exact words: the same tests run
     against a real model before every release. -->
<q:test name="the answer comes with the document it is from" page="/">
  <test:visit q="How many days do I have to return an order?" />
  <test:expect text="Sources:" />
  <test:expect text="[1] returns.md" />
</q:test>

<q:test name="another question, another document" page="/">
  <test:visit q="Is shipping free for my order?" />
  <test:expect text="[1] shipping.md" />
</q:test>

<q:test name="no question, no model call" page="/">
  <test:visit />
  <test:expect no-text="Sources:" />
</q:test>
text
tests/ask.test.q
  PASS  the answer comes with the document it is from
  PASS  another question, another document
  PASS  no question, no model call
3 passed, 0 failed

Testado: no CI estes testes rodam contra um servidor de modelos substituto, que responde a partir da primeira fonte que recebe; antes de cada versão eles rodam contra um modelo de verdade (tests/live_ai/test_cookbook_ai.py). Por isso eles conferem a estrutura — qual fonte, qual ferramenta, o que a página mostra quando algo falha — e nunca as palavras do modelo.

Veja IA-2, IA-6 e o guia de IA (em inglês).

Licença MIT · Feito com VitePress