
    ph=                        d dl mZ d dlmZ d dlZd dlZd dlZd dlmZm	Z	 d dl
mZmZmZmZ d dlmZ d dlmZ d dlZd dlZd dlZd dlmZ d dlZd d	lmZ d d
lmZ  ed       d dlZ ej8                  d      Z ej8                  d      Z ej8                  d      Z ej8                  d      Z  ej8                  d      Z! ej8                  d      Z" ej8                  dd      Z# ej8                  d      Z$ ej8                  d      Z% ej8                  d      Z& ej8                  d      Z'ejP                  jS                  ejP                  jU                  ejP                  jW                  e,      dd            Z-ejP                  jU                  e-dddd      Z. ej^                  e.d        eedee       Z0 G d! d"e      Z1 G d# d$e      Z2 G d% d&e      Z3 G d' d(e      Z4 G d) d*e      Z5 G d+ d,      Z6y)-    )load_dotenv)AzureOpenAIN)ListOptional)	BaseModelFieldValidationErrorfield_validator)search_handler)SearchRequest)datetime)Image)BytesIOT)overrideAZURE_OPENAI_API_KEYAZURE_OPENAI_ENDPOINTAZURE_OPENAI_DEPLOYMENTAZURE_OPENAI_API_VERSION_CHATIDEOGRAM_URLIDEOGRAM_API_KEYBASE_URLz(https://hubwallet-dev.dreamztesting.com/AZURE_OPENAI_ENDPOINT_IMAGEAZURE_OPENAI_DEPLOYMENT_IMAGEAZURE_OPENAI_API_VERSION_IMAGEAZURE_OPENAI_API_KEY_IMAGEz..menu_designdesignerstaticgenerated_imagesexist_okz2024-08-01-preview)api_keyapi_versionazure_endpointazure_deploymentc                       e Zd ZU  edd      Zee   ed<    edd      Zee   ed<    edd      Z	ee   ed<    edd	      Z
ee   ed
<    edd      Zee   ed<   y)PromoEntitiesNzaHigh-level type like 'BOGO', 'Flat Discount', 'Cashback', 'Bundle', 'Clearance', 'Seasonal', etc.defaultdescriptionpromotion_typez$Product or category names mentioned.productsz[Concrete offer phrasing (e.g., 'Buy 2 get 1 free', '20% off orders over $99, code SAVE20').offer_detailszOVisual/voice style cues (e.g., 'minimal', 'bold', 'modern', 'retro', 'luxury').stylezMColors or palettes mentioned or implied (e.g., 'red & gold', 'pastel green').color_theme)__name__
__module____qualname__r   r+   r   str__annotations__r,   r-   r.   r/        ?/var/www/html/hubwallet-dev/src/menu_design/core/menu_design.pyr'   r'   3   s    $)w%NHSM  $D>deHhsme#(q$M8C=  !eE8C=  "'c"K# r6   r'   c                       e Zd ZU  edd      Zee   ed<    edd      Zee   ed<    edd      Z	ee   ed<    edd	      Z
ee   ed
<   y)	PromoCopyNzWeekend Sale!, Burger Blissr(   titlezSAVE20, Save Now, Order NowtaglinezCall to action for the campaignctaz2Discount details (e.g., '20% off', 'Buy 1 Get 1').discount)r0   r1   r2   r   r:   r   r3   r4   r;   r<   r=   r5   r6   r7   r9   r9   G   st     1E8C=  #1GXc]  5C#  $HHhsm r6   r9   c                   J    e Zd ZU  edd      Zeed<    edd      Zeed<   y)ChatRequest.zThe user's message to the chat.)r*   messagez+The unique identifier for the chat session.
session_idN)r0   r1   r2   r   r@   r3   r4   rA   r5   r6   r7   r?   r?   Y   s2    5GS  AJ r6   r?   c                   ,    e Zd ZU eed<   eed<   eed<   y)Templatetemplate_idtemplate_nametemplate_urlN)r0   r1   r2   r3   r4   r5   r6   r7   rC   rC   c   s    r6   rC   c                   ~   e Zd ZU  eed      Zee   ed<    eed      Z	ee
   ed<    eed      Zee   ed<    edd	
      Zeed<    edd
      Zee
   ed<    eed      Zee
   ed<    eed      Zee   ed<    edd
      Zee
   ed<    ee      Zeee      ed<    edd
      Zeee
ef      ed<   y)	ChatStatez8Chat history with user messages and assistant responses.)default_factoryr*   historyzList of missing entities.missing_entitieszExtracted promotional entities.entitiesFz2Indicates whether all entities have been captured.r(   entities_capturedNzCurrent intentintentzList of detected intents.intentszGenerated promotional copy.copyzGenerated image URL.	image_url)rI   templatezCurrent state of the chat.state)r0   r1   r2   r   listrJ   r   dictr4   rK   r3   rL   r   rM   boolrN   rO   rP   rQ   rR   rS   r5   r6   r7   rH   rH   h   s$   NGT$Z  #(/#d3i 
  %5 Hhtn 
 $Ht 
 "$FHSM 
 /GT#Y 
 !1D(4.   %* Ix}  &+4%@HhtDz"@&+0'E8DTN# r6   rH   c                       e Zd ZddedefdZdededdfdZdedee   fdZd	 Z	defd
