o
    l^hC                  	   @   sR  d dl Z d dlZd dlZd dlmZmZmZ d dlZd dlZd dl	m
Z
 d dlmZ d dl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ZeedZed	Zd
Ze ZG dd dZG dd dZdZ dgZ!dee" dee" fddZ#de"dee" dee"ee" f fddZ$dd Z%de"de"de"fddZ&ej'ddgd ed!fd"efd#d$Z(ej)d%d&gd d'd( Z*ej'd)dgd d*efd+d,Z+ej'd-d.gd d/d0 Z,ej)d1d2gd dFd4e-fd5d6Z.ej'd7d8gd d9e"d:efd;d<Z/ej)d=d8gd d9e"fd>d?Z0ej'd@d8gd d9e"fdAdBZ1ej'dCd8gd d9e"fdDdEZ2dS )G    N)DictListTuple)async_playwright)AsyncOpenAI)	APIRouterHTTPExceptionFile
UploadFile)loggeropenai_api_key)
SpeechTextChatRequest)api_keys3z$shanri-ai-chatbot-for-text-to-speechc                   @   s"   e Zd Zdedee fddZdS )KeywordGeneratortitlereturnc              
      s   d| d}z(t jjjddddd|dgdd	d
I d H }|jd jj}dd |dD W S  tyN } zt	
d| d|  g W  Y d }~S d }~ww )Nu  
        以下の書籍のタイトルから、検索キーワードを生成してください。
        以下の条件を満たすようにしてください：
        - 本の内容を推測できるキーワードを抽出
        - 一般的な検索キーワードとして使えそうなものを選択
        - 単語や短いフレーズを抽出
        - 重複を避ける
        - 数字や括弧などの記号は含めない

        タイトル: uU   

        キーワードはカンマ区切りで出力してください。
        zgpt-3.5-turbosystemui   あなたは書籍の内容を分析し、適切な検索キーワードを生成する専門家です。rolecontentuserffffff?d   )modelmessagestemperature
max_tokensr   c                 S      g | ]
}|  r|  qS  strip).0kwr    r    */home/air/yokohama/back/yokohama_router.py
<listcomp>;       z6KeywordGenerator.generate_keywords.<locals>.<listcomp>,zError generating keywords for 'z': )clientchatcompletionscreatechoicesmessager   split	Exceptionr   error)selfr   promptresponsekeywords_texter    r    r%   generate_keywords#   s&   	z"KeywordGenerator.generate_keywordsN)__name__
__module____qualname__strr   r7   r    r    r    r%   r   !   s    r   c                   @   s&   e Zd Zdd Zdee fddZdS )RakutenScraperc                 C   s   d| _ t | _d S )Nzhttps://books.rakuten.co.jp)base_urlr   keyword_generator)r2   r    r    r%   __init__B   s   zRakutenScraper.__init__r   c              
      s&  t d zt I d H  t 4 I d H }|j I d H }| I d H }z|d | j	 d}|j
|ddI d H  d}||I d H }|s\g W | I d H  W  d   I d H  W S g }|D ]4}|dI d H }	|	smq`|	 I d H  }
|dI d H }|r| I d H  nd	}||
|d
d q`t|I d H  |D ]&}| j|d I d H }||d< |rt|I d H  t|d |I d H  qt dt| d |W | I d H  W  d   I d H  W S | I d H  w 1 I d H sw   Y  W d S  ty } z
t d|  |d }~ww )Nz'Rakuten Books scraping process started.i`  z/ranking/hourly/001/networkidle)
wait_untilz.itemz.titlez.authoru   不明rakuten)r   authorsourcer   keywordszSuccessfully processed z items.zScraping failed: )r   info	db_moduleclear_ranking_datar   chromiumlaunchnew_pageset_default_timeoutr=   gotoquery_selector_allclosequery_selectortext_contentr"   appendsave_book_rankingsr>   r7   save_keywords_listlink_keywords_to_booklenr0   r1   )r2   pbrowserpageurlselectoritemsscraped_resultsitemtitle_elementr   author_elementrC   bookrE   r6   r    r    r%   scrapeF   sV   

