end = idx + num_pad_tokens + 1
        if idx - low_idx[i] < min_token_gap:
            spans[-1][1] = end
        else:
            spans.append([idx, end])
    return ["".join(tokens[start:end]) for start, end in spans]
[docs]class FlareChain(Chain):
    """Chain that combines a retriever, a question generator,
    and a response generator."""
    question_generator_chain: QuestionGeneratorChain
    """Chain that generates questions from uncertain spans."""
    response_chain: _ResponseChain = Field(default_factory=_OpenAIResponseChain)
    """Chain that generates responses from user input and context."""
    output_parser: FinishedOutputParser = Field(default_factory=FinishedOutputParser)
    """Parser that determines whether the chain is finished."""
    retriever: BaseRetriever
    """Retriever that retrieves relevant documents from a user input."""
    min_prob: float = 0.2
    """Minimum probability for a token to be considered low confidence."""
    min_token_gap: int = 5
    """Minimum number of tokens between two low confidence spans."""
    num_pad_tokens: int = 2
    """Number of tokens to pad around a low confidence span."""
    max_iter: int = 10
    """Maximum number of iterations."""
    start_with_retrieval: bool = True
    """Whether to start with retrieval."""
    @property
    def input_keys(self) -> List[str]:
        """Input keys for the chain."""
        return ["user_input"]
    @property
    def output_keys(self) -> List[str]:
        """Output keys for the chain."""
        return ["response"]
    def _do_generation(
        self,
        questions: List[str],
        user_input: str,