U
    h*                     @   s   d Z ddlZddlmZ ddlmZmZmZmZ ddl	m
Z
mZ ddlmZ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mZ eeZG dd deZG dd deZG dd deZdS )z.Tools for interacting with a Power BI dataset.    N)perf_counter)AnyDictOptionalTuple)AsyncCallbackManagerForToolRunCallbackManagerForToolRun)Field	validator)BaseTool)_import_tiktoken)BAD_REQUEST_RESPONSEDEFAULT_FEWSHOT_EXAMPLESRETRY_RESPONSE)PowerBIDataset
json_to_mdc                   @   sF  e Zd ZU dZdZeed< dZeed< eed< e	ddZ
eed	< eZee ed
< e	eddZeeef ed< dZeed< dZeed< dZee ed< G dd dZedeedddZeee dddZd&eee eedddZd'eee eedddZeeef eee ee f d d!d"Zeee ef d#d$d%Z!dS )(QueryPowerBIToolz%Tool for querying a Power BI Dataset.Zquery_powerbinamea  
    Input to this tool is a detailed question about the dataset, output is a result from the dataset. It will try to answer the question using the dataset, and if it cannot, it will ask for clarification.

    Example Input: "How many rows are in table1?"
    description	llm_chainTexcludepowerbiexamples)default_factoryr   session_cache   max_iterationsi  output_token_limitNtiktoken_model_namec                   @   s   e Zd ZdZdS )zQueryPowerBITool.ConfigTN__name__
__module____qualname__Zarbitrary_types_allowed r$   r$   J/tmp/pip-unpacked-wheel-9gdii04g/langchain_community/tools/powerbi/tool.pyConfig*   s   r&   )r   returnc                 C   s(   |j jD ]}|dkrtd|j jq|S )z8Make sure the LLM chain has the correct input variables.)
tool_inputtablesschemasr   zrLLM chain for QueryPowerBITool must have input variables ['tool_input', 'tables', 'schemas', 'examples'], found %s)promptZinput_variables
ValueError)clsr   varr$   r$   r%   "validate_llm_chain_input_variables-   s    z3QueryPowerBITool.validate_llm_chain_input_variables)r(   r'   c                 C   s   || j krdS | j | S )zCheck if the input is present in the cache.

        If the value is a bad request, overwrite with the escalated version,
        if not present return None.N)r   )selfr(   r$   r$   r%   _check_cache:   s    
zQueryPowerBITool._check_cache)r(   run_managerkwargsr'   c              
   K   s  |  | }r td|| |S z@td| | jj|| j | j | j	|rV|
 ndd}W n@ tk
r } z"d| | j|< | j|  W Y S d}~X Y nX |dkr|| j|< | j| S td| t }| jj|d}t }	td	| td
|	| d | |\}
}|dk	r<d|kr<d| j|< | j| S |dd}|rz|| jk rz| jtj|||d||d dS |
r|
n
tj|d| j|< | j| S ):Execute the query, return the results or an error message.Found cached result for %s: %s%Running PBI Query Tool with input: %sNr(   r)   r*   r   	callbacksError on call to LLM: I cannot answer thiszPBI Query:
%scommandPBI Result: %sPBI Query duration: 0.6fTokenExpiredzCAuthentication token expired or invalid, please try reauthenticate.
iterationsr   r(   queryerror   r(   r2   rA   rD   )r1   loggerdebuginfor   Zpredictr   get_table_namesget_schemasr   	get_child	Exceptionr   r   run_parse_outputgetr   _runr   formatr   r0   r(   r2   r3   cacherC   exc
start_time
pbi_resultZend_timeresultrD   rA   r$   r$   r%   rR   C   sV    
 


  	zQueryPowerBITool._runc              
      s  |  | }r&td|| | dS zFtd| | jj|| j | j | j	|r\|
 nddI dH }W n@ tk
