U
    hD!                     @  s  d dl mZ d dlZd dlmZmZmZmZmZm	Z	 d dl
Zd dlmZ d dlmZ d dlmZ d dlmZ d dlmZ d d	lmZ d d
lmZ d dlmZ d dlmZ d dlmZm Z m!Z! d dl"m#Z# dddddZ$G dd de#Z%dddddddddZ&G dd deZ'dS )     )annotationsN)AnyDictListOptionalSequenceTuple)CallbackManagerForChainRun)BaseLanguageModel)	AIMessage)StrOutputParser)BasePromptTemplate)Field)BaseRetriever)Runnable)Chain)PROMPTQUESTION_GENERATOR_PROMPTFinishedOutputParser)LLMChainr   zTuple[List[str], List[float]])responsereturnc                 C  s@   g }g }| j d d D ] }||d  ||d  q||fS )z>Extract tokens and log probabilities from chat model response.logprobscontenttokenZlogprob)Zresponse_metadataappend)r   tokens	log_probsr    r   ?/tmp/pip-unpacked-wheel-bo69hh5q/langchain/chains/flare/base.py_extract_tokens_and_log_probs   s    r    c                   @  sB   e Zd ZU dZeZded< eddddZe	ddd	d
Z
dS )QuestionGeneratorChainz4Chain that generates questions from uncertain spans.r   promptboolr   c                 C  s   dS )NFr   )clsr   r   r   is_lc_serializable+   s    z)QuestionGeneratorChain.is_lc_serializable	List[str]c                 C  s
   dddgS )Input keys for the chain.
user_inputcontextr   r   selfr   r   r   
input_keys/   s    z!QuestionGeneratorChain.input_keysN)__name__
__module____qualname____doc__r   r"   __annotations__classmethodr&   propertyr-   r   r   r   r   r!   %   s   
r!   zSequence[str]zSequence[float]floatintr'   )r   r   min_probmin_token_gapnum_pad_tokensr   c                   s   t t ||k d } fdd|D }t|dkr:g S |d |d | d gg}t|dd  D ]@\}}	|	| d }
|	||  |k r|
|d d< qd||	|
g qd fdd|D S )Nr   c                   s    g | ]}t d  | r|qS )z\w)research).0ir   r   r   
<listcomp>=   s      z)_low_confidence_spans.<locals>.<listcomp>   c                   s"   g | ]\}}d   || qS ) )join)r<   startendr>   r   r   r?   G   s     )npwhereexplen	enumerater   )r   r   r7   r8   r9   Z_low_idxZlow_idxZspansr=   idxrE   r   r>   r   _low_confidence_spans5   s    rL   c                   @  s   e Zd ZU dZded< ded< eedZded< ded	< d
Zded< dZ	ded< dZ
ded< dZded< dZded< eddddZeddddZdddddd d!d"Zddddddd#d$d%Zd2d'd(d'd)d*d+Zed3d-dd.d d/d0d1Zd&S )4
FlareChainzChain that combines a retriever, a question generator,
    and a response generator.

    See [Active Retrieval Augmented Generation](https://arxiv.org/abs/2305.06983) paper.
    r   question_generator_chainresponse_chain)default_factoryr   output_parserr   	retrieverg?r5   r7      r6   r8      r9   
   max_iterTr#   start_with_retrievalr'   r$   c                 C  s   dgS )r(   r)   r   r+   r   r   r   r-   d   s    zFlareChain.input_keysc                 C  s   dgS )zOutput keys for the chain.r   r   r+   r   r   r   output_keysi   s    zFlareChain.output_keysstrr	   zTuple[str, bool])	questionsr)   r   _run_managerr   c                 C  s~   |  }g }|D ]}|| j| qddd |D }| j|||dd|i}	t|	trf|	j}	| j	
|	\}
}|
|fS )Nz

c                 s  s   | ]}|j V  qd S )N)Zpage_content)r<   dr   r   r   	<genexpr>y   s     z,FlareChain._do_generation.<locals>.<genexpr>r)   r*   r   	callbacks)	get_childextendrR   invokerC   rO   
isinstancer   r   rQ   parse)r,   rZ   r)   r   r[   r_   ZdocsZquestionr*   resultmarginalfinishedr   r   r   _do_generationn   s     
zFlareChain._do_generation)low_confidence_spansr[   r)   r   initial_responser   c           
        s    fdd|D }|  }tjtrLjj||d}fdd|D }	njj|d|id}	|jd|	 dd	d
 |	||S )Nc                   s   g | ]} |d qS ))r)   Zcurrent_responseZuncertain_spanr   )r<   span)rj   r)   r   r   r?      s
   z,FlareChain._do_retrieval.<locals>.<listcomp>)r_   c                   s   g | ]}| j jd   qS )r   )rN   rX   )r<   outputr+   r   r   r?      s   r_   )configzGenerated Questions: Zyellow
colorrE   )r`   rc   rN   r   applybatchon_textrh   )
r,   ri   r[   r)   r   rj   Zquestion_gen_inputsr_   Zquestion_gen_outputsrZ   r   )rj   r,   r)   r   _do_retrieval   s,     
   zFlareChain._do_retrievalNzDict[str, Any]z$Optional[CallbackManagerForChainRun])inputsrun_managerr   c                 C  s  |p
t  }|| jd  }d}t| jD ]}|jd| ddd |d|d}t| j|d|	 i\}}	t
||	| j| j| j}
| d	 d| }|
s|}| j|\}}|r(| jd |i  S q(| |
||||\}}| d	 | }|r( qq(| jd |iS )
Nr   rB   zCurrent Response: Zbluern   ro   r^   r_    )r	   Zget_noop_managerr-   rangerV   rs   r    rO   rb   r`   rL   r7   r8   r9   striprC   rQ   rd   rX   rt   )r,   ru   rv   r[   r)   r   r=   _inputr   r   ri   rj   Zfinal_responserg   rf   r   r   r   _call   sR       
zFlareChain._call    r
   r   )llmmax_generation_lenkwargsr   c                 K  sf   zddl m} W n tk
r,   tdY nX ||ddd}t|B }t|B t B }| f ||d|S )aH  Creates a FlareChain from a language model.

        Args:
            llm: Language model to use.
            max_generation_len: Maximum length of the generated response.
            kwargs: Additional arguments to pass to the constructor.

        Returns:
            FlareChain class with the given language model.
        r   )
ChatOpenAIz_OpenAI is required for FlareChain. Please install langchain-openai.pip install langchain-openaiT)Z
max_tokensr   Ztemperature)rN   rO   )Zlangchain_openair   ImportErrorr   r   r   )r%   r}   r~   r   r   rO   Zquestion_gen_chainr   r   r   from_llm   s    
zFlareChain.from_llm)N)r|   )r.   r/   r0   r1   r2   r   r   rQ   r7   r8   r9   rV   rW   r4   r-   rX   rh   rt   r{   r3   r   r   r   r   r   rM   J   s*   
% 0 rM   )(
__future__r   r:   typingr   r   r   r   r   r   ZnumpyrF   Zlangchain_core.callbacksr	   Zlangchain_core.language_modelsr
   Zlangchain_core.messagesr   Zlangchain_core.output_parsersr   Zlangchain_core.promptsr   Zlangchain_core.pydantic_v1r   Zlangchain_core.retrieversr   Zlangchain_core.runnablesr   Zlangchain.chains.baser   Zlangchain.chains.flare.promptsr   r   r   Zlangchain.chains.llmr   r    r!   rL   rM   r   r   r   r   <module>   s$    
