import os import openai import json import requests from bs4 import BeautifulSoup from langchain.chat_models import ChatOpenAI from langchain_experimental.plan_and_execute import PlanAndExecute, load_agent_executor, load_chat_planner from langchain.llms import OpenAI from langchain.agents.tools import Tool # APIキーの設定 openai.api_key = os.getenv("OPENAI_API_KEY") tavily_api_key = os.getenv('TAVILY_API_KEY') # Tavily APIのカスタムツールを定義 class EnhancedTavilySearchTool: def search(self, query): if len(query) < 5: query += " details" # クエリを拡張して必要な文字数にする params = { 'api_key': tavily_api_key, 'query': query, 'max_results': 5, 'detail_level': 'high' } response = requests.post('https://api.tavily.com/search', json=params) if response.status_code == 200: return response.json()['results'] else: raise Exception(f"Failed to fetch data from Tavily API: {response.status_code}, {response.text}") # 実行された指示を追跡するリスト executed_instructions = [] # 調査結果を保存するリスト research_results = [] # 生成状態を保存するファイル state_file = "state.json" def save_state(state): with open(state_file, "w", encoding="utf-8") as f: json.dump(state, f, ensure_ascii=False, indent=4) def load_state(): if os.path.exists(state_file): with open(state_file, "r", encoding="utf-8") as f: return json.load(f) return None def clear_state(): if os.path.exists(state_file): os.remove(state_file) global executed_instructions, research_results executed_instructions = [] research_results = [] return "状態がクリアされました" def generate_article(editable_output2): # 途中から再開する場合のために状態を読み込み state = load_state() or {'executed_instructions': [], 'research_results': [], 'current_index': 0} executed_instructions = state['executed_instructions'] research_results = state['research_results'] current_index = state['current_index'] tavily_search_tool = Tool( name="TavilySearch", func=EnhancedTavilySearchTool().search, description="Enhanced search tool using Tavily API" ) tools = [tavily_search_tool] # PlannerとExecutorの拡張定義 model_name = "gpt-3.5-turbo-0125" llm = ChatOpenAI(model_name=model_name, temperature=0, max_tokens=1000) planner = load_chat_planner(llm) executor = load_agent_executor(llm, tools, verbose=True) agent = PlanAndExecute(planner=planner, executor=executor, verbose=True) # HTML解析 soup = BeautifulSoup(editable_output2, 'html.parser') h1_text = soup.find('h1').get_text() h2_texts = [h2.get_text() for h2 in soup.find_all('h2')] h3_texts = [h3.get_text() for h3 in soup.find_all('h3')] for h2_text in h2_texts: h3_for_this_h2 = [h3 for h3 in h3_texts if h3.startswith(f"{h2_texts.index(h2_text)+1}-")] # 特定情報の指定 purpose = f"Research details about {h2_text} including {' and '.join(h3_for_this_h2)}" if "人物" in h1_text or any("人物" in h2 for h2 in h2_texts) or any("人物" in h3 for h3 in h3_texts): purpose += " including the person's name and career" elif "商品" in h1_text or any("商品" in h2 for h2 in h2_texts) or any("商品" in h3 for h3 in h3_texts): purpose += " including the brand name, product name, and price" elif "イベント" in h1_text or any("イベント" in h2 for h2 in h2_texts) or any("イベント" in h3 for h3 in h3_texts): purpose += " including the event's content, schedule, and venue" if purpose not in executed_instructions: try: response = agent.run(purpose) executed_instructions.append(purpose) research_results.append(response) save_state({'executed_instructions': executed_instructions, 'research_results': research_results, 'current_index': h2_texts.index(h2_text) + 1}) except Exception as e: print(f"Error occurred: {str(e)}") # エラー時に状態を保存して中断 save_state({'executed_instructions': executed_instructions, 'research_results': research_results, 'current_index': h2_texts.index(h2_text)}) return str(e) else: index = executed_instructions.index(purpose) response = research_results[index] system_message = { "role": "system", "content": "あなたはプロのライターです。すべての回答を日本語でお願いします。" } research_summary = "\n".join(research_results) instructions = [] instructions.append(f"""