Spaces:
Sleeping
Sleeping
| # generators/summary.py | |
| from __future__ import annotations | |
| from typing import List, Tuple | |
| from irpr.deps import search, generate_chat | |
| SYS = "あなたは日本語のIRアナリストです。引用の根拠から経営サマリを作ります。冗長な敬語は避け、事実ベースで簡潔に。マークダウンで出力。" | |
| TPL = """以下は関連文書の抜粋です。これを根拠に、投資家向けの経営サマリを作成してください。 | |
| # 出力フォーマット | |
| 業績ハイライト: | |
| - 箇条書きで3-5項目 | |
| 見通し: | |
| - 2-4項目 | |
| セグメント: | |
| - 主要セグメントごとに1-2行 | |
| 財務: | |
| - 売上/利益、CF、BSの要点 | |
| 株主還元: | |
| - 配当/自社株買い等 | |
| ESG: | |
| - 重要事項があれば簡潔に | |
| リスク: | |
| - 2-3項目 | |
| # 根拠抜粋 | |
| {context} | |
| """ | |
| def make_summary(query: str, k: int = 12) -> Tuple[str, List[str]]: | |
| hits = search(query, top_k=k) | |
| links, ctx_lines = [], [] | |
| for i, h in enumerate(hits, 1): | |
| src = h.get("source_url") or "" | |
| if src and src not in links: | |
| links.append(src) | |
| # 1抜粋1200字まで | |
| ctx_lines.append(f"[{i}] {h.get('title') or ''} {src}\n{h['text'][:1200]}") | |
| context = "\n\n".join(ctx_lines) if ctx_lines else "(根拠なし)" | |
| # OpenAIで生成(失敗時は抽出フォールバック) | |
| try: | |
| text = generate_chat( | |
| [{"role":"system","content":SYS}, | |
| {"role":"user","content":TPL.format(context=context)}], | |
| max_new_tokens=900 | |
| ) | |
| if text.strip(): | |
| return text.strip(), links | |
| except Exception: | |
| pass | |
| # フォールバック(抽出) | |
| if not hits: | |
| return "根拠が見つかりませんでした。", links | |
| bullets = [] | |
| for h in hits[:5]: | |
| for line in (h["text"][:500]).splitlines(): | |
| line = line.strip() | |
| if 6 <= len(line) <= 120: | |
| bullets.append(f"- {line}") | |
| if len(bullets) >= 5: break | |
| if len(bullets) >= 5: break | |
| text = "業績ハイライト:\n" + "\n".join(bullets) + "\n\n見通し:\n- (抽出フォールバック)" | |
| return text, links | |