From d04f794afa3408ff53505b8895c457d17167ad61 Mon Sep 17 00:00:00 2001 From: xiangjinyu Date: Tue, 11 Feb 2025 17:59:05 +0800 Subject: [PATCH] modify spo logger and app --- metagpt/ext/spo/app.py | 76 +++++++++++++++++-------- metagpt/ext/spo/components/optimizer.py | 28 ++++++--- 2 files changed, 73 insertions(+), 31 deletions(-) diff --git a/metagpt/ext/spo/app.py b/metagpt/ext/spo/app.py index ca40ff859..5e4f1d7d6 100644 --- a/metagpt/ext/spo/app.py +++ b/metagpt/ext/spo/app.py @@ -1,3 +1,4 @@ +from loguru import logger as _logger import sys from pathlib import Path @@ -10,6 +11,7 @@ sys.path.append(str(root_path)) from metagpt.ext.spo.components.optimizer import PromptOptimizer from metagpt.ext.spo.utils.llm_client import SPO_LLM +from metagpt.const import METAGPT_ROOT def load_yaml_template(template_path): @@ -159,34 +161,60 @@ def main(): } st.code(yaml.dump(preview_data, allow_unicode=True), language="yaml") - # Start optimization button - if st.button("Start Optimization"): - try: - # Initialize LLM - SPO_LLM.initialize( - optimize_kwargs={"model": opt_model, "temperature": opt_temp}, - evaluate_kwargs={"model": eval_model, "temperature": eval_temp}, - execute_kwargs={"model": exec_model, "temperature": exec_temp}, - ) + # 创建一个固定的容器来显示日志 + st.subheader("Optimization Logs") + log_container = st.empty() - # Create optimizer instance - optimizer = PromptOptimizer( - optimized_path="workspace", - initial_round=initial_round, - max_rounds=max_rounds, - template=f"{template_name}.yaml", - name=template_name, - iteration=True, - ) + class StreamlitSink: + def write(self, message): + # 获取当前日志内容 + current_logs = st.session_state.get('logs', []) + current_logs.append(message.strip()) + st.session_state.logs = current_logs - # Run optimization with progress bar - with st.spinner("Optimizing prompts..."): - optimizer.optimize() + # 使用 code 块显示日志 + log_container.code( + "\n".join(current_logs), + language="plaintext" + ) - st.success("Optimization completed!") + # 配置loguru日志 + streamlit_sink = StreamlitSink() + _logger.remove() + _logger.add( + streamlit_sink.write, + format="{time:YYYY-MM-DD HH:mm:ss.SSS} | {level: <8} | {name}:{function}:{line} - {message}" + ) + _logger.add(METAGPT_ROOT / "logs/{time:YYYYMMDD}.txt", level="DEBUG") + # Start optimization button + if st.button("Start Optimization"): + try: + # Initialize LLM + SPO_LLM.initialize( + optimize_kwargs={"model": opt_model, "temperature": opt_temp}, + evaluate_kwargs={"model": eval_model, "temperature": eval_temp}, + execute_kwargs={"model": exec_model, "temperature": exec_temp}, + ) - except Exception as e: - st.error(f"An error occurred: {str(e)}") + # Create optimizer instance + optimizer = PromptOptimizer( + optimized_path="workspace", + initial_round=initial_round, + max_rounds=max_rounds, + template=f"{template_name}.yaml", + name=template_name, + iteration=True, + ) + + # Run optimization with progress bar + with st.spinner("Optimizing prompts..."): + optimizer.optimize() + + st.success("Optimization completed!") + + except Exception as e: + st.error(f"An error occurred: {str(e)}") + _logger.error(f"Error during optimization: {str(e)}") if __name__ == "__main__": diff --git a/metagpt/ext/spo/components/optimizer.py b/metagpt/ext/spo/components/optimizer.py index 8d41a8aac..9887026c0 100644 --- a/metagpt/ext/spo/components/optimizer.py +++ b/metagpt/ext/spo/components/optimizer.py @@ -44,13 +44,13 @@ class PromptOptimizer: asyncio.set_event_loop(loop) prompt = loop.run_until_complete(self._optimize_prompt()) self.round += 1 - logger.info(f"Prompt generated in round {self.round}: {prompt}") + # logger.info(f"Prompt generated in round {self.round}: {prompt}") else: loop = asyncio.new_event_loop() asyncio.set_event_loop(loop) prompt = loop.run_until_complete(self._test_prompt()) - logger.info(f"Prompt generated in round {self.round}: {prompt}") + # logger.info(f"Prompt generated in round {self.round}: {prompt}") async def _optimize_prompt(self): prompt_path = f"{self.root_path}/prompts" @@ -59,6 +59,9 @@ class PromptOptimizer: data = self.data_utils.load_results(prompt_path) if self.round == 1: + + logger.info("\n⚡ RUNNING Round 1 PROMPT ⚡\n") + directory = self.prompt_utils.create_round_directory(prompt_path, self.round) # Load prompt using prompt_utils @@ -77,7 +80,9 @@ class PromptOptimizer: samples = self.data_utils.get_best_round() - logger.info(f"choose {samples['round']}") + logger.info(f"\n🚀Round {self.round+1} OPTIMIZATION STARTING 🚀\n") + logger.info(f"\nSelecting prompt for round {samples['round']} and advancing to the iteration phase\n") + golden_answer = self.data_utils.list_to_markdown(qa) best_answer = self.data_utils.list_to_markdown(samples["answers"]) @@ -96,7 +101,7 @@ class PromptOptimizer: modification = extract_content(response, "modification") - logger.info(f"Modification of this round: {modification}") + logger.info(f"Modification of {self.round+1} round: {modification}") prompt = extract_content(response, "prompt") @@ -105,9 +110,16 @@ class PromptOptimizer: else: self.prompt = "" + logger.info("\n🎯 NEW PROMPT GENERATED 🎯\n") + logger.info(f"\nRound {self.round+1} Prompt: {self.prompt}\n") + self.prompt_utils.write_prompt(directory, prompt=self.prompt) - new_samples = await self.evaluation_utils.execute_prompt(self, directory, data) + logger.info("\n⚡ RUNNING OPTIMIZED PROMPT ⚡\n") + + new_samples = await self.evaluation_utils.execute_prompt(self, directory) + + logger.info("\n📊 EVALUATING OPTIMIZED PROMPT 📊\n") success, answers = await self.evaluation_utils.evaluate_prompt( self, samples, new_samples, path=prompt_path, data=data, initial=False @@ -115,9 +127,11 @@ class PromptOptimizer: self.prompt_utils.write_answers(directory, answers=answers) - logger.info(f"Current round optimization successful:{success}") + logger.info("\n🎯 OPTIMIZATION RESULT 🎯\n") + logger.info(f"\nRound {self.round + 1} Optimization: {'✅ SUCCESS' if success else '❌ FAILED'}\n") - logger.info(f"now is {self.round + 1}") + + # logger.info(f"now is {self.round + 1}") return prompt