$%zRakutenScraper.scrapeN)r8   r9   r:   r?   r   r   rb   r    r    r    r%   r<   @   s    r<   u  あなたは「どんな本を読もうか思いつかない方」や「少し読みたい本が決まっている方」を支える相談サポーターです。相談者が自由にお気持ちや関心事を話せるように、寄り添いながら丁寧に傾聴してください。あなたの役割は「安心できる聞き役」であり、本を紹介・創作したり著者を答えたりしないでください。--------------------------------【会話スタイル】・丁寧に傾聴し、安心感があり楽しい雰囲気をつくる・ご相談者のお気持ちや関心事を理解するよう努める・相談者の言葉に共感の言葉を添える・一度にひとつだけ、やさしく質問する・本や著者の情報提案はせず、あくまで寄り添う【会話の手順】1. 相談者の回答を受けて、まずは共感の言葉で受け止める：『○○にご興味があるのですね。』2. その後、相談者の興味・気分・経験・思い出などを軽く質問し、共感のリアクションや感嘆なども添えながら、会話を楽しく広げる：（例：『最近気になっていることはありますか？』『以前からお好きだったことはありますか？』）3. 寄り添いの言葉を交えながら優しく質問し、対話を3〜5往復程度続けてください。4. 対話を3〜5往復、会話の最後に次のように案内する：   『お話しくださってありがとうございます。お話から面白そうなキーワードをいくつか整理しました！気になるものを押していただければ、本を探すことができますよ。』u   こんにちは。お話ししながら、あなたにぴったりの本を一緒に探しましょう。「今日はこんな本が読みたいな」と思ったことを、マイクボタンを一度軽く押してお話しください。conversation_historyr   c              
      s   | sg S zKd}dd t | D }d|}tjjjdd|ddd	| dgd
ddI dH }|jd jj	 }dd |
dD dd }td|  |W S  tyl } ztd|  g W  Y d}~S d}~ww )up   
    // AIを使って会話履歴から図書館検索に適したキーワードを3つ抽出します。
    us   ユーザーが言及した単語をそのまま抽出してください。カンマ区切りで最大3つまで。c                 S   s    g | ]\}}|d  dkr|qS )   r   r    )r#   imsgr    r    r%   r&      s     z6extract_keywords_from_conversation.<locals>.<listcomp>z | zgpt-4o-minir   r   r   u   会話内容: r   g333333?r   r   r   r   Nr   c                 S   r   r    r!   )r#   kr    r    r%   r&      r'   r(      u'   ✅ [Conversation Keywords] Extracted: z0AI keyword extraction from conversation failed: )	enumeratejoinr)   r*   r+   r,   r-   r.   r   r"   r/   r   rF   r0   r1   )rc   keyword_promptuser_messagesall_user_textr4   r5   rE   r6   r    r    r%   "extract_keywords_from_conversation   s,   
ro   r.   c              
      s   dt dg}t|D ]\}}|d dkrdnd}|||d q|d| d ztjjjd|dd	d
I dH }|jd jj	
 }W n ty_ } ztd|  d}W Y d}~nd}~ww || |g }	t|	I dH }
||
fS )un   
    // OpenAI APIを使用して、会話の応答と検索キーワードの両方を生成します。
    r   r   rd   r   r   	assistantzgpt-4-turbo  r   rg   Nz Error generating chat response: uT   申し訳ございません。応答の生成中にエラーが発生しました。)SYSTEM_PROMPT_CHATrj   rR   r)   r*   r+   r,   r-   r.   r   r"   r0   r   r1   ro   )r.   rc   messages_for_responsere   rf   r   response_completionassistant_responser6   current_full_historyrE   r    r    r%   #generate_chat_response_and_keywords   s&   rw   c                    s>   dd | D }t jjjd|dI d H }|jd jj }|S )Nc                 S   s   g | ]	}| d r|qS )r   )get)r#   rf   r    r    r%   r&      s    zask_openai.<locals>.<listcomp>zgpt-4o)r   r   r   )r)   r*   r+   r,   r-   r.   r   r"   )past_messagesvalid_messagesr4   answerr    r    r%   
ask_openai   s   r|   textuser_idc              
      s   zHt jjjdd| dI d H }tjdstd t	 }d| d| d}|
| d| d| d}t|t| t| d	t d
| W S  tyc } ztd|  tdddd }~ww )Nztts-1nova)r   voiceinputtmpz
tmp/audio--z.mp3zspeech-audio/zhttps://z.s3.amazonaws.com/u   音声生成失敗: rq   u$   音声生成に失敗しました。status_codedetail)r)   audiospeechr,   ospathexistsmakedirsuuiduuid4stream_to_file	s3_clientupload_filebucket_nameremover0   r   r1   r   )r}   r~   r4   	unique_idaudio_file_paths3_keyr6   r    r    r%   synthesize_speech   s*   


r   z/yokohama/api/sttSpeech)tags.
audio_filec              
      s.  t jdst d dt  d}zuzZt|d}t| j	| W d   n1 s-w   Y  t|d}t