Z
dedefdZd ZdefdZdededefdZdefdZdededefdZdefdZdedeeedz  edz  f   fdZddZdedefdZy)MenuDesignGeneratorrA   duckdb_pathc                    t        j                  |      | _        | j                  j                  d       | j                  j                  d       i | _        | j                  |      }|>t               | j                  |<   | j                  || j                  |          || _        y || j                  |<   || _        y )NzINSTALL json; LOAD json;z
            CREATE TABLE IF NOT EXISTS chat_state (
                session_id TEXT PRIMARY KEY,
                state JSON,
                updated_at TIMESTAMP DEFAULT now()
            )
        )	duckdbconnect_conexecutesession_load_staterH   _save_state_session_id)selfrA   rY   existings       r7   __init__zMenuDesignGenerator.__init__   s     NN;/			45		  	  ##J/'0{DLL$Zj)AB & (0DLL$%r6   rS   returnNc                    |j                         }| j                  j                  d       	 | j                  j                  d|g       | j                  j                  d||t        j                         g       | j                  j                  d       y# t
        $ r | j                  j                  d        w xY w)z/Upsert the ChatState for a session into DuckDB.BEGINz+DELETE FROM chat_state WHERE session_id = ?zGINSERT INTO chat_state (session_id, state, updated_at) VALUES (?, ?, ?)COMMITROLLBACKN)model_dump_jsonr]   r^   r   utcnow	Exception)rc   rA   rS   
state_jsons       r7   ra   zMenuDesignGenerator._save_state   s    **,
		'"		IIKj\ZIIYZ):; IIh' 	IIj)	s   A)B &B=c                     | j                   j                  d|g      j                         }|syt        j	                  |d         S )zDFetch ChatState by session_id from DuckDB; return None if not found.z1SELECT state FROM chat_state WHERE session_id = ?Nr   )r]   r^   fetchonerH   model_validate_json)rc   rA   rows      r7   r`   zMenuDesignGenerator._load_state   sG    ii?L
 (* 	 ,,SV44r6   c                 j    | j                  | j                  | j                  | j                            y)u&   Persist the current session’s state.N)ra   rb   r_   )rc   s    r7   _persistzMenuDesignGenerator._persist   s'    ))4<<8H8H+IJr6   c                    t        |t              r|j                         }nt        |t              r|rt        |d   t              rvd|d   v rog }|D ]V  }|j                  dd      j                         }|j                  | d|j                  dd      j                                 X dj                  |      }nBdj                  |D cg c]  }t        |      j                          c}      }nt        |      }g d}d	d
dd|dddiddgdd}d}	ddddfddddfddddfddddfd d!d"dfd#d$d%dfd&d'd(dfd)d*d+dfd,d-d.dfd/d0d1dfd2d0d1dfd3d0d1dfg}
d4|	d5g}|
D ]F  \  }}|j                  dd6| d7d5       |j                  d8t        j                  |d9      d5       H |j                  dd6| d7d5       	 t        j                  j                  j                  d:dd;|d<|=      }|j                  d   j                   j"                  }	 t        j&                  |      }t        |j                  dd            j                         }||v r|S dS c c}w # t$        $ r\}t        j                  j                  j                  d:ddd>i|=      }|j                  d   j                   j"                  }Y d?}~d?}~ww xY w# t        j(                  $ r_ t+        j,                  d@d|j                         t*        j.                  t*        j0                  z  A      }t        j&                  |      }Y w xY w)Ba  
        Classify the user's intent from a chat history and return one of:
        - general
        - input_collection
        - input_confirmation
        - copy_generation
        - copy_regeneration
        - copy_confirmation
        - image_generation
        - image_regeneration
        - image_confirmation
        - template_search

        Parameters
        ----------
        history : str | list[str] | list[dict]
            Conversation so far. Accepts:
            - a single string (latest user message or entire transcript),
            - a list of strings (ordered turns),
            - a list of {'role': 'user'|'assistant'|'system', 'content': '...'} dicts.
        model : str
            Chat model name (OpenAI or Azure-compatible).
        api_key_env : str
            Env var name holding the API key.

        Returns
        -------
        str
            One of the intents above. If parsing fails, defaults to 'input_collection'.
        r   contentroleuser:  
)
generalinput_collectioninput_confirmationcopy_generationcopy_regenerationcopy_confirmationimage_generationimage_regenerationimage_confirmationtemplate_searchIntentobjectFstringtypeenumr   )rN   	rationalerN   r   additionalProperties
propertiesrequirednameschemaa  You are an intent classifier for a creative assistant. Read the conversation history and output JSON with the single key 'intent'. Choose only from:
general = general conversation or inquiries.
input_collection = user is supplying requirements or asking what info you need.
input_confirmation = user confirms their inputs/brief are final.
copy_generation = user asks to create new wording/text/copy.
copy_regeneration = user asks to retry/rewrite/modify existing copy.
copy_confirmation = user approves/accepts the copy as final.
image_generation = user asks to create a new image/visual.
image_regeneration = user asks to modify/regenerate an image just made.
image_confirmation = user approves/accepts the image as final.
If ambiguous, pick the best single label.u   user: We’re launching a monsoon sale for sandals. What details do you need from me?
assistant: I can collect brand, tone, products, colors.r}   zUser asks what info to provide.uM   user: Okay, that’s all the info. Proceed with this brief.
assistant: Noted.r~   zUser confirms inputs are final.zLuser: Write a Facebook post announcing 20% off backpacks in a cheerful tone.r   zDirect request to create copy.z9user: Rewrite that caption, make it shorter and punchier.r   z'User wants a revision of existing copy.z*user: Perfect, keep that caption as final.r   zUser approves copy.z5user: Generate a square food background with no text.r   zNew image request.z?user: Try the same image but brighter colors and more contrast.r   zModify existing image.u/   user: Looks great—export that image as final.r   zUser approves image.zuser: Hi! how are you?r|   z$User initiates general conversation.zuser: Find me some templatesr   zUser asks to find templates.zuser: show templateszuser: generate some templatessystemrw   rv   z	History:
z

Return JSON.	assistant)ensure_asciigpt0json_schemar   r   modeltemperatureresponse_formatmessagesjson_objectN^```json|```$flags)
isinstancer3   striprT   rU   getlowerappendjoinjsondumpsclientchatcompletionscreatechoicesr@   rv   rm   loadsJSONDecodeErrorresub
IGNORECASE	MULTILINE)rc   rJ   
transcriptlinesmrw   xlabelsr   sysfewshotsr   uaresprv   edatarN   s                      r7   classify_intent_from_historyz0MenuDesignGenerator.classify_intent_from_history   s   H gs# J&:gaj$7IQR<S  KA550668DLLD6AEE)B,?,E,E,G+H!IJK "YYu-
!YY'H1A'HI
WJ
  (-'/@"((!3 &J
8 	$ ^)8YZ\]+:[\^[(7WXZH*9bce9*9NOQD)8LMON+:RSU>+:PQS% /UVX+(7UVX#(7UVX,(7UVX/
8 &#67 	aDAqOOV*QCGW8XYZOO[TZZX]=^_`	a 	jL\4]^_	6;;**11)6v N!	 2 D ll1o--55G	'::g&D
 TXXh+,2246)vA/AAa (I|  	6;;**11!' 7!	 2 D ll1o--55G	6 ## 	'ff-r7==?"--Z\ZfZfJfgG::g&D	's3    I&AI+  K +	K4AKKA.MMr@   c                 :   d}d| }t         j                  j                  j                  ddd|dd|dg      }|j                  d	   j
                  j                  j                         }t        j                  d
