import streamlit as st from langchain_groq import ChatGroq from langchain.chains import LLMChain from langchain.prompts import PromptTemplate from tavily import TavilyClient import re import clipboard import io import os import pandas as pd from PyPDF2 import PdfFileReader from PIL import Image import pytesseract import requests from bs4 import BeautifulSoup # Groq APIキーの設定 GROQ_API_KEY = os.getenv("GROQ_API_KEY") # Tavily APIキーの設定 TAVILY_API_KEY = os.getenv("TAVILY_API_KEY") tavily_client = TavilyClient(api_key=TAVILY_API_KEY) # Streamlitアプリケーションの設定 st.set_page_config(page_title="COM COM AI", page_icon="🤖", layout="wide") # セッション状態の初期化 if 'messages' not in st.session_state: st.session_state.messages = [] if 'uploaded_file_content' not in st.session_state: st.session_state.uploaded_file_content = None def read_pdf(file): pdf = PdfFileReader(file) content = "" for page_num in range(pdf.getNumPages()): page = pdf.getPage(page_num) content += page.extract_text() return content def read_csv(file): df = pd.read_csv(file) return df.to_string() def read_image(file): image = Image.open(file) text = pytesseract.image_to_string(image) return text def fetch_webpage_text(url): response = requests.get(url) if response.status_code != 200: return "ウェブページを取得できませんでした。" soup = BeautifulSoup(response.text, 'html.parser') paragraphs = soup.find_all('p') text_content = ' '.join([paragraph.get_text() for paragraph in paragraphs]) return text_content # サイドバーにAIモデルの選択、モード選択、ファイルアップロードを配置 with st.sidebar: ai_model = st.selectbox( "AIモデルを選択してください", ["gemma-7b-it", "gemma2-9b-it", "llama-3.1-70b-versatile", "llama-3.1-8b-instant", "mixtral-8x7b-32768"], key="model_select" ) mode = st.selectbox( "モードを選択してください", ["focus", "writing", "video","summary", "知恵袋"], key="mode_select" ) # ファイルアップロード機能 uploaded_file = st.file_uploader("ファイルをアップロード", type=["txt", "pdf", "csv", "py", "html", "css", "js", "cs", "php", "java", "png", "jpg"]) if uploaded_file is not None: file_extension = uploaded_file.name.split('.')[-1].lower() if file_extension in ['txt', 'py', 'html', 'css', 'js', 'cs', 'php', 'java']: stringio = io.StringIO(uploaded_file.getvalue().decode("utf-8")) st.session_state.uploaded_file_content = stringio.read() elif file_extension == 'pdf': st.session_state.uploaded_file_content = read_pdf(uploaded_file) elif file_extension == 'csv': st.session_state.uploaded_file_content = read_csv(uploaded_file) elif file_extension in ['png', 'jpg']: st.session_state.uploaded_file_content = read_image(uploaded_file) st.success(f"ファイル '{uploaded_file.name}' がアップロードされました。") # 会話をクリアするボタン if st.button("🔥 会話をクリア"): st.session_state.messages = [] st.session_state.uploaded_file_content = None # メインコンテンツ st.title("COM COM AI") # チャット履歴の表示 for message in st.session_state.messages: with st.chat_message(message["role"]): st.markdown(message["content"]) # ユーザー入力 if prompt := st.chat_input("メッセージを入力してください"): st.session_state.messages.append({"role": "user", "content": prompt}) with st.chat_message("user"): st.markdown(prompt) # LLMの初期化 llm = ChatGroq(temperature=0.7, groq_api_key=GROQ_API_KEY, model_name=ai_model) with st.chat_message("assistant"): message_placeholder = st.empty() full_response = "" # アップロードされたファイルの内容を考慮してプロンプトを作成 if st.session_state.uploaded_file_content: prompt = f"以下のファイル内容を参考にして回答してください:\n\n{st.session_state.uploaded_file_content}\n\nユーザーの質問: {prompt}" if mode == "focus": search_results = tavily_client.search(prompt, search_depth="advanced") prompt_template = PromptTemplate( input_variables=["query", "search_results"], template="質問: {query}\n\n検索結果: {search_results}\n\n上記の情報に基づいて、詳細な回答を提供してください:" ) chain = LLMChain(llm=llm, prompt=prompt_template) full_response = chain.invoke({"query": prompt, "search_results": search_results["results"]})["text"] message_placeholder.markdown(full_response) if search_results["results"]: for result in search_results["results"][:3]: st.markdown(f"参考URL: {result['url']}") elif mode == "writing": prompt_template = PromptTemplate( input_variables=["topic"], template="次のトピックについて包括的な記事を書いてください: {topic}\n\n導入、主要なポイント、および結論を含めてください。" ) chain = LLMChain(llm=llm, prompt=prompt_template) full_response = chain.invoke({"topic": prompt})["text"] message_placeholder.markdown(full_response) elif mode == "知恵袋": search_results = tavily_client.search(prompt, search_depth="advanced") context = "\n".join([result["content"] for result in search_results["results"]]) prompt_template = PromptTemplate( input_variables=["question", "context"], template="あなたは知恵袋の回答者です。以下の質問と関連情報に基づいて、丁寧かつ詳細に回答してください:\n\n質問: {question}\n\n関連情報: {context}\n\n回答:" ) chain = LLMChain(llm=llm, prompt=prompt_template) full_response = chain.invoke({"question": prompt, "context": context})["text"] message_placeholder.markdown(full_response) elif mode == "summary": search_results = tavily_client.search(prompt, search_depth="advanced") text_to_summarize = "\n".join([result["content"] for result in search_results["results"]]) prompt_template = PromptTemplate( input_variables=["text"], template="次のテキストを簡潔に要約してください:\n\n{text}\n\n主要なポイントを捉えた簡潔な要約を提供してください。" ) chain = LLMChain(llm=llm, prompt=prompt_template) full_response = chain.invoke({"text": text_to_summarize})["text"] message_placeholder.markdown(full_response) # コピー機能の追加 if st.button("📋 生成されたテキストをコピー"): clipboard.copy(full_response) st.success("テキストがクリップボードにコピーされました!")