Why We Don't Blindly Use Dify / LangChain
The Bottom Line
Dify and LangChain are both excellent tools. But they're general-purpose tools, and we work on non-standard scenarios.
General-purpose tools are designed to cover 80% of use cases. But if you want to achieve 90% or even 95%, you need to build it yourself.
This isn't to say Dify/LangChain are bad — it's that their abstraction level doesn't match our scenarios.
What Are Non-Standard Scenarios
Standard scenarios are those with clear workflows, clear inputs, and clear outputs. For example:
- Customer service chatbot: User asks a question, system provides an answer
- Document Q&A: User asks a document-related question, system finds the answer in the document
- Content generation: User provides a prompt, system generates text
These scenarios are well-handled by Dify and LangChain because their abstraction level matches the complexity of these scenarios.
Non-standard scenarios are those with blurry boundaries, uncertain workflows, and frequently changing requirements. For example:
- Smart authorization: User says one sentence, system must determine if they want to change permissions, extract role/permission/object, do secondary confirmation, call API, return results. This workflow has many branches and edge cases.
- Smart integration: User asks a question, system must find information from multiple documents, determine which information is relevant, integrate it, handle conflicts and contradictions. This workflow has many judgments and decisions.
- Smart content generation: User wants to generate a pitch, system must understand product features, customer profiles, sales scenarios, generate appropriate pitches, handle different styles and tones. This workflow has many creative elements and variations.
These scenarios encounter many problems when processed using Dify/LangChain's standard workflows.
Problem 1: Abstraction Level Mismatch
Dify and LangChain's abstraction level is "Chain" — stringing a series of steps together to form a workflow.
This abstraction works for simple scenarios. For example:
User input → Retrieve documents → Generate answer → Output
But for complex scenarios, this abstraction falls short. Take the smart authorization workflow:
User input → Intent recognition → [Is permission operation] → Parameter extraction → Secondary confirmation → [Confirm] → Call API → [Success] → Return result → Secondary confirmation → [Confirm] → Complete
↓ ↓ ↓ ↓
[Not] → Normal conversation [Reject] → Cancel [Fail] → Error handling [Reject] → Rollback
This workflow has many branches and loops, making it very complex to express with a Chain. Moreover, each branch has different logic — some need API calls, some need user interaction, some need error handling.
Implementing this workflow with Dify/LangChain's Chain would result in very complex, hard-to-maintain code.
Problem 2: Assumptions Become Constraints
Dify and LangChain have many assumptions:
- They assume how models are called (usually OpenAI API)
- They assume Prompt templates
- They assume tool interfaces
- They assume workflow structures
These assumptions are reasonable for most scenarios. But in non-standard scenarios, these assumptions become constraints.
For example:
Our client uses DeepSeek V3, not OpenAI. DeepSeek V3's tool-calling capabilities differ from OpenAI's, and we need to optimize specifically for DeepSeek V3's characteristics.
With LangChain, we'd either need to write an adapter layer to convert DeepSeek V3's interface to OpenAI's interface, or modify LangChain's source code to support DeepSeek V3.
Both approaches are problematic. Writing an adapter layer increases complexity and latency; modifying source code makes future upgrades difficult.
We chose to call DeepSeek V3's API directly and optimize for its characteristics. This is more direct, efficient, and可控.
Problem 3: Insufficient Flexibility
Non-standard scenario requirements change frequently. Today the client wants to add a feature, tomorrow they want to change logic, the day after they want to switch models.
With Dify/LangChain, every requirement change means modifying the Chain definition, Prompt templates, and tool interfaces. This process is tedious and error-prone.
We chose a more flexible implementation approach:
- Modular design: Make each function an independent module, with modules communicating through interfaces. When requirements change, only the corresponding module needs modification, without affecting others.
- Configuration management: Make variable parts (like Prompts, model parameters, tool interfaces) configurable. Change configuration to change behavior without changing code.
- Progressive development: Start with a minimum viable version, then iterate based on feedback. Each iteration only changes a small portion, keeping risk可控.
This approach is more flexible and better suited for non-standard scenarios.
Problem 4: Debugging Difficulty
Dify and LangChain's high abstraction level means when you encounter problems, it's hard to pinpoint where the issue lies.
For example, the user says "the system's answer is wrong." This problem could be in:
- Retrieval stage: Retrieved documents are irrelevant
- Generation stage: LLM's understanding is incorrect
- Tool stage: Tool's return value has issues
- Workflow stage: Workflow logic has bugs
With Dify/LangChain, you'd need to check layer by layer to find the root cause. Moreover, many intermediate processes are invisible — you can only see the final output.
We chose a more transparent implementation approach:
- Logging: Each step logs detailed information, including input, output, duration, errors, etc.
- Visual tracing: Visualize the workflow execution process for easy problem定位.
- Unit testing: Each module has independent unit tests to ensure the module itself is correct.
This approach is easier to debug and better suited for complex scenarios.
When to Use Dify/LangChain
Given all this, does that mean Dify/LangChain are useless?
Of course not.
Dify/LangChain are suitable for these scenarios:
- Standard scenarios: Customer service, Q&A, content generation — scenarios with clear workflows
- Rapid prototyping: When you need to quickly validate an idea without high completion requirements
- Limited team capability: When you don't have enough technical capability to implement it yourself and need framework assistance
- Limited budget: When you don't have enough budget for custom development and need to use open-source solutions
If your scenario fits the above conditions, using Dify/LangChain is an excellent choice.
But if your scenario is non-standard, complex, and requires high customization, you'll need to build it yourself.
Our Approach
Our approach is: Use Dify/LangChain's ideas, but not their code.
Specifically:
- Borrow ideas: Learn from Dify/LangChain's design philosophy, like Chain abstraction, tool encapsulation, Prompt management, etc.
- Use components: Use certain Dify/LangChain components, like vector databases, Embedding models, parsers, etc.
- Implement ourselves: Implement core logic ourselves, without depending on frameworks.
Benefits of this approach:
- Framework flexibility without framework constraints
- Component reusability without component limitations
- Philosophical guidance without philosophical dogma
An Example
When we built our smart customer service, we initially used RAGFlow. RAGFlow is an excellent RAG framework — ready to use out of the box with good results.
But after using it for a while, we encountered some issues:
- Insufficient retrieval precision: RAGFlow's retrieval strategy is fixed and can't be customized for our scenarios.
- Insufficient generation flexibility: RAGFlow's generation strategy is also fixed and can't be adjusted for our needs.
- Insufficient scalability: RAGFlow's architecture is closed and doesn't easily accommodate new features.
So we decided to implement our own RAG system.
We borrowed RAGFlow's ideas but redesigned the architecture:
- Retrieval layer: Supports multiple retrieval strategies, including semantic search, keyword search, hybrid search, etc. Choose the most appropriate strategy based on the scenario.
- Generation layer: Supports multiple generation strategies, including direct generation, citation generation, multi-turn dialogue, etc. Choose the most appropriate strategy based on requirements.
- Extension layer: Supports adding new functional modules, like knowledge graphs, multimodal processing, etc. Gradually expand based on development.
Results: Accuracy improved from 75% to 92%, response time reduced from 3 seconds to 1.5 seconds.
Final Thoughts
Tools are means, not ends.
We do AI implementation not to use a specific framework, but to solve a specific problem. Frameworks are just tools; problems are the goal.
When tools solve problems, we use tools. When tools can't solve problems, we build our own tools.
This isn't technical purism — it's pragmatism.
If you have a non-standard scenario you'd like help with, feel free to reach out. We may not use Dify/LangChain, but we'll definitely use the most appropriate approach to solve your problem.