mirror of
https://github.com/microsoft/qlib.git
synced 2026-07-16 01:06:56 +08:00
Optimize prompt for entire learn loop (#1589)
* Adjust prompt and fix cases * adjust summarizeTask & learn prompts; * fix typos & drop duplicate task method; * adjust learn prompts;
This commit is contained in:
@@ -1,8 +1,10 @@
|
|||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from jinja2 import Template
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from qlib.workflow import R
|
from qlib.workflow import R
|
||||||
from qlib.finco.log import FinCoLog
|
from qlib.finco.log import FinCoLog
|
||||||
from qlib.finco.llm import APIBackend
|
from qlib.finco.llm import APIBackend
|
||||||
from jinja2 import Template
|
|
||||||
|
|
||||||
|
|
||||||
class Knowledge:
|
class Knowledge:
|
||||||
@@ -95,7 +97,7 @@ class KnowledgeBase:
|
|||||||
Load knowledge, offer brief information of knowledge and common handle interfaces
|
Load knowledge, offer brief information of knowledge and common handle interfaces
|
||||||
"""
|
"""
|
||||||
|
|
||||||
def __init__(self, init_path=None, topics: list[Topic] = None):
|
def __init__(self, init_path=None, topics: List[Topic] = None):
|
||||||
self.logger = FinCoLog()
|
self.logger = FinCoLog()
|
||||||
init_path = init_path if init_path else Path.cwd()
|
init_path = init_path if init_path else Path.cwd()
|
||||||
|
|
||||||
@@ -111,7 +113,7 @@ class KnowledgeBase:
|
|||||||
|
|
||||||
self.topics = topics if topics else []
|
self.topics = topics if topics else []
|
||||||
|
|
||||||
def load(self, path) -> list:
|
def load(self, path) -> List:
|
||||||
if isinstance(path, str):
|
if isinstance(path, str):
|
||||||
path = Path(path)
|
path = Path(path)
|
||||||
|
|
||||||
@@ -131,7 +133,7 @@ class KnowledgeBase:
|
|||||||
self.docs = self.brief(self.knowledge)
|
self.docs = self.brief(self.knowledge)
|
||||||
self.logger.plain_info(f"Update knowledge finished.")
|
self.logger.plain_info(f"Update knowledge finished.")
|
||||||
|
|
||||||
def brief(self, knowledge: list[Knowledge]) -> list:
|
def brief(self, knowledge: List[Knowledge]) -> List:
|
||||||
docs = []
|
docs = []
|
||||||
for k in knowledge:
|
for k in knowledge:
|
||||||
docs.extend(k.brief())
|
docs.extend(k.brief())
|
||||||
|
|||||||
@@ -605,24 +605,36 @@ SummarizeTask_system : |-
|
|||||||
You can add subheadings and paragraphs in Markdown for readability.
|
You can add subheadings and paragraphs in Markdown for readability.
|
||||||
You can bold or use other formatting options to highlight keywords in the main text.
|
You can bold or use other formatting options to highlight keywords in the main text.
|
||||||
You should display images I offered in markdown using the appropriate image format.
|
You should display images I offered in markdown using the appropriate image format.
|
||||||
|
Don't list data user doesn't provide.
|
||||||
|
|
||||||
SummarizeTask_user : |-
|
SummarizeTask_user : |-
|
||||||
Here is my information: '{{information}}'
|
Here is my information: '{{information}}'
|
||||||
My intention is: {{user_prompt}}. Please provide me with a summary and recommendation based on my intention and the information I have provided. There are some figures which absolute path are: {{figure_path}}, You must display these images in markdown using the appropriate image format.
|
My intention is: {{user_prompt}}. Please provide me with a summary and recommendation based on my intention and the information I have provided. There are some figures which absolute path are: {{figure_path}}, You must display these images in markdown using the appropriate image format.
|
||||||
|
|
||||||
SummarizeTask_context_system : |-
|
SummarizeTask_context_system : |-
|
||||||
Your purpose is to find the important information offered by user and summarize it.
|
Your purpose is to find out the important information offered by user. You can just show the data provided by user in markdown format.
|
||||||
|
|
||||||
SummarizeTask_context_user : |-
|
SummarizeTask_context_user : |-
|
||||||
Here is my information: '{{key}}:{{value}}'
|
Here is my information: '{{key}}:{{value}}'
|
||||||
|
|
||||||
|
SummarizeTask_metrics_system : |-
|
||||||
|
Your purpose is to summarize the information by metrics in markdown format.
|
||||||
|
|
||||||
|
SummarizeTask_metrics_user : |-
|
||||||
|
Here is my information: '{{information}}'
|
||||||
Please summarize it.
|
Please summarize it.
|
||||||
|
|
||||||
LearnManager_system : |-
|
LearnManager_system : |-
|
||||||
Your task is adjusting system prompt in each task to fulfill user's intention
|
Your task is adjusting system prompt in each task to fulfill user's intention. If you have no idea how to optimize the system prompt, you can just return the original system prompt.
|
||||||
|
|
||||||
LearnManager_user : |-
|
LearnManager_user : |-
|
||||||
Here is the final summary:\n{{summary}}\n. Brief of this workflow is:{{brief}}\n
|
Here is the final summary:\n{{summary}}\n.
|
||||||
Tasks I have run are: {{task_finished}}, \n{{task}}'s system prompt is: {{system}}. \nUser's intention is: {{user_prompt}}. you will adjust it to:
|
Brief of this workflow is:{{brief}}\n
|
||||||
|
Tasks I have run are: {{task_finished}},\n
|
||||||
|
{{task}}'s system prompt is: {{system}}.\n
|
||||||
|
User's intention is: {{user_prompt}}.
|
||||||
|
If you have no idea how to optimize the system prompt, you can just return the original system prompt.
|
||||||
|
you will adjust {{task}}'s system prompt to:
|
||||||
|
|
||||||
Topic_IC : |-
|
Topic_IC : |-
|
||||||
Summarize the influence of parameters on IC: {{docs}}
|
Summarize the influence of parameters on IC: {{docs}}
|
||||||
|
|||||||
@@ -776,6 +776,14 @@ class SummarizeTask(Task):
|
|||||||
def summarize_context_user(self):
|
def summarize_context_user(self):
|
||||||
return self.prompt_template.get(self.__class__.__name__ + "_context_user")
|
return self.prompt_template.get(self.__class__.__name__ + "_context_user")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def summarize_metrics_system(self):
|
||||||
|
return self.prompt_template.get(self.__class__.__name__ + "_metrics_system")
|
||||||
|
|
||||||
|
@property
|
||||||
|
def summarize_metrics_user(self):
|
||||||
|
return self.prompt_template.get(self.__class__.__name__ + "_metrics_user")
|
||||||
|
|
||||||
def execute(self) -> Any:
|
def execute(self) -> Any:
|
||||||
workspace = self._context_manager.get_context("workspace")
|
workspace = self._context_manager.get_context("workspace")
|
||||||
user_prompt = self._context_manager.get_context("user_prompt")
|
user_prompt = self._context_manager.get_context("user_prompt")
|
||||||
@@ -811,8 +819,15 @@ class SummarizeTask(Task):
|
|||||||
recorder = R.get_recorder(experiment_name=workflow_yaml["experiment_name"])
|
recorder = R.get_recorder(experiment_name=workflow_yaml["experiment_name"])
|
||||||
recorder.save_objects(context_summary=context_summary)
|
recorder.save_objects(context_summary=context_summary)
|
||||||
|
|
||||||
|
prompt_workflow_selection = self.summarize_metrics_user.render(
|
||||||
|
information=_get_value_from_info(info=record_info, k="metrics"), user_prompt=user_prompt
|
||||||
|
)
|
||||||
|
metrics_response = be.build_messages_and_create_chat_completion(
|
||||||
|
user_prompt=prompt_workflow_selection, system_prompt=self.summarize_metrics_system.render()
|
||||||
|
)
|
||||||
|
|
||||||
prompt_workflow_selection = self.user.render(
|
prompt_workflow_selection = self.user.render(
|
||||||
information=file_info + record_info, figure_path=figure_path, user_prompt=user_prompt
|
information=file_info + [{"metrics": metrics_response}], figure_path=figure_path, user_prompt=user_prompt
|
||||||
)
|
)
|
||||||
response = be.build_messages_and_create_chat_completion(
|
response = be.build_messages_and_create_chat_completion(
|
||||||
user_prompt=prompt_workflow_selection, system_prompt=self.system.render()
|
user_prompt=prompt_workflow_selection, system_prompt=self.system.render()
|
||||||
@@ -856,23 +871,15 @@ class SummarizeTask(Task):
|
|||||||
|
|
||||||
def get_info_from_context(self):
|
def get_info_from_context(self):
|
||||||
context = []
|
context = []
|
||||||
# TODO: get all keys from context?
|
for key, v in self._context_manager.context.items():
|
||||||
for key in [
|
if v is not None:
|
||||||
"user_prompt",
|
v = str(v)
|
||||||
"chat_history",
|
context.append({key: v[: self.__MAX_LENGTH_OF_FILE]})
|
||||||
"Dataset_plan",
|
|
||||||
"Model_plan",
|
|
||||||
"Record_plan",
|
|
||||||
"Strategy_plan",
|
|
||||||
"Backtest_plan",
|
|
||||||
]:
|
|
||||||
c = self._context_manager.get_context(key=key)
|
|
||||||
if c is not None:
|
|
||||||
c = str(c)
|
|
||||||
context.append({key: c[: self.__MAX_LENGTH_OF_FILE]})
|
|
||||||
return context
|
return context
|
||||||
|
|
||||||
def get_info_from_recorder(self, path, exp_name) -> list:
|
@staticmethod
|
||||||
|
def get_info_from_recorder(path, exp_name) -> list:
|
||||||
|
path = Path(path)
|
||||||
path = path if path.name == "mlruns" else path.joinpath("mlruns")
|
path = path if path.name == "mlruns" else path.joinpath("mlruns")
|
||||||
|
|
||||||
R.set_uri(Path(path).as_uri())
|
R.set_uri(Path(path).as_uri())
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ import sys
|
|||||||
import copy
|
import copy
|
||||||
import shutil
|
import shutil
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
|
from typing import List
|
||||||
|
|
||||||
from qlib.finco.task import WorkflowTask, SummarizeTask, TrainTask
|
from qlib.finco.task import WorkflowTask, SummarizeTask, TrainTask
|
||||||
from qlib.finco.prompt_template import PromptTemplate, Template
|
from qlib.finco.prompt_template import PromptTemplate, Template
|
||||||
@@ -188,8 +189,17 @@ class LearnManager:
|
|||||||
|
|
||||||
def learn(self):
|
def learn(self):
|
||||||
workspace = self.wm.context.get_context("workspace")
|
workspace = self.wm.context.get_context("workspace")
|
||||||
|
|
||||||
|
def _drop_duplicate_task(_task: List):
|
||||||
|
unique_task = {}
|
||||||
|
for obj in _task:
|
||||||
|
task_name = obj.__class__.__name__
|
||||||
|
if task_name not in unique_task:
|
||||||
|
unique_task[task_name] = obj
|
||||||
|
return list(unique_task.values())
|
||||||
|
|
||||||
# one task maybe run several times in workflow
|
# one task maybe run several times in workflow
|
||||||
task_finished = list(set(self.wm.context.get_context("task_finished")))
|
task_finished = _drop_duplicate_task(self.wm.context.get_context("task_finished"))
|
||||||
|
|
||||||
user_prompt = self.wm.context.get_context("user_prompt")
|
user_prompt = self.wm.context.get_context("user_prompt")
|
||||||
summary = self.wm.context.get_context("summary")
|
summary = self.wm.context.get_context("summary")
|
||||||
@@ -197,13 +207,13 @@ class LearnManager:
|
|||||||
for task in task_finished:
|
for task in task_finished:
|
||||||
prompt_workflow_selection = self.wm.prompt_template.get(f"{self.__class__.__name__}_user").render(
|
prompt_workflow_selection = self.wm.prompt_template.get(f"{self.__class__.__name__}_user").render(
|
||||||
summary=summary, brief=self.knowledge_base.query_topics(),
|
summary=summary, brief=self.knowledge_base.query_topics(),
|
||||||
task_finished=[str(task) for task in task_finished],
|
task_finished=[str(t) for t in task_finished],
|
||||||
task=task.__class__, system=task.system, user_prompt=user_prompt
|
task=task.__class__.__name__, system=task.system.render(), user_prompt=user_prompt
|
||||||
)
|
)
|
||||||
|
|
||||||
response = APIBackend().build_messages_and_create_chat_completion(
|
response = APIBackend().build_messages_and_create_chat_completion(
|
||||||
user_prompt=prompt_workflow_selection,
|
user_prompt=prompt_workflow_selection,
|
||||||
system_prompt=self.wm.prompt_template.get(f"{self.__class__.__name__}_user").render()
|
system_prompt=self.wm.prompt_template.get(f"{self.__class__.__name__}_system").render()
|
||||||
)
|
)
|
||||||
|
|
||||||
# todo: response assertion
|
# todo: response assertion
|
||||||
|
|||||||
Reference in New Issue
Block a user