dify icon indicating copy to clipboard operation
dify copied to clipboard

[Question] how to see the mid-process of ReAct Agent

Open xiangpingjiang opened this issue 1 year ago • 6 comments

Self Checks

  • [X] I have searched for existing issues search for existing issues, including closed ones.
  • [X] I confirm that I am using English to submit this report (我已阅读并同意 Language Policy).
  • [X] Pleas do not modify this template :) and fill in all the required fields.

Provide a description of the help you need

I locally host dify in my pc, add llama as my LLM.

When I use ReAct mode, I can't see the mid-process Screenshot 2024-02-22 at 14 58 22

If it is possible to see the whole ReAct process to debug ? Thoughts Actions Observations

xiangpingjiang avatar Feb 22 '24 07:02 xiangpingjiang

🤖

Hey @xiangpingjiang, great to see you back here! Hope you're doing well.

Yes, it is possible to view the entire ReAct process, including Thoughts, Actions, and Observations, for debugging purposes when using the locally hosted dify with llama as the LLM.

In the dify codebase, there is a function called getFormattedChatList that is used to format the chat messages. This function includes the agent_thoughts field in the formatted chat list. The agent_thoughts field contains the assistant's thoughts, which can be used for debugging purposes.

Here is the relevant code snippet:

const getFormattedChatList = (messages: ChatMessage[]) => {
  const newChatList: IChatItem[] = []
  messages.forEach((item: ChatMessage) => {
    newChatList.push({
      id: `question-${item.id}`,
      content: item.inputs.query || item.inputs.default_input || item.query, // text generation: item.inputs.query; chat: item.query
      isAnswer: false,
      log: item.message as any,
      message_files: item.message_files?.filter((file: any) => file.belongs_to === 'user') || [],
    })
    newChatList.push({
      id: item.id,
      content: item.answer,
      agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
      feedback: item.feedbacks.find(item => item.from_source === 'user'), // user feedback
      adminFeedback: item.feedbacks.find(item => item.from_source === 'admin'), // admin feedback
      feedbackDisabled: false,
      isAnswer: true,
      message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [],
      more: {
        time: dayjs.unix(item.created_at).format('hh:mm A'),
        tokens: item.answer_tokens + item.message_tokens,
        latency: item.provider_response_latency.toFixed(2),
      },
      annotation: (() => {
        if (item.annotation_hit_history) {
          return {
            id: item.annotation_hit_history.annotation_id,
            authorName: item.annotation_hit_history.annotation_create_account?.name || 'N/A',
            created_at: item.annotation_hit_history.created_at,
          }
        }

        if (item.annotation) {
          return {
            id: '',
            authorName: '',
            logAnnotation: item.annotation,
            created_at: 0,
          }
        }

        return undefined
      })(),
    })
  })
  return newChatList
}

In this function, agent_thoughts is added to the chat list. This field contains the assistant's thoughts, which can be used for debugging purposes. The addFileInfos and sortAgentSorts functions are used to process the agent_thoughts data. You can find this function in the web/app/components/app/log/list.tsx file.

The agent_thoughts field in the dify codebase is a list of nested fields. Each item in the list is a dictionary with the following structure:

{
    'id': fields.String,
    'chain_id': fields.String,
    'message_id': fields.String,
    'position': fields.Integer,
    'thought': fields.String,
    'tool': fields.String,
    'tool_labels': fields.Raw,
    'tool_input': fields.String,
    'created_at': TimestampField,
    'observation': fields.String,
    'files': fields.List(fields.String)
}

Here is a brief description of each field:

  • id: A string that represents the unique identifier of the agent thought.
  • chain_id: A string that represents the chain identifier of the agent thought.
  • message_id: A string that represents the message identifier of the agent thought.
  • position: An integer that represents the position of the agent thought.
  • thought: A string that represents the thought of the agent.
  • tool: A string that represents the tool used by the agent.
  • tool_labels: A raw field that represents the labels of the tool used by the agent.
  • tool_input: A string that represents the input to the tool used by the agent.
  • created_at: A timestamp field that represents when the agent thought was created.
  • observation: A string that represents the observation of the agent.
  • files: A list of strings that represents the files associated with the agent thought.

You can find this structure in the api/fields/message_fields.py file.

I hope this helps! If you have any other questions, feel free to ask.

Sources

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

dosubot[bot] avatar Feb 22 '24 07:02 dosubot[bot]

@dosu-bot

can I see the mid-process of ReAct in logs ?

xiangpingjiang avatar Feb 22 '24 07:02 xiangpingjiang

🤖

To view the entire ReAct process, including Thoughts, Actions, and Observations, in the logs for debugging purposes, you can use the getFormattedChatList function. This function formats the chat messages and includes the agent_thoughts field.

Here is the relevant part of the code:

