File size: 5,621 Bytes
68a83b7
 
 
 
 
922a900
 
 
68a83b7
 
 
 
 
922a900
68a83b7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
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
import gradio as gr
import cohere
import psycopg2
from psycopg2.extras import RealDictCursor
import os
from dotenv import load_dotenv

load_dotenv()

# 環境変数の設定
os.environ["PYTHONIOENCODING"] = "utf-8"

# --- 設定 ---
COHERE_API_KEY = os.getenv("COHERE_API_KEY")
DB_CONFIG = {
    "host": "www.ryhintl.com",
    "dbname": "smair",
    "user": "smairuser",
    "password": "smairuser",
    "port": 10629,
    "connect_timeout": 15
}

co = cohere.Client(COHERE_API_KEY)

def generate_ai_advice(query, results):
    context = ""
    for res in results:
        context += f"- 事例: {res['title']}\n  現象: {res['phenomenon']}\n  原因: {res['cause']}\n  処置: {res['action']}\n  防止策: {res['prevention']}\n\n"

    prompt = f"""
あなたはベテランの工場管理者です。以下の「ユーザーからの相談内容」に対し、提供された「過去の類似事例」を参考にして、現場で今すぐ取るべき行動と、長期的な対策をプロの視点で要約・アドバイスしてください。

# ユーザーからの相談内容:
{query}

# 過去の類似事例:
{context}

# 回答の指針:
1. 過去事例から共通する原因を特定してください。
2. 現場担当者が優先して確認すべき点(チェックポイント)を3つ挙げてください。
3. 再発防止のための改善提案を簡潔に述べてください。
回答は日本語で、現場で読みやすいように箇条書きを活用してください。
"""
    # model名を安定した名称に変更(command-r-plusなど)
    response = co.chat(
        message=prompt,
        model='command-a-03-2025' 
    )
    return response.text

def search_troubles(query):
    if not query.strip():
        return "⚠️ トラブル事象を入力してください。"

    conn = None
    try:
        # 1. ベクトル化
        res = co.embed(
            texts=[query],
            model='embed-multilingual-v3.0',
            input_type='search_query'
        )
        query_embedding = res.embeddings[0]

        # 2. DB接続
        conn = psycopg2.connect(**DB_CONFIG, client_encoding='utf8')
        cur = conn.cursor(cursor_factory=RealDictCursor)
        
        search_query = """
        SELECT id, occurrence_date, process_name, equipment_name, title, 
               phenomenon, cause, action, prevention, severity,
               1 - (embedding <=> %s::vector) AS similarity
        FROM factory_troubles
        ORDER BY similarity DESC
        LIMIT 3;
        """
        cur.execute(search_query, (query_embedding,))
        results = cur.fetchall()
        
        if not results:
            return "該当する事例が見つかりませんでした。"

        # 3. AIによるアドバイス生成
        ai_advice = generate_ai_advice(query, results)

        # 4. フォーマット
        output = "## 🤖 AIからのトラブルシューティング・アドバイス\n\n"
        output += f"{ai_advice}\n\n"
        output += "---\n"
        output += "## 🔍 参考にした過去の類似事例\n\n"
        
        for i, res in enumerate(results):
            output += f"### {i+1}. {res['title']} (類似度: {res['similarity']:.4f})\n"
            output += f"**【処置】**: {res['action']}\n\n"
            output += f"""
<details>
<summary><b>📄 元のデータ(出典詳細)を表示</b></summary>
<div style="background-color: #f9f9f9; padding: 10px; border-radius: 5px; border: 1px solid #ddd; color: #333;">
    <p><b>発生日:</b> {res['occurrence_date']} | <b>工程:</b> {res['process_name']}</p>
    <p><b>現象:</b> {res['phenomenon']}</p>
    <p><b>原因:</b> {res['cause']}</p>
    <p><b>防止策:</b> {res['prevention']}</p>
</div>
</details>\n\n---\n"""
        return output

    except Exception as e:
        return f"### ⚠️ エラーが発生しました\n詳細: `{repr(e)}`"
    finally:
        if conn: conn.close()

# --- Gradio Blocks UI ---
with gr.Blocks(title="AI工場トラブル・コンシェルジュ", css=".gradio-container {background-color: #f5f7f9}") as demo:
    gr.Markdown("# 🛠 AI工場トラブル・コンシェルジュ")
    gr.Markdown("過去の知見に基づき、AIが現場の課題解決に向けたアドバイスを生成します。")
    
    with gr.Row():
        with gr.Column():
            input_text = gr.Textbox(
                label="現在のトラブル状況を入力", 
                info="例: コンベアのモーターが高温になっており、焦げたような臭いがする。 加工面の焼け発生している。 末端のシール部からの液漏れがある。",
                lines=3
            )
            # ボタンクリック時に非活性化するように設定可能
            search_btn = gr.Button("🔍 知見を検索してAIアドバイスを受ける", variant="primary")
            
    with gr.Row():
        # ステータス表示用のコンポーネント(任意ですが、標準機能で十分カバーされます)
        output_markdown = gr.Markdown(value="ここに結果が表示されます。")

    # .click の際に、検索中はボタンを無効化し、ローディングを表示する設定
    search_btn.click(
        fn=search_troubles,
        inputs=input_text,
        outputs=output_markdown,
        show_progress="full",    # "full"にすることで画面全体にローディングインジケータを表示
        scroll_to_output=True    # 完了時に結果へスクロール
    )

if __name__ == "__main__":
    demo.launch()