Evaluates the node and saves the result to the file. Args: case (Case): The case to be evaluated. solution (Solution): The solution configuration. llm (OpenAILLM): The large language model instance. logger (logging.Logger): Logger for
(case: Case, solution: Solution, llm: OpenAILLM, logger)
| 153 | |
| 154 | @staticmethod |
| 155 | def node_eval(case: Case, solution: Solution, llm: OpenAILLM, logger): |
| 156 | """ |
| 157 | Evaluates the node and saves the result to the file. |
| 158 | |
| 159 | Args: |
| 160 | case (Case): The case to be evaluated. |
| 161 | solution (Solution): The solution configuration. |
| 162 | llm (OpenAILLM): The large language model instance. |
| 163 | logger (logging.Logger): Logger for logging information and errors. |
| 164 | """ |
| 165 | if logger: |
| 166 | logger.debug("Start Node evaluation, case id is " + case.case_id) |
| 167 | assert case.trajectory is not None and len(case.trajectory.states) > 0, \ |
| 168 | "case.trajectory is None or len is 0, please forward the case first" |
| 169 | input_dict = {} |
| 170 | |
| 171 | cur_node_name = None |
| 172 | start_idx = 0 |
| 173 | previous_node_summary = "You are the first node." |
| 174 | for idx, state in enumerate(case.trajectory.states): |
| 175 | # If the node_name changes, it's a new node |
| 176 | if state.node.node_name != cur_node_name: |
| 177 | start_idx = idx |
| 178 | cur_node_name = state.node.node_name |
| 179 | |
| 180 | # If it's the last state of the current node, then it needs to be evaluated |
| 181 | if (idx == len(case.trajectory.states) - 1 |
| 182 | or case.trajectory.states[idx + 1].node.node_name != cur_node_name): |
| 183 | # Obtain the output of all roles of the current node |
| 184 | role_chat = "" |
| 185 | for i in range(start_idx, idx + 1): |
| 186 | role_chat += (case.trajectory.states[i].action.agent_role + " : " |
| 187 | + case.trajectory.states[i].action.content + "\n") |
| 188 | input_dict["role_chat"] = role_chat |
| 189 | input_dict["node_config"] = { |
| 190 | "node_name": solution.sop.nodes[cur_node_name].node_name, |
| 191 | "node_description": solution.sop.nodes[cur_node_name].node_description, |
| 192 | } |
| 193 | input_dict["previous_node_summary"] = previous_node_summary |
| 194 | |
| 195 | eval_prompt = eval_node_prompt.format(**input_dict) |
| 196 | response, content = llm.get_response( |
| 197 | chat_messages=None, |
| 198 | system_prompt="", |
| 199 | last_prompt=eval_prompt, |
| 200 | stream=False, |
| 201 | ) |
| 202 | |
| 203 | # To extract the result, first extract the part of the result package, then convert it to json, |
| 204 | # and input it into the state, specifically a summary and an evaluation |
| 205 | eval_result = OptimUtils.extract_data_from_response(content, ["result"]) |
| 206 | try: |
| 207 | eval_result = json.loads(eval_result["result"]) |
| 208 | except: |
| 209 | logger.error( |
| 210 | "Error in node evaluation, case id is " + case.case_id |
| 211 | + ", the result is not a legal json string, the result is: " + content |
| 212 | ) |
no test coverage detected