d|      }t        j                  dd|      }|S )z
        Take a rough bot reply and return a polished version in Markdown.
        - Tone: professional, friendly, concise
        - Output: Markdown only (no code fences)
        ue  You are an expert promotional-material assistant. Rewrite the user's draft reply so it is professional, friendly, and concise. Preserve intent and factual details, improve clarity, and format as Markdown. Use short sentences, clear structure, and bullets only when they help. Return ONLY the improved reply in Markdown—no code fences, no extra commentary.zDraft reply to improve:

r   g?r   r   rx   r   r   r   r   z^```[a-zA-Z]*\s*rz   z\s*```$)
r   r   r   r   r   r@   rv   r   r   r   )rc   r@   system_promptuser_promptr   outs         r7   _reply_markdownz#MenuDesignGenerator._reply_markdown|  s    ` 	 4G9={{&&--!m<K8 . 
 ll1o%%--335ff("c2ffZS)
r6   c                    ddl }ddl}ddl}ddlm} t        |t              r|j                         }nt        |t              r|rt        |d   t              rvd|d   v rog }|D ]V  }|j                  dd      j                         }	|j                  |	 d|j                  dd      j                                 X d	j                  |      }nBd	j                  |D 
cg c]  }
t        |
      j                          c}
      }nt        |      }d
}g d}dddddid|ddddddgidddgidddiddddgidddiddddiddddgidddgidddgidddgid
ddddddiddidddgdddg ddd}d}d |d!g}|j                  d |d!       |D ]  }|j                  |d   |d   d!        	 t        j                  j                   j#                  d"dd#|d$|%      }|j$                  d   j&                  j(                  }	  |j,                  |      S c c}
w # t*        $ rU t        j                  j                   j#                  d"ddd&i|%      }|j$                  d   j&                  j(                  }Y uw xY w# |j.                  $ rP  |j0                  d'd|j                         |j2                  |j4                  z  (      } |j,                  |      cY S w xY w))a  
        Produce the next assistant reply for a promo-material workflow, based on conversation history.
        Returns a structured JSON dict with:
        - assistant_reply: concise text to show the user
        - next_intent: one of
            [input_collection, input_confirmation, copy_generation, copy_regeneration,
            copy_confirmation, image_generation, image_regeneration, image_confirmation]
        - state_write: key-value updates the app should persist (inputs/preferences)
        - copy: a dictionary containing (title, tagline, cta, offer details) all in max 2 words
        - image_requests: list of image generation prompts (each: {purpose, prompt, size, variations})
        - template_suggestions: optional list of templates {name, rationale}
        - missing_inputs: array of strings describing remaining info needed

        `history` can be:
        - a single string (transcript or latest user message),
        - a list[str] (ordered turns),
        - a list[{'role': 'user'|'assistant'|'system', 'content': '...'}].

        The function does NOT create images; it returns prompts your app can pass to an image generator.
        r   N)OpenAIrv   rw   rx   ry   rz   r{   u  You are an expert promotional material designer that helps users create promotional materials by guiding them through a structured, step-by-step process, maintaining state and context, and facilitating inputs, copywriting, image generation, and template selection. Handle users’ requests and changes efficiently, ensuring every step is completed before moving forward.

Key Guidelines:
- Maintain State: Keep track of all inputs and user preferences. Handle users changing their minds, revisiting stages,   or providing inputs out of order.
- Conversational Tone: Keep responses concise, conversational, and focused while staying on task.
- Critical Task Completion: Always complete promised tasks (e.g., generating copy, images) in the same response.
- Adaptive Engagement: Ask for clarifications if intent is unclear. Detect and adapt to whether a user is providing   inputs, modifying previous data, or requesting suggestions.

Return STRICT JSON only with the schema provided. No markdown, no extra commentary.)r}   r~   r   r   r   r   r   r   PromoAssistantReplyr   Fr   r   r   Tnullarray)r   items)
brandr+   r,   r-   r.   r/   tonechannelsize_preferencesnotes)r   r   r   )labeltextr   r   r   )assistant_replynext_intentstate_writerP   )r   r   r   rP   image_requeststemplate_suggestionsmissing_inputsr   u  You will read the conversation history and produce the next response.
Rules:
1) Be concise and conversational in 'assistant_reply'.
2) If the user asked for copy, generate 2–4 short, high-quality options in 'copy'.
3) If the user asked for images, include at least one 'image_requests' entry with a clear prompt.
   Prefer square 1080x1080 for Facebook/Instagram unless user specified otherwise.
