design
全3件を表示
-


00 自己紹介:
続きを読む
AI System Engineer × DATA Scientist
徐東秀(ソドンス) SEO DongSooQuick View -

31 39Safari 「ロゴデザイン」
続きを読むQuick View -
#core
import os
import sys
import time
from dotenv import load_dotenvimport streamlit as st
from langchain_openai import (
AzureOpenAIEmbeddings,
OpenAIEmbeddings,
AzureChatOpenAI,
ChatOpenAI
)
try:
from langchain_google_vertexai import ChatVertexAI
except ImportError:
ChatVertexAI = Nonetry:
from langchain_google_genai import ChatGoogleGenerativeAI
except ImportError:
ChatGoogleGenerativeAI = None
from langchain_community.vectorstores import FAISS
from langchain_core.messages import(
HumanMessage,
AIMessage,
)#tools
import pandas as pd
import numpy as np#import
from src.config import system_config
from src.rag_oop import B612ai
from src.logo import logo_img
from src.estimate_generator import EstimateGenerator
from src.sidebar import render_common_sidebar, clear_chat_historyUSER_ICON = “user”
ASSISTANT_ICON = “assistant”def create_embeddings():
“””埋め込みモデルを作成”””
api_config = system_config.api_configif api_config.is_azure_embedding_configured():
# Azure OpenAI Embeddingsを使用
embedding_config = api_config.get_azure_embedding_config()
return AzureOpenAIEmbeddings(
azure_deployment=embedding_config[‘deployment’],
openai_api_version=embedding_config[‘api_version’]
)
elif api_config.is_openai_configured():
# OpenAI Embeddingsを使用
return OpenAIEmbeddings(model=’text-embedding-3-small’)
else:
st.error(‘埋め込みモデルのAPI Keyが設定されていません。’)
return Nonedef create_model(selected_model=None):
“””言語モデルを作成”””
api_config = system_config.api_config
model_config = system_config.model_configif api_config.is_azure_configured():
# Azure OpenAIを使用
azure_config = api_config.get_azure_config()
return AzureChatOpenAI(
azure_deployment=azure_config[‘deployment’],
openai_api_version=azure_config[‘api_version’],
temperature=model_config.temperature
)
elif api_config.is_gemini_configured():
# Google Geminiを使用
gemini_config = api_config.get_gemini_config()# APIキー方式(Google AI Studio)
if gemini_config[‘api_key’]:
if ChatGoogleGenerativeAI is None:
st.error(‘langchain-google-genai パッケージがインストールされていません。’)
st.info(‘以下のコマンドでインストールしてください: pip install langchain-google-genai’)
return Nonereturn ChatGoogleGenerativeAI(
model=gemini_config[‘model_name’],
google_api_key=gemini_config[‘api_key’],
temperature=model_config.temperature
)# Vertex AI方式
elif gemini_config[‘project_id’]:
if ChatVertexAI is None:
st.error(‘langchain-google-vertexai パッケージがインストールされていません。’)
st.info(‘以下のコマンドでインストールしてください: pip install langchain-google-vertexai’)
return Nonereturn ChatVertexAI(
model_name=gemini_config[‘model_name’],
project=gemini_config[‘project_id’],
location=gemini_config[‘location’],
temperature=model_config.temperature
)
else:
st.error(‘Geminiの設定が不完全です。APIキーまたはプロジェクトIDを設定してください。’)
return Noneelif api_config.is_openai_configured():
# OpenAI APIを使用(選択されたモデルに基づく)
if selected_model:
# 選択されたモデルに基づいてモデル名を決定
model_mapping = {
“gpt-3.5”: “gpt-3.5-turbo”,
“gpt-4o”: “gpt-4o”,
“gpt-o1”: “o1-preview”,
“gpt-5”: “gpt-5” # 将来のモデル
}
model_name = model_mapping.get(selected_model, “gpt-3.5-turbo”)
else:
openai_config = api_config.get_openai_config()
model_name = openai_config[‘api_version’] if openai_config[‘api_version’] else “gpt-3.5-turbo”return ChatOpenAI(
model=model_name,
temperature=model_config.temperature
)
else:
st.error(‘言語モデルのAPI Keyが設定されていません。’)
return Nonedef main():
# システム設定のチェック(load_dotenv()はconfig.pyで実行済み)
if not system_config.check_system_health():
st.stop()size = “large”
logo_img(size)# 共通のサイドバーをレンダリング
render_common_sidebar()
clear_chat_history()st.title(‘📄 見積書作成ページ’)
st.caption(“AIチャットの内容をもとに、Excel見積書を自動生成します”)# 埋め込みモデルと言語モデルの作成
embeddings = create_embeddings()# セッション状態から選択されたモデルを取得
selected_model = st.session_state.get(‘selected_model’, ‘gpt-3.5’)
model = create_model(selected_model)if embeddings is None or model is None:
st.error(“モデルの初期化に失敗しました。”)
st.stop()# B612aiの初期化
rag_system = B612ai(
model=model,
embeddings=embeddings,
chunk_size=system_config.model_config.chunk_size,
chunk_overlap=system_config.model_config.chunk_overlap
)# FAISSベクトルストアの読み込み(存在しない場合はエラーメッセージを表示)
retriever = rag_system.pull_from_faiss()# ベクトルストアをB612aiに設定
rag_system.vectorstore = FAISS.load_local(“vector_store”, rag_system.embeddings, allow_dangerous_deserialization=True)
rag_system.retriever = rag_system.vectorstore.as_retriever()if “chat_log” not in st.session_state:
st.session_state.chat_log = []# チャット履歴の表示(プレーンテキストで表示してスマホエラーを回避)
if len(st.session_state.chat_log) > 0:
st.subheader(“💬 チャット履歴”)
for chat in st.session_state.chat_log:
if isinstance(chat, AIMessage):
with st.chat_message(ASSISTANT_ICON):
st.text(chat.content)
else:
with st.chat_message(USER_ICON):
st.text(chat.content)# 見積書作成機能
if len(st.session_state.chat_log) > 0:
st.divider()
st.subheader(“📄 見積書作成”)
st.caption(“チャット履歴から見積書情報を抽出してExcel見積書を作成します”)# オレンジ色のボタンスタイル(スマホブラウザ対応)
st.markdown(“””
<style>
/* Primaryボタンのスタイル */
button[kind=”primary”] {
background-color: #FFA421 !important;
color: white !important;
border: none !important;
}
button[kind=”primary”]:hover {
background-color: #FFB84D !important;
color: white !important;
}/* ダウンロードボタンのスタイル */
div[data-testid=”stDownloadButton”] button {
background-color: #FFA421 !important;
color: white !important;
border: none !important;
}
div[data-testid=”stDownloadButton”] button:hover {
background-color: #FFB84D !important;
color: white !important;
}
</style>
“””, unsafe_allow_html=True)col2, = st.columns([1])
with col2:
if st.button(” 見積書を作成”, type=”primary”, use_container_width=True):
with st.spinner(“見積書情報を抽出中…”):
try:
# 見積書生成器を初期化
estimate_generator = EstimateGenerator(model)# チャット履歴から見積書情報を抽出
estimate_info = estimate_generator.extract_estimate_info(st.session_state.chat_log)# 見積書情報をExcel形式で表示
with st.expander(“抽出された見積書情報”, expanded=True):
# 基本情報を表示
col_info1, col_info2 = st.columns(2)
with col_info1:
st.write(“**顧客名:**”)
st.write(estimate_info.get(‘company_name’, ‘N/A’))
st.write(“**見積番号:**”)
st.write(estimate_info.get(‘estimate_number’, ‘N/A’))
with col_info2:
st.write(“**見積日:**”)
st.write(estimate_info.get(‘estimate_date’, ‘N/A’))
st.write(“**件名:**”)
st.write(estimate_info.get(‘title’, ‘N/A’))st.divider()
# 商品・サービス一覧をテーブル形式で表示
if ‘items’ in estimate_info and estimate_info[‘items’]:
items_data = []
for idx, item in enumerate(estimate_info[‘items’], start=1):
items_data.append({
‘No’: idx,
‘商品・サービス名’: item.get(‘name’, ”),
‘数量’: item.get(‘quantity’, 0),
‘単価’: f”¥{item.get(‘unit_price’, 0):,}”,
‘金額’: f”¥{item.get(‘amount’, 0):,}”,
‘説明’: item.get(‘description’, ”)
})
items_df = pd.DataFrame(items_data)
st.write(“**商品・サービス一覧:**”)
st.dataframe(items_df, use_container_width=True, hide_index=True)st.divider()
# 金額情報を表示
col_amount1, col_amount2, col_amount3 = st.columns(3)
with col_amount1:
st.write(“**小計:**”)
st.write(f”¥{estimate_info.get(‘subtotal’, 0):,}”)
with col_amount2:
tax_rate = estimate_info.get(‘tax_rate’, 0.1)
tax_rate_percent = int(tax_rate * 100)
st.write(f”**消費税 ({tax_rate_percent}%):**”)
st.write(f”¥{estimate_info.get(‘tax’, 0):,}”)
with col_amount3:
st.write(“**合計:**”)
st.write(f”**¥{estimate_info.get(‘total’, 0):,}**”)# 備考がある場合
if estimate_info.get(‘notes’):
st.divider()
st.write(“**備考:**”)
st.write(estimate_info.get(‘notes’))# Excel見積書を作成
with st.spinner(“Excel見積書を作成中…”):
excel_path = estimate_generator.create_excel_estimate(estimate_info)# ファイルを読み込んでダウンロードボタンとキャンセルボタンを表示
with open(excel_path, “rb”) as f:
excel_data = f.read()
col_download, col_cancel = st.columns(2)
with col_download:
st.download_button(
label=”見積書をダウンロード”,
data=excel_data,
file_name=excel_path,
mime=”application/vnd.openxmlformats-officedocument.spreadsheetml.sheet”,
use_container_width=True
)
with col_cancel:
if st.button(“キャンセル”, type=”secondary”, use_container_width=True):
st.info(“見積書の作成をキャンセルしました。”)
st.rerun()# 一時ファイルを削除
if os.path.exists(excel_path):
os.remove(excel_path)st.success(“✅ 見積書が正常に作成されました!”)
except Exception as e:
st.error(f”見積書作成中にエラーが発生しました: {str(e)}”)
st.exception(e)else:
st.info(“💬 まずチャットで会話を始めてください。会話内容から見積書情報を抽出します。”)# チャット入力(プレーンテキストで表示してスマホエラーを回避)
user_msg = st.chat_input(“メッセージをご入力ください。”)
if user_msg:
with st.chat_message(USER_ICON):
st.text(user_msg)# B612aiを使用して回答を生成
with st.chat_message(ASSISTANT_ICON):
msg_placeholder = st.empty()try:
# 関連文書を検索
relavant_docs = rag_system.search(user_msg, k=3)# 回答を生成
response = rag_system.generate_response(user_msg, relavant_docs)# ストリーミング表示(プレーンテキストで表示してスマホエラーを回避)
for i, char in enumerate(response):
msg_placeholder.text(response[:i+1] + “*”)
time.sleep(0.01) # ストリーミング効果
msg_placeholder.text(response)# 関連資料の表示(B612aiクラスから)
rag_system.display_related_images(user_msg, relavant_docs)except Exception as e:
st.error(f”回答生成中にエラーが発生しました: {str(e)}”)
response = “申し訳ございません。エラーが発生しました。”st.session_state.chat_log.extend([
HumanMessage(content=user_msg),
AIMessage(content=response)
])
st.rerun()if __name__ == ‘__main__’:
main()
32 雑誌のデザイン
続きを読むQuick View


