langgenius / dify

Dify is an open-source LLM app development platform. Dify's intuitive interface combines AI workflow, RAG pipeline, agent capabilities, model management, observability features and more, letting you quickly go from prototype to production.
https://dify.ai
Other
50.8k stars 7.3k forks source link

Integration of Redis Tool for Efficient Token Caching #8153

Closed G81192 closed 1 week ago

G81192 commented 1 month ago

Self Checks

1. Is this request related to a challenge you're experiencing? Tell me about your story.

Yes, I frequently need to request tokens for third-party API calls. This process can be time-consuming and inefficient. I would like to see a Redis tool integrated into Dify. This tool would allow users to cache tokens, reducing the need for repeated token requests. By caching tokens, I can save time and resources, making my workflow more efficient. This feature would eliminate the need to request a new token for each API call, thereby speeding up the development process.

2. Additional context or comments

I have developed a function in my local code that implements this feature. I am willing to share this function with the Dify community.

3. Can you help us with this feature?

dosubot[bot] commented 1 month ago

Hey @G81192, I'm here to help you with any bugs, questions, or contributions you have for Dify. Let's work together to improve the platform!

I found a similar open issue that might be relevant to your request: feat: cloudflare kv. This issue is closed and was last updated on August 30, 2024. It was referenced by a pull request feat: cloudflare kv, which was also last updated on August 30, 2024 [1].

Regarding your request, you can indeed integrate a Redis tool into Dify for efficient token caching. The docker-compose.yaml file in the Dify repository already includes a Redis service configuration that can be used for this purpose. Here is the relevant part of the docker-compose.yaml file:

# The redis cache.
redis:
  image: redis:6-alpine
  restart: always
  volumes:
    # Mount the redis data directory to the container.
    - ./volumes/redis/data:/data
  # Set the redis password when startup redis server.
  command: redis-server --requirepass difyai123456
  healthcheck:
    test: [ "CMD", "redis-cli", "ping" ]
  # uncomment to expose redis port to host
  # ports:
  #   - "6379:6379"

Additionally, the api and worker services are already configured to connect to the Redis instance:

# API service
api:
  ...
  environment:
    ...
    # The configurations of redis connection.
    REDIS_HOST: redis
    REDIS_PORT: 6379
    REDIS_USERNAME: ''
    REDIS_PASSWORD: difyai123456
    REDIS_USE_SSL: 'false'
    # use redis db 0 for redis cache
    REDIS_DB: 0
    ...
# worker service
worker:
  ...
  environment:
    ...
    # The configurations of redis cache connection.
    REDIS_HOST: redis
    REDIS_PORT: 6379
    REDIS_USERNAME: ''
    REDIS_PASSWORD: difyai123456
    REDIS_DB: 0
    REDIS_USE_SSL: 'false'
    ...

To implement token caching, you can use the Redis instance to store and retrieve tokens. Here is a simple example in Python using the redis library:

import redis
import time

# Connect to Redis
r = redis.Redis(host='redis', port=6379, password='difyai123456', db=0)

def get_token():
    # Check if token is already cached
    token = r.get('api_token')
    if token:
        return token.decode('utf-8')

    # If not cached, request a new token from the third-party API
    token = request_new_token_from_api()

    # Cache the token with an expiration time (e.g., 3600 seconds)
    r.set('api_token', token, ex=3600)

    return token

def request_new_token_from_api():
    # Implement the logic to request a new token from the third-party API
    return "new_token"

# Example usage
token = get_token()
print(f"Token: {token}")

This code checks if the token is already cached in Redis. If it is, it retrieves the token from the cache. If not, it requests a new token from the third-party API, caches it in Redis with an expiration time, and then returns the token [2].

Additionally, the TokenManager class in the api/libs/helper.py file is responsible for token management and can be extended to include caching mechanisms [3].

Feel free to share your implementation with the Dify community, as it could be a valuable contribution!

To continue talking to Dosu, mention @dosu.

laipz8200 commented 1 month ago

Have you considered using conversation variables to store the token and its expiration time? I’d love to know if there are any challenges in implementing this in your specific scenario.

G81192 commented 1 month ago

@laipz8200 I have a requirement that involves the following scenarios:

  1. Some nodes in the process require calling internal system APIs, but the internal system uses an authentication token. This token needs to be retrieved from an endpoint and has an expiration time. As a result, I need to obtain the token each time the process runs, which leads to performance degradation.
  2. Certain third-party information, such as tenant resource details, changes infrequently. Since querying these details is slow, caching is desired for handling this information.

Additionally, can the conversation variables you mentioned address this issue? I haven't found a better solution during my debugging so far.

laipz8200 commented 1 month ago

By using the conversation variable, you only need to gather the necessary information once at the beginning of each conversation. This information will be stored within the conversation until it is deleted.

G81192 commented 1 month ago

By using the conversation variable, you only need to gather the necessary information once at the beginning of each conversation. This information will be stored within the conversation until it is deleted.

Conversation variables seem to be derived from user-provided information, but the information that needs to be cached is not provided by the user.