o
    |!g                     @  s  d dl mZ d dlZd dlmZmZ zd dlmZ W n ey)   d dlmZ Y nw d dl	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 ddlmZmZ ddlmZ dZG dd dZG dd deZG dd deZG dd deZG dd deZdS )    )annotationsN)AnyProtocol)Self)meta)	BaseModelValidationError   )DefaultCacheRenderCache)config)env)
AsyncError)ChatMessagechat_message_from_text)generate_canary_word0c                   @  s~   e Zd Zddddddd%ddZd&ddZed'ddZed(ddZed(ddZed)ddZ	ed*d d!Z
d+d#d$ZdS ),
BasePromptN)nameversionmetadatacanary_wordrender_cachetextstrr   
str | Noner   r   dict[str, Any] | Noner   r   RenderCache | NonereturnNonec                C  sX   |pi | _ |ptt | _|| _|pt | _t	|| _
|p t| _d|p't i| _dS )aD  
        Prompt constructor.

        Parameters:
            text: The template text.
            name: The name to identify this prompt.
            version: The version string attached to this prompt.
            metadata: A key-value set of metadata pairs attached to this prompt.
            canary_word: The string to use for the `{{canary_word}}` extension. If `None`, a default string will be
                generated.
            render_cache: The caching backend to store rendered prompts. If `None`, the default in-memory backend will
                be used.
        r   N)	_metadatar   uuiduuid4_name_rawr
   _render_cacher   from_string	_templateDEFAULT_VERSION_versionr   defaults)selfr   r   r   r   r   r    r,   N/mnt/skqttb/ctump_chatbot/chatbot/lib/python3.10/site-packages/banks/prompt.py__init__   s   

zBasePrompt.__init__datadict | Nonedictc                 C  s   |d u r| j S || j B S Nr*   )r+   r/   r,   r,   r-   _get_context<   s   
zBasePrompt._get_contextdict[str, Any]c                 C     | j S r2   )r    r+   r,   r,   r-   r   A      zBasePrompt.metadatac                 C  r6   r2   )r#   r7   r,   r,   r-   r   E   r8   zBasePrompt.namec                 C  r6   )z#Returns the raw text of the prompt.)r$   r7   r,   r,   r-   rawI   s   zBasePrompt.rawc                 C  r6   r2   )r)   r7   r,   r,   r-   r   N   r8   zBasePrompt.versionset[str]c                 C  s   t | j}t|S r2   )r   parser9   r   find_undeclared_variables)r+   astr,   r,   r-   	variablesR   s   
zBasePrompt.variablesboolc                 C  s   | j d |v S )z^Returns whether the canary word is present in `text`, signalling the prompt might have leaked.r   r3   )r+   r   r,   r,   r-   canary_leakedW   s   zBasePrompt.canary_leaked)r   r   r   r   r   r   r   r   r   r   r   r   r   r   )r/   r0   r   r1   )r   r5   )r   r   )r   r   )r   r:   )r   r   r   r?   )__name__
__module____qualname__r.   r4   propertyr   r   r9   r   r>   r@   r,   r,   r,   r-   r      s&    
 r   c                   @  s(   e Zd ZdZddddZddd
dZdS )Prompta  
    The `Prompt` class is the only thing you need to know about Banks on the Python side. The class can be
    initialized with a string variable containing the prompt template text, then you can invoke the method `text`
    on your instance to pass the data needed to render the template and get back the final prompt.

    A quick example:
    ```py
    from banks import Prompt


    p = Prompt("Write a 500-word blog post on {{ topic }}.")
    my_topic = "retrogame computing"
    print(p.text({"topic": my_topic}))
    ```
    Nr/   r   r   r   c                 C  s<   |  |}| j|}|r|S | j|}| j|| |S )
        Render the prompt using variables present in `data`

        Parameters:
            data: A dictionary containing the context variables.
        )r4   r%   getr'   rendersetr+   r/   cachedrenderedr,   r,   r-   r   m   s   