4) Update 'state_write' with any inputs you can infer (brand, products, style, color_theme, etc.).
5) If something is missing, list it in 'missing_inputs' and ask briefly for it in 'assistant_reply'.
6) Choose 'next_intent' from the enum to reflect what just happened or what you're prompting next.
7) Never output markdown. Only return valid JSON as per schema.
r   r   r   r   r   r   r   r   r   )osr   r   openair   r   r3   r   rT   rU   r   r   r   r   r   r   r   r   r   r@   rv   rm   r   r   r   r   r   )rc   rJ   r   r   r   r   r   r   r   rw   r   r   rO   r   rubricr   r   r   rv   s                      r7   answer_user_from_historyz,MenuDesignGenerator.answer_user_from_history  sa   0 	! gs# J&:gaj$7IQR<S  KA550668DLLD6AEE)B,?,E,E,G+H!IJK "YYu-
!YY'H1A'HI
WJb 	 	
 * (-(.'9,4g#F (04&,x.?%@/57H.I18FHCU(V.4x6G-H.5@R%S4;vxFX+Y%+hv->$?(.&0A'B17(69J0K&,x.?%@'$" !)$,49*0();)/(:+ *1(8"' B RI%(
X	P 	 &-@Af=> 	PDOOT&\d9oNO	P	6;;**11)6{ S!	 2 D ll1o--55G	'4::g&&g (IN  	6;;**11!' 7!	 2 D ll1o--55G	6 ## 	'bff-r7==?"--Z\ZfZfJfgG4::g&&	's-    H6AH! 
J !AI?>I?AK! K!c                    t        |t              r|j                         }nyt        |t              r5|r3t        |d   t              r d|d   v rdj                  d |D              }n4t        |t              rdj                  d |D              }nt        |      }d}d| d}t        j                  j                  j                  d	d
d|dd|dg      }|j                  d   j                  j                  j                         S )u   
        Simple LLM-driven reply generator for general/possibly-irrelevant user inputs,
        using the provided conversation history. No rules or few-shots—LLM decides.

        Returns a single short reply string.
        r   rv   r{   c              3      K   | ]9  }|j                  d d       d|j                  dd      j                           ; ywrw   rx   ry   rv   rz   Nr   r   .0r   s     r7   	<genexpr>z4MenuDesignGenerator.general_reply.<locals>.<genexpr>M  s=     "m`aaeeF6&:%;2aeeIb>Q>W>W>Y=Z#["m   ?Ac              3   N   K   | ]  }t        |      j                           y wNr3   r   r   r   s     r7   r   z4MenuDesignGenerator.general_reply.<locals>.<genexpr>O  s     "Ca3q6<<>"C   #%u  You are an expert promotional material designer that helps users create promotional materials by guiding them through a structured, step-by-step process, maintaining state and context, and facilitating inputs, copywriting, image generation, and template selection. Handle users’ requests and changes efficiently, ensuring every step is completed before moving forward.

Give answer to user based on the historyIf it is a general input from user then reply accodingly and politely state that you are a copy & design agent for promotional materials. Offer help with copy, image prompts, or templates, or offer to continue the existing discussion if context exists.Conversation history:
z

Write ONE short, helpful reply to the user's LAST message, following the system guidelines above. Keep it concise and conversational.r   g333333?r   r   rx   r   )r   r3   r   rT   rU   r   r   r   r   r   r   r@   rv   )rc   rJ   r   r   r   r   s         r7   general_replyz!MenuDesignGenerator.general_reply>  s    gs# J&7z'!*d7SXaelmneoXo"mel"mmJ&"C7"CCJWJv 	 &l 22 	 {{&&--!m<K8 . 
 ||A&&..4466r6   rJ   rL   c           
         d}ddddddgidddgidddgidddgidddgidg dd	d
}d|dg}t        |      D ]  \  }}|j                  |d   |d   d       ! dj                  d |j                         D              }|j                  dd| d       t        j
                  j                  j                  ddd|d|      }	|	j                  d   j                  j                  }
	 t        j                  |
      }|j,                  r|j,                  j!                         |_        |j.                  r|j.                  j!                         |_        |S # t        $ r ddl}ddl}|