r } z"d| | j|< | j|  W Y S d}~X Y nX |dkr|| j|< | j| S td| t }| jj|d	I dH }t }	td
| td|	| d | |\}
}|dk	rXd|ksDd|krXd| j|< | j| S |dd}|r|| jk r| jtj|||d||d dI dH S |
r|
n
tj|d| j|< | j| S )r4   r5   z3, from cache, you have already asked this question.r6   Nr7   r9   r:   zPBI Query: %sr;   r=   r>   r?   r@   
TokenErrorzkAuthentication token expired or invalid, please try to reauthenticate or check the scope of the credential.rA   r   rB   rE   rF   rG   )r1   rH   rI   rJ   r   Zapredictr   rK   rL   r   rM   rN   r   r   ZarunrP   rQ   r   _arunr   rS   r   rT   r$   r$   r%   r[   y   sV    
 


  	zQueryPowerBITool._arun)rX   r'   c                 C   s   d|krt|d d d d d }t |dkr:td dS t|}| |\}}|rld| d| j d	d
fS |d
fS d|krd|d krd|d d krd
|d d d d d fS d
|d fS d
|fS )z2Parse the output of the query to a markdown table.resultsr   r)   rowsz%0 records in result, query was valid.)Nz^0 rows returned, this might be correct, but please validate if all filter values were correct?z[Result too large, please try to be more specific or use the `TOPN` function. The result is z tokens long, the limit is z tokens.NrD   z	pbi.errordetailsZdetail)lenrH   rJ   r   _result_too_larger   )r0   rX   r]   rY   Ztoo_longlengthr$   r$   r%   rP      s(    

zQueryPowerBITool._parse_output)rY   r'   c                 C   sD   | j r@t }|| j }t||}td| || jk|fS dS )z!Tokenize the output of the query.zResult length: %s)Fr   )r   r   Zencoding_for_modelr_   encoderH   rJ   r   )r0   rY   Z	tiktoken_encodingra   r$   r$   r%   r`      s    z"QueryPowerBITool._result_too_large)N)N)"r!   r"   r#   __doc__r   str__annotations__r   r   r	   r   r   r   r   r   dictr   r   r   intr   r   r&   r
   r/   r1   r   rR   r   r[   r   rP   boolr`   r$   r$   r$   r%   r      sD   
 9 7
r   c                   @   sz   e Zd ZU dZdZeed< dZeed< eddZ	e
ed< G d	d
 d
Zdeee edddZdeee edddZdS )InfoPowerBIToolz2Tool for getting metadata about a PowerBI Dataset.Zschema_powerbir   z
    Input to this tool is a comma-separated list of tables, output is the schema and sample rows for those tables.
    Be sure that the tables actually exist by calling list_tables_powerbi first!

    Example Input: "table1, table2, table3"
    r   Tr   r   c                   @   s   e Zd ZdZdS )zInfoPowerBITool.ConfigTNr    r$   r$   r$   r%   r&      s   r&   Nr(   r2   r'   c                 C   s   | j |dS )z4Get the schema for tables in a comma-separated list., )r   Zget_table_infosplitr0   r(   r2   r$   r$   r%   rR      s    zInfoPowerBITool._runc                    s   | j |dI d H S )Nrl   )r   Zaget_table_inform   rn   r$   r$   r%   r[      s    zInfoPowerBITool._arun)N)Nr!   r"   r#   rd   r   re   rf   r   r	   r   r   r&   r   r   rR   r   r[   r$   r$   r$   r%   rj      s"   
  rj   c                   @   s   e Zd ZU dZdZeed< dZeed< eddZ	e
ed< G d	d
 d
Zdee ee edddZdee ee edddZdS )ListPowerBIToolzTool for getting tables names.Zlist_tables_powerbir   zUInput is an empty string, output is a comma separated list of tables in the database.r   Tr   r   c                   @   s   e Zd ZdZdS )zListPowerBITool.ConfigTNr    r$   r$   r$   r%   r&      s   r&   Nrk   c                 C   s   d | j S zGet the names of the tables.rl   joinr   rK   rn   r$   r$   r%   rR     s    zListPowerBITool._runc                    s   d | j S rq   rr   rn   r$   r$   r%   r[   	  s    zListPowerBITool._arun)NN)NNro   r$   r$   r$   r%   rp      s&   
  
  rp   ) rd   loggingtimer   typingr   r   r   r   Zlangchain_core.callbacksr   r   Zlangchain_core.pydantic_v1r	   r
   Zlangchain_core.toolsr   Z&langchain_community.chat_models.openair   Z(langchain_community.tools.powerbi.promptr   r   r   Z%langchain_community.utilities.powerbir   r   	getLoggerr!   rH   r   rj   rp   r$   r$   r$   r%   <module>   s   
 @