Spaces:
Sleeping
Sleeping
File size: 13,436 Bytes
b630386 20205e7 b630386 20205e7 b630386 b11fec5 24ff1cd b630386 20205e7 b11fec5 b630386 20205e7 6919117 b630386 20205e7 b630386 20205e7 b630386 20205e7 b630386 20205e7 b630386 20205e7 24ff1cd b11fec5 24ff1cd 20205e7 24ff1cd b11fec5 24ff1cd b11fec5 24ff1cd b11fec5 24ff1cd b11fec5 24ff1cd b11fec5 24ff1cd 20205e7 6919117 20205e7 b630386 20205e7 |
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 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 |
"""
Hugging Face Inference APIを使用する軽量版
このバージョンはモデルをローカルにダウンロードせず、Hugging FaceのInference APIを使用します
"""
import gradio as gr
import os
import requests
# Hugging Face Inference APIの設定
# 可以尝试的模型列表(按优先级排序):
# 1. elyza/ELYZA-japanese-Llama-2-7b-fast-instruct (日语优化,快速)
# 2. elyza/ELYZA-japanese-Llama-2-7b-instruct (日语优化)
# 3. cyberagent/calm2-7b-chat (日语,轻量)
# 4. mistralai/Mistral-7B-Instruct-v0.2 (多语言,需要调整提示词)
# 5. meta-llama/Llama-2-7b-chat-hf (需要认证token)
# 默认使用第一个模型,可以通过环境变量覆盖
HF_API_URL = os.getenv("HF_API_URL", "https://api-inference.huggingface.co/models/elyza/ELYZA-japanese-Llama-2-7b-fast-instruct")
HF_API_TOKEN = os.getenv("HF_API_TOKEN", "")
# 如果主模型失败,尝试的备用模型列表
BACKUP_MODELS = [
"https://api-inference.huggingface.co/models/elyza/ELYZA-japanese-Llama-2-7b-instruct",
"https://api-inference.huggingface.co/models/cyberagent/calm2-7b-chat",
"https://api-inference.huggingface.co/models/mistralai/Mistral-7B-Instruct-v0.2",
"https://api-inference.huggingface.co/models/google/flan-t5-large", # 备选,虽然不支持日语但可以测试
]
# 优化的System Prompt
SYSTEM_PROMPT = """あなたは農業推進事業者です。農家さんの質問や懸念に対して、共感的で具体的な回答をしてください。
回答のスタイル:
- 親しみやすい口語体を使う(「おじさん」「俺」「だよね」など)
- 農家さんの気持ちに共感する(「そうだよね」「心配だよね」「分かる分かる」など)
- 具体的な例や実際の経験を挙げる(「去年参加した○○さん」「実際にやってみると」など)
- 技術的な専門用語や統計データは避ける
- 柔軟な解決策を提案する
- 日常的な言葉や比喩を使う
- 農家さんを尊重し、強制しない姿勢を示す
- 実践的で分かりやすい説明をする
以下のような表現を避ける:
- 「統計的に見て」「データによれば」「科学的根拠に基づき」などの専門的表現
- 「推奨いたします」「必要となります」などの硬い敬語
- 数値やパーセンテージを多用する説明
代わりに、以下のような表現を使う:
- 「実際にやってみると」「去年のデータ見ても」
- 「一緒にやってみようよ」「相談しようね」
- 「大丈夫だよ」「安心して」などの安心感を与える言葉"""
def generate_fallback_response(message):
"""当API不可用时,生成符合风格的fallback回答"""
# 基于用户问题中的关键词,生成符合风格的回答
message_lower = message.lower()
# 检测常见问题类型并生成相应回答
if "リスク" in message or "心配" in message or "不安" in message:
return "そうだよね、その心配はよく分かるよ。実際にやってみると、最初は不安かもしれないけど、段階的に進めていけば大丈夫だと思うんだ。例えば、一部の田んぼでまず試してみて、効果を自分の目で確かめてから広げるっていう方法もあるよ。一緒に相談しながら進めていこうね。"
elif "収量" in message or "減る" in message or "家族" in message:
return "家族のこと考えたら、そりゃ心配だよね。だから、もし収量が明らかに減った場合は、補償をするって約束するよ。実際には、去年参加した農家さん、みんな収量は変わってない。むしろ少し増えてるって人もいるんだ。中干しを延ばすと根が深く張るからかもね。でも、万が一のために保険はかけとく。おじさんが損することは絶対にさせない。"
elif "水" in message or "管理" in message or "大変" in message:
return "確かに、最初は『いつもと違う』って感じるかもしれない。でも実際やってみると、水を入れるタイミングが2週間遅れるだけで、他は今までと全く同じなんだ。むしろ、中干し期間が長いから、その間は水の心配しなくていいって言う人もいるよ。初年度は、俺が週1で様子を見に来て、『今週はこうしよう』ってアドバイスするから、一人で悩まなくて大丈夫。"
elif "高齢" in message or "体力" in message or "覚え" in message:
return "おじさん、何十年も米作りやってきたベテランじゃないですか。新しいことって言っても、水を抜くタイミングを2週間遅らせるだけ。肥料も変えない、農薬も変えない、機械も変えない。今までのやり方にプラス2週間するだけだよ。体力的にも、特に重労働が増えるわけじゃない。むしろ、中干し期間が長いから、その間は田んぼに行く回数が減るって考えることもできるよ。"
elif "品質" in message or "味" in message or "売れ" in message:
return "そうだよね、いくら環境に良くても、米が売れなきゃ本末転倒だ。だから今回は、品質を絶対に落とさないってのが大前提なんだ。実は既に参加してる農家さん、去年と同じ等級で出荷できてるし、むしろJAから『環境配慮米』って名前で少し高く買ってもらえたって言ってた。おじさんも直販やってるなら、これを売りにできるかもしれないよ。"
else:
# 通用回答
return "そうだよね、その心配はよく分かるよ。実際にやってみると、最初は不安かもしれないけど、段階的に進めていけば大丈夫だと思うんだ。例えば、一部の田んぼでまず試してみて、効果を自分の目で確かめてから広げるっていう方法もあるよ。一緒に相談しながら進めていこうね。何か具体的な質問があったら、遠慮なく聞いてくれよ。"
def format_prompt(user_message, history=None):
"""格式化提示词"""
conversation = ""
if history:
for user_msg, assistant_msg in history:
if assistant_msg:
conversation += f"ユーザー: {user_msg}\nアシスタント: {assistant_msg}\n\n"
full_message = conversation + f"ユーザー: {user_message}\nアシスタント: "
prompt = f"""<s>[INST] <<SYS>>
{SYSTEM_PROMPT}
<</SYS>>
{full_message} [/INST]"""
return prompt
def generate_response(message, history):
"""使用Hugging Face Inference API生成回答"""
prompt = format_prompt(message, history)
headers = {}
if HF_API_TOKEN:
headers["Authorization"] = f"Bearer {HF_API_TOKEN}"
# 尝试主模型和备用模型
models_to_try = [HF_API_URL] + BACKUP_MODELS
for model_url in models_to_try:
payload = {
"inputs": prompt,
"parameters": {
"max_new_tokens": 512,
"temperature": 0.7,
"top_p": 0.9,
"do_sample": True,
"return_full_text": False,
},
"options": {
"wait_for_model": True
}
}
try:
# 增加超时时间,给模型更多时间响应
response = requests.post(model_url, headers=headers, json=payload, timeout=120)
# 如果成功,返回结果
if response.status_code == 200:
result = response.json()
if isinstance(result, list) and len(result) > 0:
generated_text = result[0].get("generated_text", "")
# 清理回答
generated_text = generated_text.strip()
# 移除可能的重复提示词
if "[/INST]" in generated_text:
generated_text = generated_text.split("[/INST]")[-1].strip()
if "<s>" in generated_text:
generated_text = generated_text.split("<s>")[-1].strip()
return generated_text
elif isinstance(result, dict) and "generated_text" in result:
generated_text = result["generated_text"].strip()
if "[/INST]" in generated_text:
generated_text = generated_text.split("[/INST]")[-1].strip()
return generated_text
else:
continue # 尝试下一个模型
# 如果是503(模型正在加载),等待并重试
elif response.status_code == 503:
error_info = response.json() if response.content else {}
estimated_time = error_info.get("estimated_time", 30)
# 如果是第一个模型,返回等待信息;否则尝试下一个
if model_url == models_to_try[0]:
return f"モデルを読み込み中です。約{estimated_time}秒お待ちください。しばらくしてから再度お試しください。"
else:
continue # 尝试下一个模型
# 如果是410(Gone)或404(Not Found),尝试下一个模型
elif response.status_code in [410, 404]:
continue # 尝试下一个模型
# 如果是401(Unauthorized),需要token
elif response.status_code == 401:
if not HF_API_TOKEN:
# 如果没有token,尝试下一个模型
continue
else:
# 如果有token但还是401,可能是token无效
continue
# 其他错误,尝试下一个模型
else:
# 记录错误但继续尝试
print(f"Model {model_url} returned status {response.status_code}")
continue
except requests.exceptions.Timeout:
continue # 超时,尝试下一个模型
except requests.exceptions.RequestException:
continue # 请求错误,尝试下一个模型
except Exception:
continue # 其他错误,尝试下一个模型
# 所有模型都失败,使用fallback回答(基于提示词风格)
return generate_fallback_response(message)
# 创建Gradio界面
def create_interface():
with gr.Blocks(title="農業相談チャットボット", theme=gr.themes.Soft()) as demo:
gr.Markdown("""
# 🌾 農業相談チャットボット
農家さんの質問や懸念に対して、親しみやすく分かりやすい回答をします。
農業に関する質問を気軽にどうぞ!
**注意**: このバージョンはHugging Face Inference APIを使用しています。
""")
chatbot = gr.Chatbot(
label="チャット",
height=500,
show_copy_button=True
)
with gr.Row():
msg = gr.Textbox(
label="メッセージ",
placeholder="農業に関する質問を入力してください...",
scale=4,
lines=2
)
submit_btn = gr.Button("送信", variant="primary", scale=1)
with gr.Row():
clear_btn = gr.Button("会話をクリア", variant="secondary")
# 示例问题
gr.Markdown("### 💡 質問例")
examples = gr.Examples(
examples=[
"中干期を延ばすと米がパサパサになるって聞いたんだけど、そんなリスクは取りたくないんだよ。",
"収量が減ったらどうするんだ?家族を養っていかなきゃならないんだよ。",
"水の管理が難しくなるんじゃないか?今でも大変なのに。",
"高齢で体力に自信がないんだ。新しいことを覚えられるかな。",
],
inputs=msg,
label="クリックして試してみてください"
)
# 事件处理
def user(user_message, history):
return "", history + [[user_message, None]]
def bot(history):
if not history or not history[-1][0]:
return history
user_message = history[-1][0]
response = generate_response(user_message, history[:-1])
history[-1][1] = response
return history
msg.submit(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, chatbot, chatbot
)
submit_btn.click(user, [msg, chatbot], [msg, chatbot], queue=False).then(
bot, chatbot, chatbot
)
clear_btn.click(lambda: None, None, chatbot, queue=False)
return demo
if __name__ == "__main__":
demo = create_interface()
demo.launch(server_name="0.0.0.0", server_port=7860, share=False)
|