j!                         } |j"                  dd||j$                  |j&                  z        j!                         }t)        d|        t        di  |j*                  |      }Y w xY w)z
        Returns a PromoEntities object with normalized fields.
        Works with OpenAI; for Azure OpenAI, initialize the `client` with your Azure base_url and api_key.
        ak  You are an expert information extractor.
        Return ONLY valid JSON following the provided schema. No markdown. No extra keys. Do not assume data. Return null if not found. 
        User can provide answer like any or all for exmaple any color, all product, choose yourself. Take that as answer and if needed generate answer based on that input.
        Do not change or modify data unless user asked to. Example 70% off upto $100 does not mean 70% off.
        If a field is unknown, use null (for scalars) or [] (for arrays).
        Examples:
        Promotion Type: Sales, Product Launch, Holiday Special, BOGO, nothing specific
        Products: ceramic mugs, swimwear, beach towels, all items, all product
        Style: warm, cozy, hand-drawn, bold, minimalist, modern, contemporary, anything
        Color Theme: white and blue, gold and black, any color
        r'   r   Fr   r   r   )r+   r,   r-   r.   r/   r   r   r   r   rw   rv   z, c              3   0   K   | ]  \  }}| d |   yw)=Nr5   )r   kvs      r7   r   z=MenuDesignGenerator.extract_promo_entities.<locals>.<genexpr>  s     A1A3asA   rx   zexisting entities are, r   r   r   r   r   Nr   rz   r   zValidation error: r5   )	enumerater   r   r   r   r   r   r   r   r@   rv   r'   rq   r	   r   r   r   r   r   r   printr   r-   r+   )rc   rJ   rL   SYSr   r   iobjliner   rawr   r   cleaneds                 r7   extract_promo_entitiesz*MenuDesignGenerator.extract_promo_entitieso  s   
 $ (-'-&/A&B!'(F); <&,x.@%A$x&89$*Xv,>#? d
" &#67( 	NFAsOOS[S^LM	N yyA0@AA4KD62RST {{&&--%2;O	 . 
 ll1o%%--	733C8C  # 1 1 7 7 9C!$!3!3!9!9!;C
!  	7iikGbff-r7"--RTR^R^B^_eegG&wi016*$**W"56C	7s   -E BG"!G"c           	         t        |t              r|j                         }nit        |t              rN|r3t        |d   t              r d|d   v rdj                  d |D              }n$dj                  d |D              }nt        |      }d}d| d}d	|d
g}|D ]  }|j                  |d   |d   d
        t        j                  j                  j                  ddddi|      }|j                  d   j                  j                  j                         }	 t        j                  t!        j"                  dd|t         j$                  t         j&                  z        j                               }	|	j+                  d      |	j+                  d      |	j+                  d      |	j+                  d      dS # t        j(                  $ r i }	Y Zw xY w)z
        Generate ultra-brief promo copy (max 2 words each) from conversation history.
        Returns dict: {title, tagline, cta, offer}
        r   rv   r{   c              3      K   | ]9  }|j                  d d       d|j                  dd      j                           ; ywr   r   r   s     r7   r   zAMenuDesignGenerator.generate_copy_from_history.<locals>.<genexpr>  >     &qde!%%v*>)?r!%%	RTBUB[B[B]A^'_&qr   c              3   N   K   | ]  }t        |      j                           y wr   r   r   s     r7   r   zAMenuDesignGenerator.generate_copy_from_history.<locals>.<genexpr>       &G!s1v||~&Gr   u  You are an expert copywriter that guides users through structured steps, maintains state, and generates concise copy. Output STRICT JSON only with keys: title, tagline, cta, offer. Each value MUST be 1–2 words, no punctuation-heavy phrases. Do not chnage any details such as offer, promotion type, etc unless user have asked to. Keep them as it isInfer from the conversation history if details are missing.r   uW   

Return JSON with exactly these keys and 1–2 words each: title, tagline, cta, offer.r   r   rw   r   r   r   r   r   rz   r   r:   r;   r<   offer)r:   r;   r<   r  )r   r3   r   rT   rU   r   r   r   r   r   r   r   r@   rv   r   r   r   r   r   r   r   r   )
rc   rJ   r   r   r   r   msgr   r   r   s
             r7   generate_copy_from_historyz.MenuDesignGenerator.generate_copy_from_history  s    gs# J&:gaj$7IQR<S!YY&qip&qq
!YY&Gw&GG
WJJ 	 &l ** 	 &-@A 	NCOOS[S^LM	N {{&&--#]3	 . 
 ll1o%%--335	::bff%5r3bmmVXVbVbFbciiklD
 xx(xx	*xxxx(	
 	
 ## 	D	s   AF7 7GGlast_msgc                 $   t        |t              r|j                         }nit        |t              rN|r3t        |d   t              r d|d   v rdj                  d |D              }n$dj                  d |D              }nt        |      }|d| z  }d| d}t        j                  j                  j                  d	d
dd|dgddd      }|j                  d   j                  j                  j                         dz   }t        d|        |S )zW
        Generate a prompt for image generation based on conversation history.
        r   rv   r{   c              3      K   | ]9  }|j                  d d       d|j                  dd      j                           ; ywr   r   r   s     r7   r   z<MenuDesignGenerator.generate_image_prompt.<locals>.<genexpr>  r  r   c              3   N   K   | ]  }t        |      j                           y wr   r   r   s     r7   r   z<MenuDesignGenerator.generate_image_prompt.<locals>.<genexpr>	  r  r   z
Last mesasge of the user: zn
            Create a detailed image prompt for an image with the following details:
            
            a  
            
            
            The image should be realistic with proper background and foreground elements relevant to the user input, 
            with a mild black overlay, and without any text. Focus on creating a visually appealing image.
            The image would be a food menu design image for one or multiple products as provided.

            
            From the reference only take the graphics design excluding the texts and copy. 
            IMPORTANT: Do not add text and copy in the image.
            
            Do not add any promotional info or offer details from the user input.
            
            Generate a detailed prompt that I can use to create this image, in not more than 300 chars.
            r   zYou are a helpful assistant.r   rx   i  gffffff?r   )r   
max_tokensr   r   z
 IMPORTANT: The image should NOT include any text in the image. You should only generate image. Any text in the image would mean it is not qualified. Generate this image formenu design for restaurant for printzGenerated image prompt: )r   r3   r   rT   rU   r   r   r   r   r   r   r@   rv   r   )rc   rJ   r  r   promptresponseimage_prompts          r7   generate_image_promptz)MenuDesignGenerator.generate_image_prompt  s2   
 gs# J&:gaj$7IQR<S!YY&qip&qq
