dify icon indicating copy to clipboard operation
dify copied to clipboard

How to obtain user information and set it in the chat context

Open hjxtclm opened this issue 1 year ago • 3 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

To create an intelligent customer service agent that uses customer information as context during a conversation, the process is as follows: When a user chats with the intelligent customer service agent, certain user information is set as context. The intelligent customer service responds based on this user information. According to the documentation, external API extensions can be used to obtain data. However, the service API that retrieves user information requires login verification. It is unclear how external API verification is handled when Dify services call external APIs.

hjxtclm avatar Mar 29 '24 06:03 hjxtclm

Hey there, @hjxtclm! Great to see you back here - hope you've been doing awesomely. Let's dive into your query and see how we can tackle it together. 🚀

Based on the information you provided and the context I found in the Dify repository, here's how you can handle external API verification when Dify services call external APIs that require login verification.

Firstly, to integrate third-party APIs, including your own server API and others, you can refer to the pattern used in the DatasetRetrievalFeature class. This class uses the retrieve method through AgentExecutor to run queries and return results. You need to create a new class that inherits from BaseTool and implement the methods required to interact with your API. Then, this new class will replace or be added to DatasetRetrieverTool or DatasetMultiRetrieverTool in the AgentConfiguration. Here is a simplified example of how to create a new tool to interact with your API:

from core.tools.tool import BaseTool

class MyAPITool(BaseTool):
    def __init__(self, api_url, api_key):
        self.api_url = api_url
        self.api_key = api_key

    def run(self, query):
        # Implement the logic to interact with your API here.
        # This may involve sending requests to the API and handling responses.
        pass

Then, you can use this tool in AgentConfiguration like this:

my_api_tool = MyAPITool(api_url='https://my-api.com', api_key='my-api-key')

agent_configuration = AgentConfiguration(
    strategy=planning_strategy,
    model_config=model_config,
    tools=[my_api_tool],
    memory=memory,
    max_iterations=10,
    max_execution_time=400.0,
    early_stopping_method="generate"
)

agent_executor = AgentExecutor(agent_configuration)
result = agent_executor.run(query)

This is a starting point for your own implementation, and the actual implementation will depend on the specifics of your API and how you wish to interact with it. You can find more details in the How to fetch data from a third-party API issue and the api/core/features/dataset_retrieval.py file.

Secondly, to handle external API verification when calling services that require login verification to retrieve user information, Dify can implement a secure backend system that manages API keys and user authentication. The backend can authenticate a user, manage session tokens, and use stored API keys to securely interact with external services on behalf of the user. This method ensures that sensitive information, such as API keys and user credentials, is not exposed in the frontend application, thus maintaining security and integrity. Here's a conceptual example of how this could be implemented in a backend service using Node.js and Express:

const express = require('express');
const fetch = require('node-fetch');
const app = express();
const PORT = 3000;

// Middleware to parse JSON bodies
app.use(express.json());

// Endpoint to handle user login and API interaction
app.post('/login-and-fetch-data', async (req, res) => {
    const { username, password } = req.body;

    // Example of user authentication (details depend on your auth system)
    const isAuthenticated = authenticateUser(username, password);
    if (!isAuthenticated) {
        return res.status(401).send('Authentication failed');
    }

    // Assuming authentication is successful, use the stored API key to call an external service
    const apiKey = 'YOUR_STORED_API_KEY_FOR_EXTERNAL_SERVICE';
    const externalApiResponse = await fetch('https://external.api/service', {
        method: 'GET', // or 'POST'
        headers: {
            'Authorization': `Bearer ${apiKey}`,
            'Content-Type': 'application/json',
        },
        // Include body if needed for the external API request
    });

    const data = await externalApiResponse.json();

    // Respond with the data retrieved from the external API
    res.json(data);
});

function authenticateUser(username, password) {
    // Placeholder for actual authentication logic
    // This could involve checking a database for user credentials, etc.
    return true; // Simplified for example purposes
}

app.listen(PORT, () => console.log(`Server running on port ${PORT}`));

This example demonstrates a secure way to handle user authentication and external API calls without exposing sensitive information in the frontend. The actual implementation details, such as the authentication mechanism and external API specifics, would need to be adapted to fit the particular requirements of the Dify service and the external APIs it interacts with. You can find more details in the en/user-guide/launching-dify-apps/developing-with-apis/README.md file.

Unfortunately, I wasn't able to find specific information on how Dify handles user authentication and session management in its current implementation, or the current method for setting user information as context in a conversation within Dify. I also couldn't find a specific class or method in Dify that handles external API calls. However, Dify handles the secure storage and retrieval of API keys for external services by recommending that API keys should be called through the backend instead of being directly exposed in the frontend code or requests. This approach is intended to prevent the application from being misused or attacked. Additionally, Dify allows the creation of multiple access credentials for an application, enabling the delivery of AI capabilities to different users or developers while keeping the underlying Prompt engineering, datasets, and tool capabilities encapsulated. You can find more details in the zh_CN/guides/application-publishing/developing-with-apis.md file.

I hope this information helps! If you have any other questions or need further clarification, please let me know.

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 Mar 29 '24 06:03 dosubot[bot]

@dosu-bot How the username and password mentioned above are passed to the /login-and-fetch-data interface

hjxtclm avatar Mar 29 '24 06:03 hjxtclm

In a typical Node.js and Express backend service, the username and password are passed in the request body of a POST request. Here's how the data might look:

{
    "username": "exampleUser",
    "password": "examplePassword"
}

This data is accessed in the Express route handler as follows:

app.post('/login-and-fetch-data', function(req, res) {
    var username = req.body.username;
    var password = req.body.password;
    // ... handle authentication here ...
});

This example demonstrates a general approach to handling username and password data in a POST request. It's crucial to ensure that any sensitive data, like passwords, are securely handled and not stored in plain text.

If you're looking for more specific details on how the username and password are handled in the '/login-and-fetch-data' interface within the Dify codebase, providing more context or pointing to the specific part of the codebase in question would be helpful for a more accurate response.

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 Mar 29 '24 06:03 dosubot[bot]