jjjd|dd	I dH }W d   n1 sOw   Y  td
|j  d|jiW W t j|rot | S S  ty } ztd|  tdddd}~ww t j|rt | w w )u   
    // フロントエンドから送信された音声ファイルを受け取り、
    // OpenAI Whisper APIを使用して文字起こしを行います。
    z/tmpz/tmp/z.oggwbNrbz	whisper-1json)r   fileresponse_formatzWhisper STT successful: 
transcriptzError during transcription: rq   u0   音声の文字起こしに失敗しました。r   )r   r   r   r   r   r   openshutilcopyfileobjr   r)   r   transcriptionsr,   r   rF   r}   r   r0   r1   r   )r   	file_pathbufferr   transcript_responser6   r    r    r%   transcribe_audio   s8   
r   z/healthSystemc                      s
   ddiS )Nstatushealthyr    r    r    r    r%   health_check  s   r   z/yokohama/api/speechspeech_datac                    s0   | j s
tdddt| j | jI d H }d|iS )Ni  zText is requiredr   	audio_url)r}   r   r   
chat_token)r   r   r    r    r%   r     s
   r   z/yokohama/api/scrape-rankingsScrapingc               
      sb   zt  } |  I d H }ddt|dW S  ty0 } ztd|  tdt|dd }~ww )NsuccesszScraping completed.)r   r.   scraped_items_countzScraping endpoint failed: rq   r   )r<   rb   rV   r0   r   r1   r   r;   )scraperscraped_datar6   r    r    r%   scrape_rakuten_rankings  s   r   z/yokohama/api/random-keywordsKeywords   limitc              
      sf   zt j| dI d H }|sdg diW S d|iW S  ty2 } ztd|  tdddd }~ww )N)r   rE   )u   村上春樹u   ミステリーu	   最新刊u   料理レシピzFailed to get random keywords: rq   zCould not fetch keywords.r   )rG   get_random_keywordsr0   r   r1   r   )r   rE   r6   r    r    r%   get_random_keywords_endpoint*  s   
r   z/yokohama/api/chat/{session_id}Chat
session_idrequestc           	         s   |j }t| I d H }g }|D ]}|d r||d  |d r(||d  q|sG|sGtr3td nd}d}g }t| t|d|I d H  nt||I d H \}}d}t| t|||I d H  |||dS )Nuser_messageru   r       Z   )r4   rE   r   )r.   rG   get_chat_historyrR   	questionssave_chat_messager;   rw   )	r   r   r   history_recordsrc   recordr4   r   rE   r    r    r%   chatbot5  s"   r   z'/yokohama/api/chat/history/{session_id}c                    s   t | I dH }d|iS )u^   
    // 指定されたsession_idの全会話履歴をDBから取得して返します。
    Nhistory)rG   r   )r   r   r    r    r%   get_chat_history_by_sessionN  s   r   z!/yokohama/api/result/{session_id}c                    s   t | I dH }|stdddd}d|dg}|D ]}|d r+|d	|d d qt|I dH }t | d
d|I dH  d|ddS )uO   
    // 指定されたセッションの会話履歴を要約します。
    Ni  zChat history not found.r   u  相談者が自分のことをやさしく再認識できるように、会話の内容を箇条書きで整理してください。--------------------------------1. 興味・関心：相談者が話した本やテーマ、気になっていること、関心のある話題2. 思い出・経験：相談者が思い出したことや過去の経験、心に残っている出来事3. 感情・気持ち：会話の中で感じたこと、表れた気持ちや反応4. 新しい発見・気づき：相談者が改めて気づいたことや再認識したこと5. 前向きなヒント：毎日の生活で試してみたいこと、挑戦してみたいこと、楽しめそうなことr   r   r   r   99u   回答結果c   )r.   r4   r   )rG   r   r   rR   r|   r   )r   r   system_messagery   r   r4   r    r    r%   resultV  s   r   z /yokohama/api/clear/{session_id}c                    s"   t | I dH  dd|  diS )uO   
    // 指定されたセッションの会話履歴を削除します。
    Nr.   zChat history for session z cleared)rG   delete_chat_history)r   r    r    r%   clearu  s   r   )r   )3r   timeasynciotypingr   r   r   r   r   playwright.async_apir   openair   boto3fastapir   r   r	   r
   configr   r   schemasr   r   rG   r)   r   r   routerr   r<   rr   r   r;   ro   rw   r|   r   postr   rx   r   r   r   intr   r   r   r   r   r    r    r    r%   <module>   sZ    

7&%