!YY&Gw&GG
WJ4XJ??
 L < ;;**11 %=
 #%	  2 
   ''*22::@@B  F[  [ 	(78r6   r  c                 @   t        t        j                               }d| j                   d| d}t        j                  j                  t        |      }t        j                  j                  t        d      }t        j                  j                  t        d      }t        j                  j                  t        d      }t        j                  j                  t        d      }	 t        j                  t        dt        id |fd	d
dddt        |d      fdt        |d      fdt        |d      fdt        |d      fd      }	t        d|	j                   d|	        |	j                  dk7  rdd d|	j                   fS |	j                         j!                  d      d   j!                  d      }
|
sy	 t        j                   
      }|j                  dk7  rdd d|j                   d|j                   fS t%        j                  t'        |j(                              }|j+                  |       t        d|        t,        j/                  d      rt,        nt,        dz   }| d| }t        d|        d|d fS # t"        $ r}t        |        Y d }~d }~ww xY w) Npromo_image__.pngz%Food_Menu_Special_Price_Promotion.jpgzBlack_Modern_Restaurant.jpgz.delicious_food_menu_design_Instagram_story.jpgzhot_pizza.pngzApi-Key)N1x1)NON)NzTexts, logos, brands, annoucement.No text allowed in the image. Stricly no text. No text in the image. No text in the image. No text in the image. No text in the image. No text in the image.)r  aspect_ratiomagic_promptnegative_promptrbz.delicious_food_menu_design_Instagram_story.png)style_reference_imagesr  r  r  )headersr   filesz.Received response from Ideogram generate API:  -    FzError from Ideogram API: r   r   url)FNz&No image URL returned by Ideogram API.Failed to download image: zImage saved locally at: /static/generated_images/zImage URL set to: T)inttimerb   r   pathr   STATIC_PATHrequestspostr   r   openr   status_coder   r   r   rm   r   r   rv   saver   endswith)rc   r  	timestampimage_filenameimage_filepathsample_ref_1sample_ref_2sample_ref_3sample_ref_4r  generation_urlr   image_responseimgbase_urlrQ   s                   r7   generate_imagez"MenuDesignGenerator.generate_imageH  s   		$	'(8(8'99+TJk>Bww||K1XYww||K1NOww||K1abww||KA	}}/  $\2$1$0 (p	 0WX\]ikoXp.q/LdS_aeNf.g/_aefrtxay.z/>\SW@X.Y	H& B8CWCWBXX[\d[efg ##s*d&?$OOO%]]_008;??FN!L " "n5%%,$"<^=W=W<XX[\j\o\o[p qqqjj!7!789 ((89:  (00588c>j 88HI	 	"9+./Y$$)  	QCMM	s   &BI> 3I> >	JJJr  c                    dt          dt         dt         }ddt         d}|ddd	d
dd}t	        j
                  |||d      }|j                  dk7  rddd|j                   d|j                   fS |j                         j                  dg       }|sy|d   }t        j                  t        d       t        t        j                               }d| j                   d| d}	t        j                   j#                  t        |	      }
	 |j                  d      s|j                  d      r|j                  d      xs |j                  d      }t	        j                  |d      }|j                  dk7  rddd|j                   d|j                   fS t%        j&                  t)        |j*                              }|j-                  |
       nX|j                  d       rFt/        j0                  |d          }t%        j&                  t)        |            j-                  |
       ny!t4        j7                  d#      rt4        nt4        d#z   }| d$|	 }d|dfS # t2        $ r}ddd"| fcY d}~S d}~ww xY w)%aM  
        Simple: call Azure OpenAI Images, save PNG under STATIC_PATH, return public URL.
        Expects globals: AZURE_ENDPOINT, AZURE_API_KEY, API_VERSION, DEPLOYMENT_NAME,
                        STATIC_PATH (disk path to static/generated_images),
                        BASE_URL (site base, e.g., https://example.com/)
        zhttps://z%.openai.azure.com/openai/deployments/z /images/generations?api-version=zapplication/jsonzBearer )zContent-TypeAuthorization	1024x1024mediumd   png   )r  sizequalityoutput_compressionoutput_formatnx   )r  r   timeoutr  FNzGeneration failed: r  r   )FNzNo image data returned.r   Tr    r  r  r  r  content_url)rF  r   b64_json)FNz/Unsupported image payload (no url or b64_json).zFailed to save image: r!  r"  )AZURE_ENDPOINT_IMAGEDEPLOYMENT_NAME_IMAGEAPI_VERSION_IMAGEAZURE_API_KEY_IMAGEr'  r(  r*  r   r   r   r   makedirsr&  r#  r$  rb   r%  r   r   r)  r   rv   r+  base64	b64decoderm   r   r,  )rc   r  r  r  payloadrr   itemr-  r.  r/  r4  r5  r6  	png_bytesr   r7  rQ   s                     r7   generate_promo_imagez(MenuDesignGenerator.generate_promo_image  sc    -..STiSj  kK  L]  K^  _ /&':&;<

 "%"
 MM#wWcJ==C$"5amm_Cx PPPvvx||FB'9Aw 	K$/		$	'(8(8'99+TJk>B	=xx$((="9!%%!KDHH]4K!)nc!J!--4 $*D^E_E_D``cdrdwdwcx(yyyjj)?)?!@A(*%",,T*-=>	

79-.33NCU
  (00588c>j 88HI	Y$$  	=$"8 <<<	=s&   B
I BI 	I4"I/)I4/I4c           	      @   	 d|d    d|d    d|d    d|d    d		}t        |d
|      }t        |      }|j                  }|D cg c]&  }|j                  |j                  |j
                  d( }}|S c c}w # t        $ r}	t        d|	        g cY d }	~	S d }	~	ww xY w)Nzpromotion type is :r+   z,
            offer details is r-   z,
            style is r.   z,
            color theme is r/   z
            design_template)querycollection_namelimit)rF   rD   rE   zError in select_templates: )r   r   resultsrF   rD   rE   rm   r   )
