o
    :iG                  	   @   s^  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 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!d0d1 Z.ej+d2d3gd!dGd5e/fd6d7Z0ej)d8d9gd!d:e$d;efd<d=Z1ej+d>d9gd!d:e$fd?d@Z2ej)dAd9gd!d:e$fdBdCZ3ej)dDd9gd!d:e$fdEdFZ4dS )H    N)DictListTuple)async_playwright)AsyncOpenAI)KeywordFilter)	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d Zdedee fddZdS )KeywordGeneratorc                 C   s   t  | _d S )N)r   keyword_filterself r   -/home/air/ShanriRobot/back/yokohama_router.py__init__$   s   zKeywordGenerator.__init__titlereturnc              
      s   d| d}z1t jjjddddd|dgdd	d
I d H }|jd jj}dd |dD }| j	||}|W S  t
yW } ztd| d|  g W  Y d }~S d }~ww )Nu   
        あなたは書籍の内容分析の専門家です。以下の書籍タイトルから、その本の「内容・テーマ」を表す検索キーワードを抽出してください。

        ## 書籍タイトル
        uj  

        ## 抽出条件（重要）
        ### 含めるべきキーワード:
        - 本の主題やテーマ（例: 哲学、経済学、心理学）
        - 扱っているトピック（例: ユダヤ人の歴史、AI技術、習慣形成）
        - ジャンル（例: ミステリー、ビジネス書、自己啓発）
        - 重要な概念や理論（例: マインドフルネス、行動心理学）
        - 対象読者層（例: 初心者向け、経営者向け）

        ### 絶対に除外すべきキーワード:
        - 書籍の物理的特性: 本、巻、上巻、下巻、セット、表紙、カバー
        - 販売情報: 予約、入荷予約、限定、限定特典、楽天ブックス
        - 年号や数字: 2025、2026、第1巻、21
        - 一般的すぎる語: もの、こと、記録、知識
        - 出版社や書店名

        ## 出力形式
        カンマ区切りで5〜10個のキーワードを出力してください。
        各キーワードは2文字以上で、書籍の内容を具体的に表現するものにしてください。
        zgpt-3.5-turbosystemui   あなたは書籍の内容を分析し、適切な検索キーワードを生成する専門家です。rolecontentuserffffff?   )modelmessagestemperature
max_tokensr   c                 S   s   g | ]}|  qS r   strip).0kwr   r   r   
<listcomp>L   s    z6KeywordGenerator.generate_keywords.<locals>.<listcomp>,zError generating keywords for 'z': )clientchatcompletionscreatechoicesmessager   splitr   filter	Exceptionr   error)r   r   promptresponsekeywords_textraw_keywordsfiltered_keywordser   r   r   generate_keywords(   s*   z"KeywordGenerator.generate_keywordsN)__name__
__module____qualname__r   strr   r<   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_generatorr   r   r   r   r   W   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_timeoutrB   gotoquery_selector_allclosequery_selectortext_contentr'   appendsave_book_rankingsrC   r<   save_keywords_listlink_keywords_to_booklenr4   r5   )r   pbrowserpageurlselectoritemsscraped_resultsitemtitle_elementr   author_elementrG   bookrI   r;   r   r   r   scrape\   sV   

$%zRakutenScraper.scrapeN)r=   r>   r?   r   r   r   rf   r   r   r   r   rA   U   s    rA   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   会話内容: d   g333333?r"   r#   r%   r$   Nr   c                 S   s   g | ]
}|  r|  qS r   r&   )r(   kr   r   r   r*      s    r+      u'   ✅ [Conversation Keywords] Extracted: z0AI keyword extraction from conversation failed: )	enumeratejoinr,   r-   r.   r/   r0   r1   r   r'   r2   r   rJ   r4   r5   )rg   keyword_promptuser_messagesall_user_textr7   r8   rI   r;   r   r   r   "extract_keywords_from_conversation   s,   
rt   r1   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   rh   r   r   	assistantzgpt-4-turbo  r    rl   Nz Error generating chat response: uT   申し訳ございません。応答の生成中にエラーが発生しました。)SYSTEM_PROMPT_CHATro   rV   r,   r-   r.   r/   r0   r1   r   r'   r4   r   r5   rt   )r1   rg   messages_for_responseri   rj   r   response_completionassistant_responser;   current_full_historyrI   r   r   r   #generate_chat_response_and_keywords   s&   r|   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(   rj   r   r   r   r*      s    zask_openai.<locals>.<listcomp>zgpt-4o)r"   r#   r   )r,   r-   r.   r/   r0   r1   r   r'   )past_messagesvalid_messagesr7   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   音声生成失敗: rv   u$   音声生成に失敗しました。status_codedetail)r,   audiospeechr/   ospathexistsmakedirsuuiduuid4stream_to_file	s3_clientupload_filebucket_nameremover4   r   r5   r	   )r   r   r7   	unique_idaudio_file_paths3_keyr;   r   r   r   synthesize_speech   s*   


r   z/shanri/robot/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: rv   u0   音声の文字起こしに失敗しました。r   )r   r   r   r   r   r   openshutilcopyfileobjr   r,   r   transcriptionsr/   r   rJ   r   r   r4   r5   r	   )r   	file_pathbufferr   transcript_responser;   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   r1   scraped_items_countzScraping endpoint failed: rv   r   )rA   rf   rZ   r4   r   r5   r	   r@   )scraperscraped_datar;   r   r   r   scrape_rakuten_rankings2  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   rI   )u   村上春樹u   ミステリーu	   最新刊u   料理レシピzFailed to get random keywords: rv   zCould not fetch keywords.r   )rK   get_random_keywordsr4   r   r5   r	   )r   rI   r;   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_messagerz   r       Z   )r7   rI   r   )r1   rK   get_chat_historyrV   	questionssave_chat_messager@   r|   )	r   r   r   history_recordsrg   recordr7   r   rI   r   r   r   chatbotK  s"   r   z'/yokohama/api/chat/history/{session_id}c                    s   t | I dH }d|iS )u^   
    // 指定されたsession_idの全会話履歴をDBから取得して返します。
    Nhistory)rK   r   )r   r   r   r   r   get_chat_history_by_sessiond  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   )r1   r7   r   )rK   r   r	   rV   r   r   )r   r   system_messager~   r   r7   r   r   r   resultl  s   r   z /yokohama/api/clear/{session_id}c                    s"   t | I dH  dd|  diS )uO   
    // 指定されたセッションの会話履歴を削除します。
    Nr1   zChat history for session z cleared)rK   delete_chat_history)r   r   r   r   clear  s   r   )r   )5r   timeasynciotypingr   r   r   r   r   playwright.async_apir   openair   boto3r   r   fastapir   r	   r
   r   configr   r   schemasr   r   rK   r,   r   r   routerr   rA   rw   r   r@   rt   r|   r   r   postr   r}   r   r   r   intr   r   r   r   r   r   r   r   r   <module>   s\    

28&%


