Spaces:
Sleeping
Sleeping
File size: 8,632 Bytes
2529adf 3596a9a 2529adf | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 | import streamlit as st
import requests
import json
from duckduckgo_search import DDGS
import re
import clipboard
import io
import os
import pandas as pd
from PyPDF2 import PdfFileReader
from PIL import Image
import pytesseract
from bs4 import BeautifulSoup
import tiktoken
from langchain import LLMChain, PromptTemplate
# OpenRouter APIキーの設定
OPENROUTER_API_KEY = os.getenv("OPENROUTER_API_KEY").strip()
# Streamlitアプリケーションの設定
st.set_page_config(page_title="Orb 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 "Web page could not be retrieved"
soup = BeautifulSoup(response.text, 'html.parser')
paragraphs = soup.find_all('p')
text_content = ' '.join([paragraph.get_text() for paragraph in paragraphs])
return text_content
def truncate_prompt(prompt, max_tokens):
tokenizer = tiktoken.get_encoding("cl100k_base")
tokens = tokenizer.encode(prompt)
if len(tokens) > max_tokens:
truncated_tokens = tokens[:max_tokens]
truncated_prompt = tokenizer.decode(truncated_tokens)
return truncated_prompt
return prompt
def call_openrouter_api(prompt, model):
max_context_tokens = 4096
completion_tokens = 500
max_prompt_tokens = max_context_tokens - completion_tokens
truncated_prompt = truncate_prompt(prompt, max_prompt_tokens)
response = requests.post(
url="https://openrouter.ai/api/v1/chat/completions",
headers={
"Authorization": f"Bearer {OPENROUTER_API_KEY}",
"HTTP-Referer": "https://supertakerin2-comcomgptfree.hf.space/",
"X-Title": "Orb AI",
},
data=json.dumps({
"model": model,
"messages": [{"role": "user", "content": truncated_prompt}]
})
)
if response.status_code == 200:
try:
response_json = response.json()
if "choices" in response_json:
return response_json["choices"][0]["message"]["content"]
else:
st.error("API response does not contain 'choices'")
return "API response does not contain 'choices'"
except json.JSONDecodeError:
st.error("API response JSON decoding failed.")
return "API response JSON decoding failed."
else:
st.error(f"API request failed status code: {response.status_code}, message: {response.text}")
return "API request failed"
# サイドバーにAIモデルの選択、モード選択、ファイルアップロードを配置
with st.sidebar:
ai_model = st.selectbox(
"Select AI model",
["openchat/openchat-7b:free", "microsoft/phi-3-mini-128k-instruct:free", "meta-llama/llama-3.1-8b-instruct:free", "google/gemma-7b-it:free", "undi95/toppy-m-7b:free", "mistralai/mistral-7b-instruct:free"],
key="model_select"
)
mode = st.selectbox(
"Select mode",
["focus", "writing", "video", "summary"],
key="mode_select"
)
# ファイルアップロード機能をサイドバーに移動
uploaded_file = st.file_uploader("Upload file", type=["txt", "pdf", "csv", "py", "html", "css", "js", "cs", "php", "java", "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 ['jpg']:
st.session_state.uploaded_file_content = read_image(uploaded_file)
st.success(f"file '{uploaded_file.name}' was uploaded")
# 会話をクリアするボタン
if st.button("🔥 Delete conversation"):
st.session_state.messages = []
st.session_state.uploaded_file_content = None
# メインコンテンツ
st.title("Orb AI")
# チャット履歴の表示
for message in st.session_state.messages:
with st.chat_message(message["role"]):
st.markdown(message["content"])
# ユーザー入力
if prompt := st.chat_input("Please enter your message."):
st.session_state.messages.append({"role": "user", "content": prompt})
with st.chat_message("user"):
st.markdown(prompt)
# アップロードされたファイルの内容を考慮してプロンプトを作成
if st.session_state.uploaded_file_content:
prompt = f"以下のファイル内容を参考にして回答してください:\n\n{st.session_state.uploaded_file_content}\n\nユーザーの質問: {prompt}"
full_response = ""
if mode == "focus":
# DuckDuckGo検索の実行
with DDGS() as ddgs:
search_results = list(ddgs.text(prompt, max_results=4))
search_results_text = "\n".join([result["body"] for result in search_results])
urls = "\n".join([result["href"] for result in search_results[:4]])
prompt = f"質問: {prompt}\n\n検索結果: {search_results_text}\n\n上記の情報に基づいて、詳細な回答を提供してください:"
full_response = call_openrouter_api(prompt, ai_model)
# 回答の下に検索結果のURLを表示
with st.chat_message("assistant"):
st.markdown(full_response)
st.markdown("### Sources:")
st.markdown(urls)
elif mode == "writing":
prompt = f"次のトピックについて包括的な記事を書いてください: {prompt}\n\n導入、主要なポイント、および結論を含めてください。"
full_response = call_openrouter_api(prompt, ai_model)
with st.chat_message("assistant"):
st.markdown(full_response)
elif mode == "summary":
prompt = f"次のテキストを簡潔に要約してください:\n\n{prompt}\n\n主要なポイントを捉えた簡潔な要約を提供してください。"
full_response = call_openrouter_api(prompt, ai_model)
with st.chat_message("assistant"):
st.markdown(full_response)
elif mode == "video":
# DuckDuckGo検索を使用してYouTubeの動画を検索
with DDGS() as ddgs:
search_results = list(ddgs.text(f"{prompt} site:youtube.com", max_results=5))
if search_results:
for result in search_results[:4]:
video_url = result['href']
video_id = None
youtube_patterns = [
r"(?<=v=)[^/]+",
r"(?<=be/)[^/]+",
r"(?<=embed/)[^/]+"
]
for pattern in youtube_patterns:
match = re.search(pattern, video_url)
if match:
video_id = match.group()
break
if video_id:
st.markdown(f'<iframe width="560" height="315" src="https://www.youtube.com/embed/{video_id}" frameborder="0" allowfullscreen></iframe>', unsafe_allow_html=True)
st.markdown(f"Related Videos: {result['title']}")
else:
st.warning(f"Video ID not found: {video_url}")
else:
full_response = "No related videos were found."
with st.chat_message("assistant"):
st.markdown(full_response)
# コピー機能の追加
if st.button("📋 Copy the generated text"):
clipboard.copy(full_response)
st.success("Text has been copied to the clipboard!") |