rc   user_requirementstop_kinput_requirementrequestr  selected_resultsrQ  return_array_of_resultr   s
             r7   select_templatesz$MenuDesignGenerator.select_templates  s    "	$78IJZ8[7\ ]/@A B'01 2-m<= >!
 $' 1G
 &g.H  (// && 	 !" }}!"&" & *)&  	/s34I	s0   AA: +A51A: 5A: :	BBBBr^  c           	      j   | j                   |j                     }|j                  j                  d|j                  d       | j                  |j                        }|j                  j                  |       g |_        t        d       t        |       t        d       |dk(  r| j                  |j                        }|j                  j                  d|d       |dd|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S | j                  |j                  |j                        D ];  }|d	   |j                  j                  |d
          '|d	   |j                  |d
   <   = |j                  rk|j                  j                  dddj!                  |j                        z   dz   dz   dj!                  d |j                  j#                         D              z   d       || j                   |j                  <   ddj!                  |j                        z   dz   dz   dj!                  d |j                  j#                         D              z   }d|j                  v r|dz   }| j%                  |      }|dd|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S |j&                  sd|_        g |_        || j                   |j                  <   ddj!                  d |j                  j#                         D              z   }| j%                  |      }|j                  j                  d|d       |dd|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S | j                  |j                        }t        d|       |dk(  sd|j                  v ryd|j                  vs't)        |j                  j#                               d
k(  rD| j+                  |j                        }	t        d|	       dj!                  d |	j#                         D              }
|j                  j                  |       |j                  j                  d       |	|_        |j                  j                  dd|
 dd       || j                   |j                  <   d|
 d}| j%                  |      }|dd|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S |dk(  s|dk(  r!| j+                  |j                        }	t        d|	       dj!                  d |	j#                         D              }
d|
 d }|dk(  r|d!z  }|j                  j                  |       |	|_        |j                  j                  d|d       || j                   |j                  <   | j%                  |      }|d||j                  |j                  d|	|j                  xs d |j                  xs g |j                  d}| j                          |S |dk(  sd|j                  v rEt        |j                         d"|j                  vr!t        d#       | j-                  |j                  |j                        }| j/                  |      }|j                  j                  dd$d       |j                  j                  |       |j                  j                  d"       |d	   |_        || j                   |j                  <   d$d%d"|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S |d"k(  s|d&k(  r| j-                  |j                  |j                        }| j/                  |      }|j                  j                  dd$d       |j                  j                  |       |d	   |_        || j                   |j                  <   d$d%||j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S |d%k(  sd%|j                  v r=d'|j                  vr.| j1                  |j                        }||_        ||_        d'|_        dj!                  d( t5        |      D              }|j                  &t)        |j                  j#                               d
k(  r"| j+                  |j                        }	|	|_        d)d*d'|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}|j                  j                  dd+| d       | j                          |S |d'k(  rE| j1                  |j                        }||_        ||_        dj!                  d, t5        |      D              }|j                  &t)        |j                  j#                               d
k(  r"| j+                  |j                        }	|	|_        |j                  j                  dd)d       d)d*d'|j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}|j                  j                  dd+| d       | j                          |S |dk(  r5|j                  j                  dd-dz   dj!                  d. |j                  j#                         D              z   d       || j                   |j                  <   d/dj!                  d0 |j                  j#                         D              z   }| j%                  |      }|j                  j                  d|d       |d||j                  |j                  d|j                  xs i |j                  xs d |j                  xs g |j                  d}| j                          |S y )1Nrx   r   z$===============  INTENT IS =========r|   r   r}   )rL   rK   )r   r   rN   r   rP   rQ   r   r   r?  r   z2Please provide the following missing information:
r{   z$We have the following information:
 c              3   0   K   | ]  \  }}| d |   ywry   Nr5   r   keyvalues      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>  sS       XT  oy  or  ty  \_  [`  `b  ch  bi  Yj  XTr   c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>!  sS       jf  AK  AD  FK  nq  mr  rt  uz  t{  k|  jfr   r.   zW ### some examples of style may include modern, bold, minimalist, vintage, contemporaryTz]All required information has been provided. Please check and confirm the following details: 
c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>?  sS       FB  ]g  ]`  bg  JM  IN  NP  QV  PW  GX  FBr   r~   zdetected intentr   zgenerated copy:c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>Z  s     2decU"UG3D2dr   zEGreat! Here is the generated copy based on the provided information:
zI. Do you want to continue with image generation or want any modification?r   r   c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>x  s     .`ZS%#b/@.`r   z>Here is the generated copy based on the provided information:
.zH Do you want to continue with image generation or want any modification?r   zWill generate image herez}We have generated an image for you based on your inputs. Should we proceed for template search or you want any modification? r   r   r   c              3   <   K   | ]  \  }}|d z    d|d      ywr?  z. rE   Nr5   r   r   rR   s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>  s2       8Gbmbcem1Q3%r(?B[A\8]  8G   z1Here are some templates that might work for you:
template_selectionz3Here are some templates that might work for you:  
c              3   <   K   | ]  \  }}|d z    d|d      ywrn  r5   ro  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>  s2       4C^i^_aiqse2h>W=X4Y  4Crp  z*Does the updated information look correct?c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>  sS       KG  bl  be  gl  OR  NS  SU  V[  U\  L]  KGr   z+Does the updated information look correct?
c              3   0   K   | ]  \  }}| d |   ywrd  r5   re  s      r7   r   z+MenuDesignGenerator.chat.<locals>.<genexpr>  s/       XTnxnqsx[^Z__abgahXi  XTr   )r_   rA   rJ   r   r@   r   rO   rK   r   r   rL   rP   rQ   rR   rt   r   r   r   r   rM   lenr  r  r8  ra  rN   r   )rc   r^  rS   rN   answerr  entityreplymd_replyrP   formatted_copyr   md_assistant_replycopy_outputmd_copy_outputr  rQ   	templatesformatted_templatess                      r7   r   zMenuDesignGenerator.chat  s   <<(:(:; 	fIJ225==AV$ "$45f45Y''6FMM  +&!IJ#)1, %(-(>(>  

(b"__4(-(<""'"8"8H MMOO11%--P 	6Fq	!&&--fQi8,21Ivay)	6 !!MM  +Dw{  |E  |E  FK  F\  F\  |]  C]  _c  Cc  fK  CL  OS  OX  OX  XT  }B  }K  }K  }Q  }Q  }S  XT  OT  CT  "U  V/4DLL++,
 JTYYW\WmWmMnnptt  x]  ^  ae  aj  aj  jf  OT  O]  O]  Oc  Oc  Oe  jf  af  fE%000 yy++E2H#+1, %(-(>(>  