zPrompt.textlist[ChatMessage]c              	   C  s   |  |}| j|}|s| j|}| j|| g }| dD ]}z
|t	
| W q# ty8   Y q#w |sD|td|d |S )rF   
user)rolecontent)r4   r%   rG   r'   rH   rI   stripsplitappendr   model_validate_jsonr   r   )r+   r/   rL   messagesliner,   r,   r-   chat_messages}   s   
zPrompt.chat_messagesr2   r/   r   r   r   )r/   r   r   rM   )rA   rB   rC   __doc__r   rX   r,   r,   r,   r-   rE   \   s    rE   c                      s.   e Zd ZdZd fddZddddZ  ZS )AsyncPrompta-  
    Banks provides async support through the machinery [provided by Jinja](https://jinja.palletsprojects.com/en/3.0.x/api/#async-support)

    Since the Jinja environment is a global state in banks, the library can work either with or
    without async support, and this must be known before importing anything.

    If the application using banks runs within an `asyncio` loop, you can do two things
    to optimize banks' execution:

    1. Set the environment variable `BANKS_ASYNC_ENABLED=true`.
    2. Use the `AsyncPrompt` class that has an awaitable `run` method.

    For example, let's render a prompt that contains some calls to the `generate` extension. Those calls
    will be heavily I/O bound, so other tasks can take advantage and advance while the prompt is being
    rendered.

    Example:
    ```python
    # Enable async support before importing from banks
    import os

    os.environ["BANKS_ASYNC_ENABLED"] = "true"

    # Show logs to see what's happening at runtime
    import logging

    logging.basicConfig(level=logging.INFO)

    import asyncio
    from banks import AsyncPrompt

    prompt_template = """
    Generate a tweet about the topic '{{ topic }}' with a positive sentiment.
    """

    async def task(task_id: int, sleep_time: int):
        logging.info(f"Task {task_id} is running.")
        await asyncio.sleep(sleep_time)
        logging.info(f"Task {task_id} done.")


    async def main():
        p = AsyncPrompt(prompt_template)
        # Schedule the prompt rendering along with two executions of 'task', one sleeping for 10 seconds
        # and one sleeping for 1 second
        results = await asyncio.gather(p.text({"topic": "AI frameworks"}), task(1, 10), task(2, 1))
        print("All tasks done, rendered prompt:")
        print(results[0])


    asyncio.run(main())
    ```
    argsr   kwargsr   r   c                   s(   t  j|i | tjsd}t|d S )NzaAsync is not enabled. Please set the environment variable 'BANKS_ASYNC_ENABLED=on' and try again.)superr.   r   ASYNC_ENABLEDr   )r+   r\   r]   msg	__class__r,   r-   r.      s
   zAsyncPrompt.__init__Nr/   r   r   c                   sD   |  |}| j|}|r|S | j|I dH }| j|| |S )rF   N)r4   r%   rG   r'   render_asyncrI   rJ   r,   r,   r-   r      s   
zAsyncPrompt.text)r\   r   r]   r   r   r   r2   rY   )rA   rB   rC   rZ   r.   r   __classcell__r,   r,   ra   r-   r[      s    6r[   c                   @  s0   e Zd ZdZdddd
dZdddddZdS )PromptRegistryz:Interface to be implemented by concrete prompt registries.N)r   r   r   r   r   r   rE   c                C     d S r2   r,   )r+   r   r   r,   r,   r-   rG          zPromptRegistry.getF)	overwritepromptrh   r?   r   c                C  rf   r2   r,   )r+   ri   rh   r,   r,   r-   rI      rg   zPromptRegistry.set)r   r   r   r   r   rE   )ri   rE   rh   r?   r   r   )rA   rB   rC   rZ   rG   rI   r,   r,   r,   r-   re      s    re   c                   @  sL   e Zd ZU dZded< dZded< dZded< dZded	< edddZ	dS )PromptModelz(Serializable representation of a Prompt.r   r   Nr   r   r   r   r   cls
type[Self]ri   rE   r   r   c                 C  s   | |j |j|j|jdS )N)r   r   r   r   )r9   r   r   r   )rk   ri   r,   r,   r-   from_prompt   s   zPromptModel.from_prompt)rk   rl   ri   rE   r   r   )
rA   rB   rC   rZ   __annotations__r   r   r   classmethodrm   r,   r,   r,   r-   rj      s   
 rj   ) 
__future__r   r!   typingr   r   r   ImportErrortyping_extensionsjinja2r   pydanticr   r   cacher
   r   r   r   errorsr   typesr   r   utilsr   r(   r   rE   r[   re   rj   r,   r,   r,   r-   <module>   s,   A>O