// Format interface data for easy display
const getFormattedChatList = (messages: ChatMessage[]) => {
  const newChatList: IChatItem[] = []
  messages.forEach((item: ChatMessage) => {
    newChatList.push({
      id: `question-${item.id}`,
      content: item.inputs.query || item.inputs.default_input || item.query, // text generation: item.inputs.query; chat: item.query
      isAnswer: false,
      log: item.message as any,
      message_files: item.message_files?.filter((file: any) => file.belongs_to === 'user') || [],
    })
    newChatList.push({
      id: item.id,
      content: item.answer,
      agent_thoughts: addFileInfos(item.agent_thoughts ? sortAgentSorts(item.agent_thoughts) : item.agent_thoughts, item.message_files),
      feedback: item.feedbacks.find(item => item.from_source === 'user'), // user feedback
      adminFeedback: item.feedbacks.find(item => item.from_source === 'admin'), // admin feedback
      feedbackDisabled: false,
      isAnswer: true,
      message_files: item.message_files?.filter((file: any) => file.belongs_to === 'assistant') || [],
      more: {
        time: dayjs.unix(item.created_at).format('hh:mm A'),
        tokens: item.answer_tokens + item.message_tokens,
        latency: item.provider_response_latency.toFixed(2),
      },
      annotation: (() => {
        if (item.annotation_hit_history) {
          return {
            id: item.annotation_hit_history.annotation_id,
            authorName: item.annotation_hit_history.annotation_create_account?.name || 'N/A',
            created_at: item.annotation_hit_history.created_at,
          }
        }

        if (item.annotation) {
          return {
            id: '',
            authorName: '',
            logAnnotation: item.annotation,
            created_at: 0,
          }
        }

        return undefined
      })(),
    })
  })
  return newChatList
}

In this function, for each message, a new chat item is created with the agent_thoughts field included. The agent_thoughts field is processed by the addFileInfos and sortAgentSorts functions before being added to the chat item. This field contains the thoughts of the agent, which can be useful for debugging purposes.

Please note that this code is specific to the dify codebase and may not work in other contexts. Also, the llama LLM is not specifically mentioned in the provided context, so it's unclear how it interacts with the getFormattedChatList function or the agent_thoughts field.

As for the structure and content of the agent_thoughts field in the dify codebase, it is a list of nested fields. Each item in the list is a dictionary with the following structure:

  • 'id': A string field representing the unique identifier of the agent thought.
  • 'chain_id': A string field representing the chain identifier of the agent thought.
  • 'message_id': A string field representing the message identifier associated with the agent thought.
  • 'position': An integer field representing the position of the agent thought.
  • 'thought': A string field representing the actual thought or content.
  • 'tool': A string field representing the tool used for the agent thought.
  • 'tool_labels': A raw field representing the labels of the tool used.
  • 'tool_input': A string field representing the input given to the tool.
  • 'created_at': A timestamp field representing when the agent thought was created.
  • 'observation': A string field representing the observation made from the agent thought.
  • 'files': A list of string fields representing any files associated with the agent thought.

Here is the code snippet that defines it:

agent_thought_fields = {
    'id': fields.String,
    'chain_id': fields.String,
    'message_id': fields.String,
    'position': fields.Integer,
    'thought': fields.String,
    'tool': fields.String,
    'tool_labels': fields.Raw,
    'tool_input': fields.String,
    'created_at': TimestampField,
    'observation': fields.String,
    'files': fields.List(fields.String)
}

I hope this helps! If you have any other questions or need further clarification, feel free to ask.

Sources

About Dosu

This response is meant to be useful and save you time. It is not meant to be a precise solution, but rather a starting point for your own research.

Help me be more useful! Please leave a 👍 if this is helpful and 👎 if it is irrelevant.

If you want to continue the conversation, start your reply with @dosu-bot.

dosubot[bot] avatar Feb 22 '24 07:02 dosubot[bot]

For debugging agent step by step, it's in our development plan. We will release this feature soon.

crazywoola avatar Feb 22 '24 07:02 crazywoola

For debugging agent step by step, it's in our development plan. We will release this feature soon.

@crazywoola

Oh, that's cool, is there an issue to track the feature ?

xiangpingjiang avatar Feb 22 '24 07:02 xiangpingjiang

Hi, @xiangpingjiang

I'm helping the team manage our backlog and am marking this issue as stale. From what I understand, you were unable to see the mid-process of ReAct Agent when using dify locally and asked if it's possible to view the entire ReAct process for debugging purposes. I provided a detailed response explaining how to view the entire ReAct process using the getFormattedChatList function, and crazywoola confirmed that debugging the agent step by step is in their development plan and will be released soon.

Could you please confirm if this issue is still relevant to the latest version of the repository? If it is, please let the team know by commenting on the issue. Otherwise, feel free to close the issue yourself, or it will be automatically closed in 7 days. Thank you!

dosubot[bot] avatar Mar 29 '24 16:03 dosubot[bot]