(b"__4(-(<""'"8"8H MMOO
 ***.')+&38W//0x  }A  }F  }F  FB  kp  ky  ky  k  k  kA  FB  }B  B//6$$[8%LM'/#72$)NN,1,B,B$ "JJ,"!&!8D,1NN,@b&+&<&<  ::5==I'/115IU]]5Z(=UZZEUEUEWAX\]A]#>>u}}M/6)-2dW[WaWaWc2d)d,,V4,,->?%)
,,k  QW  Xf  Wg  gp  Oq  .r  s;@W%7%78,r  tB  sC  CL  +M-1-A-A/-R* 0B+>&7,1NN494J4J, %*JJ$4").)@D49NN4Hb.3.D.D$ '..&<O2O::5==ID+T2%)YY.`SWS]S]S_.`%`N$cdrcsst"uK!22#'qqMM((0!%EJMM((++)VW7<DLL!3!34%)%9%9+%FN ,:':"((-050F0F( !%%*__%<050D"*/*@*@ H MMO#O004G5==4X%--()>89'+'A'A%--QXQ`Q`'a$($7$7$E	 ,,[  NK  .M  N,,V4,,-?@*3A,;@W%7%78 2o+?&8,1NN494J4J, %*JJ$4").)@D49NN4Hb.3.D.D$ '//6=Q3Q#'#=#=emmW__#]L $ 3 3L AI MM((  JG  *I  JMM((0&/lEO7<DLL!3!34 ,k';"((-050F0F( !&

 0b%*__%<050D"*/*@*@ H MMO#O115IU]]5Z(=$($9$9%..$I	)2'-'8.2ii  8Gqz  |E  rF  8G  /G+ ::-UZZ5E5E5G1HA1M#'#B#B5==#QD'+EJ1c+?&7,1NN494J4J, %*JJ$4").)@D49NN4Hb.3.D.D$ ,,k  QE  FY  EZ  O[  .\  ]'.. $ 5 5enn EI%.EN#)EL*.))  4Cmv  xA  nB  4C  +C'zz)S1A1A1C-D-I#>>u}}M#'
MM((I{)}~-_';"3(-050F0F( !&

 0b%*__%<050D"*/*@*@ H MM((+  MA  BU  AV  KW  *X  YMMO#O//MM((+Lvz~J~  BF  BK  BK  KG  pu  p~  p~  pD  pD  pF  KG  BG  KG  *H  I7<DLL!3!34Jdii  XT  }B  }K  }K  }Q  }Q  }S  XT  OT  TE#33E:HMM((x)PQ+3';"((-050F0F( !&

 0b%*__%<050D"*/*@*@!H MMO#O) 0r6   )zmenu_state.duckdb)   )r0   r1   r2   r3   re   rH   ra   r   r`   rt   r   r   r   r   rT   r'   r   rU   r  r  r8  tuplerV   rT  ra  r?   r   r5   r6   r7   rX   rX      s7   &3 &S &<c )   	5c 	5hy.A 	5K^B 
^BB!! 
!H\'|.7 
.7bQQ Q 
	Qf:
 
:
xFT FC FC FT=%# =%~<%3 <%5sTz3QU:9U3V <%@#Jh$K h$C h$r6   rX   )7dotenvr   r   r   r   r   r'  typingr   r   pydanticr   r   r	   r
   -src.marketing.vector_db_collection.controllerr   )src.marketing.vector_db_collection.schemar   r   r[   r   r$  PILr   ior   rN  getenvAPI_KEYENDPOINT
DEPLOYMENTAPI_VERSIONr   r   r   rI  rJ  rK  rL  r%  abspathr   dirname__file__BASE_DIRr&  rM  r   r'   r9   r?   rC   rH   rX   r5   r6   r7   <module>r     s      	  ! G G H D       T  
"))*
+299,-RYY01
bii78ryy(299/0 299Z!KL!		"?@ !		"AB BII>? RYY;<  77??277<<(A4NO ggll8]JJ\] K$ ' 
$	
I (	 $) y 
+	 +jw$ w$r6   