mirror of
https://github.com/langgenius/dify-docs.git
synced 2026-03-27 13:28:32 +07:00
auto translate core
This commit is contained in:
121
.github/workflows/sync_docs.yml
vendored
Normal file
121
.github/workflows/sync_docs.yml
vendored
Normal file
@@ -0,0 +1,121 @@
|
||||
name: Sync Documentation Structure
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- main
|
||||
- revamp
|
||||
paths:
|
||||
- 'docs.json'
|
||||
- 'en/**/*.md'
|
||||
- 'en/**/*.mdx'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
since_commit:
|
||||
description: 'Git commit to compare against (default: HEAD~1)'
|
||||
required: false
|
||||
default: 'HEAD~1'
|
||||
|
||||
jobs:
|
||||
sync-docs:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v4
|
||||
with:
|
||||
fetch-depth: 0 # Fetch all history for git diff
|
||||
token: ${{ secrets.GITHUB_TOKEN }}
|
||||
|
||||
- name: Set up Python
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.9'
|
||||
|
||||
- name: Install dependencies
|
||||
run: |
|
||||
cd tools/translate
|
||||
pip install httpx aiofiles python-dotenv
|
||||
|
||||
- name: Check for documentation changes
|
||||
id: check-changes
|
||||
run: |
|
||||
# Determine the commit to compare against
|
||||
if [[ "${{ github.event_name }}" == "workflow_dispatch" ]]; then
|
||||
SINCE_COMMIT="${{ github.event.inputs.since_commit }}"
|
||||
else
|
||||
SINCE_COMMIT="HEAD~1"
|
||||
fi
|
||||
|
||||
echo "Checking for changes since: $SINCE_COMMIT"
|
||||
|
||||
# Check if there are any English doc changes
|
||||
if git diff --name-only $SINCE_COMMIT HEAD | grep -E '^(docs\.json|en/.*\.(md|mdx))$'; then
|
||||
echo "has_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "since_commit=$SINCE_COMMIT" >> $GITHUB_OUTPUT
|
||||
else
|
||||
echo "has_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No documentation changes detected"
|
||||
fi
|
||||
|
||||
- name: Run documentation synchronization
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
env:
|
||||
DIFY_API_KEY: ${{ secrets.DIFY_API_KEY }}
|
||||
run: |
|
||||
cd tools/translate
|
||||
echo "Starting documentation synchronization..."
|
||||
echo "Since commit: ${{ steps.check-changes.outputs.since_commit }}"
|
||||
|
||||
python sync_and_translate.py "$DIFY_API_KEY" "${{ steps.check-changes.outputs.since_commit }}"
|
||||
|
||||
- name: Check for sync results
|
||||
if: steps.check-changes.outputs.has_changes == 'true'
|
||||
id: check-sync-results
|
||||
run: |
|
||||
# Check if there are any changes to commit
|
||||
if [[ -n $(git status --porcelain) ]]; then
|
||||
echo "has_sync_changes=true" >> $GITHUB_OUTPUT
|
||||
echo "Sync created changes to commit"
|
||||
else
|
||||
echo "has_sync_changes=false" >> $GITHUB_OUTPUT
|
||||
echo "No changes from sync"
|
||||
fi
|
||||
|
||||
- name: Commit and push synchronized changes
|
||||
if: steps.check-sync-results.outputs.has_sync_changes == 'true'
|
||||
run: |
|
||||
git config --global user.name 'github-actions[bot]'
|
||||
git config --global user.email 'github-actions[bot]@users.noreply.github.com'
|
||||
|
||||
# Add all changes
|
||||
git add .
|
||||
|
||||
# Create commit message
|
||||
COMMIT_MSG="docs: auto-sync documentation structure and translations
|
||||
|
||||
🤖 Generated with [Claude Code](https://claude.ai/code)
|
||||
|
||||
Co-Authored-By: Claude <noreply@anthropic.com>"
|
||||
|
||||
git commit -m "$COMMIT_MSG"
|
||||
|
||||
# Push to the current branch
|
||||
echo "Pushing to branch: ${{ github.ref_name }}"
|
||||
git push origin HEAD:${{ github.ref_name }}
|
||||
|
||||
echo "✓ Documentation synchronization completed and pushed"
|
||||
|
||||
- name: Summary
|
||||
if: always()
|
||||
run: |
|
||||
if [[ "${{ steps.check-changes.outputs.has_changes }}" == "true" ]]; then
|
||||
if [[ "${{ steps.check-sync-results.outputs.has_sync_changes }}" == "true" ]]; then
|
||||
echo "✅ Documentation synchronization completed successfully"
|
||||
else
|
||||
echo "ℹ️ Documentation synchronization ran but no changes were needed"
|
||||
fi
|
||||
else
|
||||
echo "ℹ️ No documentation changes detected, synchronization skipped"
|
||||
fi
|
||||
112
en/documentation/pages/getting-started/faq.md
Normal file
112
en/documentation/pages/getting-started/faq.md
Normal file
@@ -0,0 +1,112 @@
|
||||
# Frequently Asked Questions
|
||||
|
||||
Welcome to the Dify FAQ section. Here you'll find answers to the most commonly asked questions about using Dify.
|
||||
|
||||
## Getting Started
|
||||
|
||||
### What is Dify?
|
||||
|
||||
Dify is an open-source platform for building AI applications. It provides a comprehensive set of tools and features to help you build, deploy, and manage your AI applications without extensive coding knowledge.
|
||||
|
||||
### How do I get started with Dify?
|
||||
|
||||
To get started with Dify:
|
||||
|
||||
1. **Sign up** for a Dify account at [dify.ai](https://dify.ai)
|
||||
2. **Create your first application** using our intuitive interface
|
||||
3. **Configure your AI model** by connecting to providers like OpenAI, Anthropic, or others
|
||||
4. **Test and iterate** on your application
|
||||
5. **Deploy** your AI application to production
|
||||
|
||||
### What types of applications can I build with Dify?
|
||||
|
||||
You can build various types of AI applications with Dify:
|
||||
|
||||
- **Chatbots** for customer service
|
||||
- **Knowledge base assistants** that can answer questions about your documents
|
||||
- **Workflow automation tools** that process data intelligently
|
||||
- **Content generation tools** for marketing and writing
|
||||
- **AI agents** that can perform complex tasks
|
||||
|
||||
## Technical Questions
|
||||
|
||||
### What AI models does Dify support?
|
||||
|
||||
Dify supports a wide range of AI models including:
|
||||
|
||||
- **OpenAI models**: GPT-4, GPT-3.5, and others
|
||||
- **Anthropic models**: Claude 3 and Claude 2
|
||||
- **Open source models**: Through providers like Hugging Face, Ollama
|
||||
- **Local models**: You can host your own models
|
||||
|
||||
### How does Dify handle my data?
|
||||
|
||||
Data security and privacy are our top priorities:
|
||||
|
||||
- **Your data remains yours** - we don't train on your private data
|
||||
- **Encryption in transit** and at rest
|
||||
- **SOC2 compliance** for enterprise customers
|
||||
- **GDPR compliance** for European users
|
||||
|
||||
### Can I use Dify for commercial purposes?
|
||||
|
||||
Yes! Dify offers both:
|
||||
|
||||
- **Open source version** with Apache 2.0 license for self-hosting
|
||||
- **Cloud version** with commercial plans for managed hosting
|
||||
- **Enterprise plans** with advanced features and support
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### My AI application is giving incorrect responses
|
||||
|
||||
Try these troubleshooting steps:
|
||||
|
||||
1. **Review your prompt** - Make sure it's clear and specific
|
||||
2. **Check your knowledge base** - Ensure relevant documents are uploaded
|
||||
3. **Adjust model parameters** - Try different temperature or top-k settings
|
||||
4. **Test with different models** - Some models work better for specific tasks
|
||||
|
||||
### I'm experiencing slow response times
|
||||
|
||||
To improve response times:
|
||||
|
||||
1. **Check your model configuration** - Some models are faster than others
|
||||
2. **Optimize your knowledge base** - Remove unnecessary documents
|
||||
3. **Use caching** - Enable response caching for frequently asked questions
|
||||
4. **Consider upgrading** your plan for better performance
|
||||
|
||||
### How do I get support?
|
||||
|
||||
You can get support through:
|
||||
|
||||
- **Community forum** - Connect with other Dify users
|
||||
- **Documentation** - Comprehensive guides and tutorials
|
||||
- **GitHub issues** - For bug reports and feature requests
|
||||
- **Email support** - For paid plan customers
|
||||
- **Enterprise support** - Dedicated support for enterprise customers
|
||||
|
||||
## Billing and Plans
|
||||
|
||||
### What are the different pricing plans?
|
||||
|
||||
Dify offers several plans:
|
||||
|
||||
- **Free tier** - Perfect for getting started and small projects
|
||||
- **Pro plans** - For growing businesses with higher usage needs
|
||||
- **Enterprise plans** - Custom solutions for large organizations
|
||||
|
||||
### How is usage calculated?
|
||||
|
||||
Usage is typically calculated based on:
|
||||
|
||||
- **API calls** to AI models
|
||||
- **Storage** for documents and data
|
||||
- **Active users** on your applications
|
||||
- **Custom features** depending on your plan
|
||||
|
||||
For detailed pricing information, visit our [pricing page](https://dify.ai/pricing).
|
||||
|
||||
---
|
||||
|
||||
Need more help? Contact our support team or check out our [comprehensive documentation](../../../guides/).
|
||||
126
en/documentation/pages/getting-started/faq.mdx
Normal file
126
en/documentation/pages/getting-started/faq.mdx
Normal file
@@ -0,0 +1,126 @@
|
||||
---
|
||||
title: "Frequently Asked Questions"
|
||||
description: "Common questions and answers about using Dify"
|
||||
icon: "circle-question"
|
||||
---
|
||||
|
||||
Welcome to the Dify FAQ section. Here you'll find answers to the most commonly asked questions about using Dify.
|
||||
|
||||
## Getting Started
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What is Dify?">
|
||||
Dify is an open-source platform for building AI applications. It provides a comprehensive set of tools and features to help you build, deploy, and manage your AI applications without extensive coding knowledge.
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I get started with Dify?">
|
||||
To get started with Dify:
|
||||
|
||||
1. **Sign up** for a Dify account at [dify.ai](https://dify.ai)
|
||||
2. **Create your first application** using our intuitive interface
|
||||
3. **Configure your AI model** by connecting to providers like OpenAI, Anthropic, or others
|
||||
4. **Test and iterate** on your application
|
||||
5. **Deploy** your AI application to production
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="What types of applications can I build with Dify?">
|
||||
You can build various types of AI applications with Dify:
|
||||
|
||||
- **Chatbots** for customer service
|
||||
- **Knowledge base assistants** that can answer questions about your documents
|
||||
- **Workflow automation tools** that process data intelligently
|
||||
- **Content generation tools** for marketing and writing
|
||||
- **AI agents** that can perform complex tasks
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Technical Questions
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What AI models does Dify support?">
|
||||
Dify supports a wide range of AI models including:
|
||||
|
||||
- **OpenAI models**: GPT-4, GPT-3.5, and others
|
||||
- **Anthropic models**: Claude 3 and Claude 2
|
||||
- **Open source models**: Through providers like Hugging Face, Ollama
|
||||
- **Local models**: You can host your own models
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How does Dify handle my data?">
|
||||
Data security and privacy are our top priorities:
|
||||
|
||||
- **Your data remains yours** - we don't train on your private data
|
||||
- **Encryption in transit** and at rest
|
||||
- **SOC2 compliance** for enterprise customers
|
||||
- **GDPR compliance** for European users
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Can I use Dify for commercial purposes?">
|
||||
Yes! Dify offers both:
|
||||
|
||||
- **Open source version** with Apache 2.0 license for self-hosting
|
||||
- **Cloud version** with commercial plans for managed hosting
|
||||
- **Enterprise plans** with advanced features and support
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="My AI application is giving incorrect responses">
|
||||
Try these troubleshooting steps:
|
||||
|
||||
1. **Review your prompt** - Make sure it's clear and specific
|
||||
2. **Check your knowledge base** - Ensure relevant documents are uploaded
|
||||
3. **Adjust model parameters** - Try different temperature or top-k settings
|
||||
4. **Test with different models** - Some models work better for specific tasks
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="I'm experiencing slow response times">
|
||||
To improve response times:
|
||||
|
||||
1. **Check your model configuration** - Some models are faster than others
|
||||
2. **Optimize your knowledge base** - Remove unnecessary documents
|
||||
3. **Use caching** - Enable response caching for frequently asked questions
|
||||
4. **Consider upgrading** your plan for better performance
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How do I get support?">
|
||||
You can get support through:
|
||||
|
||||
- **Community forum** - Connect with other Dify users
|
||||
- **Documentation** - Comprehensive guides and tutorials
|
||||
- **GitHub issues** - For bug reports and feature requests
|
||||
- **Email support** - For paid plan customers
|
||||
- **Enterprise support** - Dedicated support for enterprise customers
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## Billing and Plans
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="What are the different pricing plans?">
|
||||
Dify offers several plans:
|
||||
|
||||
- **Free tier** - Perfect for getting started and small projects
|
||||
- **Pro plans** - For growing businesses with higher usage needs
|
||||
- **Enterprise plans** - Custom solutions for large organizations
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="How is usage calculated?">
|
||||
Usage is typically calculated based on:
|
||||
|
||||
- **API calls** to AI models
|
||||
- **Storage** for documents and data
|
||||
- **Active users** on your applications
|
||||
- **Custom features** depending on your plan
|
||||
|
||||
For detailed pricing information, visit our [pricing page](https://dify.ai/pricing).
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
<Note>
|
||||
Need more help? Contact our support team or check out our [comprehensive documentation](../../../guides/).
|
||||
</Note>
|
||||
36
ja-jp/documentation/pages/build/orchestrate-node.mdx
Normal file
36
ja-jp/documentation/pages/build/orchestrate-node.mdx
Normal file
@@ -0,0 +1,36 @@
|
||||
> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版](../../../../en/documentation/pages/build/orchestrate-node.mdx)を参照してください。
|
||||
|
||||
---
|
||||
title: "フローロジック"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
ノードは、接続方法によって実行方法が異なります。
|
||||
|
||||

|
||||
|
||||
## 直列実行
|
||||
|
||||
ノードを次々に接続すると、それらは順番に実行されます。各ノードは、前のノードの実行が完了するのを待ってから開始します。
|
||||
|
||||

|
||||
|
||||
各ノードは、チェーン内でそれより前に実行された任意のノードの変数を使用できます。
|
||||
|
||||
## 並列実行
|
||||
|
||||
複数のノードを同じ開始ノードに接続すると、それらはすべて同時に実行されます。
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
1つのノードから最大10個の並列ブランチを持つことができ、ネストされた並列構造は最大3レベルまでです。
|
||||
</Note>
|
||||
|
||||
## 変数アクセス
|
||||
|
||||
直列フローでは、ノードはチェーン内の先行する任意のノードの変数にアクセスできます。
|
||||
|
||||
並列フローでは、ノードは並列分割の前に実行されたノードの変数にアクセスできますが、他の並列ノードは同時に実行されているため、それらの変数にはアクセスできません。
|
||||
|
||||
並列ブランチの実行が完了した後、下流のノードはすべての並列出力からの変数にアクセスできます。
|
||||
108
ja-jp/documentation/pages/debug/error-type.mdx
Normal file
108
ja-jp/documentation/pages/debug/error-type.mdx
Normal file
@@ -0,0 +1,108 @@
|
||||
> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版](../../../../en/documentation/pages/debug/error-type.mdx)を参照してください。
|
||||
|
||||
---
|
||||
title: エラータイプ
|
||||
icon: "circle-xmark"
|
||||
---
|
||||
|
||||
各ノードタイプは、問題の原因と解決策を理解するのに役立つ特定のエラークラスをスローします。
|
||||
|
||||
## ノード固有のエラー
|
||||
|
||||
<Tabs>
|
||||
<Tab title="コード" icon="code">
|
||||
|
||||
`CodeNodeError`
|
||||
<Info>PythonまたはJavaScriptコードの実行中に例外がスローされました</Info>
|
||||
|
||||

|
||||
|
||||
`OutputValidationError`
|
||||
<Info>コードが返したデータ型が、設定した出力変数の型と一致しません</Info>
|
||||
|
||||
`DepthLimitError`
|
||||
<Info>コードが5階層より深いネストされたデータ構造を作成しました</Info>
|
||||
|
||||
`CodeExecutionError`
|
||||
<Info>サンドボックスサービスがコードを実行できませんでした - 通常、サービスがダウンしていることを意味します</Info>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
<Tab title="LLM" icon="brain">
|
||||
|
||||
`VariableNotFoundError`
|
||||
<Info>プロンプトテンプレートが、ワークフローのコンテキストに存在しない変数を参照しています</Info>
|
||||
|
||||

|
||||
|
||||
`InvalidContextStructureError`
|
||||
<Info>文字列のみを受け付けるコンテキストフィールドに配列またはオブジェクトを渡しました</Info>
|
||||
|
||||
`NoPromptFoundError`
|
||||
<Info>プロンプトフィールドが完全に空です</Info>
|
||||
|
||||
`ModelNotExistError`
|
||||
<Info>LLMノードの設定でモデルが選択されていません</Info>
|
||||
|
||||
`LLMModeRequiredError`
|
||||
<Info>選択されたモデルに有効なAPI認証情報が設定されていません</Info>
|
||||
|
||||
`InvalidVariableTypeError`
|
||||
<Info>プロンプトテンプレートが有効なJinja2構文またはプレーンテキスト形式ではありません</Info>
|
||||
|
||||

|
||||
|
||||
</Tab>
|
||||
<Tab title="HTTPリクエスト" icon="globe">
|
||||
|
||||
`AuthorizationConfigError`
|
||||
<Info>APIエンドポイントの認証設定が欠落しているか、無効です</Info>
|
||||
|
||||
`InvalidHttpMethodError`
|
||||
<Info>HTTPメソッドはGET、HEAD、POST、PUT、PATCH、またはDELETEである必要があります</Info>
|
||||
|
||||
`ResponseSizeError`
|
||||
<Info>APIレスポンスが10MBのサイズ制限を超えました</Info>
|
||||
|
||||
`FileFetchError`
|
||||
<Info>リクエストで参照されているファイル変数を取得できませんでした</Info>
|
||||
|
||||
`InvalidURLError`
|
||||
<Info>URLの形式が不正であるか、到達できません</Info>
|
||||
|
||||
</Tab>
|
||||
<Tab title="ツール" icon="wrench">
|
||||
|
||||
`ToolParameterError`
|
||||
<Info>ツールに渡されたパラメータが、期待されるスキーマと一致しません</Info>
|
||||
|
||||
`ToolFileError`
|
||||
<Info>ツールが必要なファイルにアクセスできませんでした</Info>
|
||||
|
||||
`ToolInvokeError`
|
||||
<Info>外部ツールAPIが実行中にエラーを返しました</Info>
|
||||
|
||||
<p align="center">
|
||||
<img src="https://assets-docs.dify.ai/2024/12/84af0831b7cb23e64159dfbba80e9b28.jpg" width="300" />
|
||||
</p>
|
||||
|
||||
`ToolProviderNotFoundError`
|
||||
<Info>ツールプロバイダーが正しくインストールまたは設定されていません</Info>
|
||||
|
||||
</Tab>
|
||||
</Tabs>
|
||||
|
||||
## システムレベルのエラー
|
||||
|
||||
`InvokeConnectionError`
|
||||
<Info>外部サービスへのネットワーク接続に失敗しました</Info>
|
||||
|
||||
`InvokeServerUnavailableError`
|
||||
<Info>外部サービスが503ステータスを返したか、一時的にダウンしています</Info>
|
||||
|
||||
`InvokeRateLimitError`
|
||||
<Info>APIまたはモデルプロバイダーのレート制限に達しました</Info>
|
||||
|
||||
`QuotaExceededError`
|
||||
<Info>このサービスの利用クォータを超えました</Info>
|
||||
128
ja-jp/documentation/pages/getting-started/faq.mdx
Normal file
128
ja-jp/documentation/pages/getting-started/faq.mdx
Normal file
@@ -0,0 +1,128 @@
|
||||
> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版](../../../../en/documentation/pages/getting-started/faq.mdx)を参照してください。
|
||||
|
||||
---
|
||||
title: "よくある質問"
|
||||
description: "Difyの使用に関する一般的な質問と回答"
|
||||
icon: "circle-question"
|
||||
---
|
||||
|
||||
Difyのよくある質問セクションへようこそ。ここでは、Difyの使用に関する最も一般的な質問への回答を見つけることができます。
|
||||
|
||||
## はじめに
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="Difyとは何ですか?">
|
||||
Difyは、AIアプリケーションを構築するためのオープンソースプラットフォームです。広範なコーディング知識がなくても、AIアプリケーションの構築、デプロイ、管理を支援する包括的なツールと機能のセットを提供します。
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Difyを始めるにはどうすればよいですか?">
|
||||
Difyを始めるには:
|
||||
|
||||
1. [dify.ai](https://dify.ai)でDifyアカウントに**サインアップ**します
|
||||
2. 直感的なインターフェースを使用して**最初のアプリケーションを作成**します
|
||||
3. OpenAI、Anthropicなどのプロバイダーに接続してAIモデルを**設定**します
|
||||
4. アプリケーションを**テストして改善**します
|
||||
5. AIアプリケーションを本番環境に**デプロイ**します
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Difyでどのような種類のアプリケーションを構築できますか?">
|
||||
Difyを使用して、さまざまなタイプのAIアプリケーションを構築できます:
|
||||
|
||||
- カスタマーサービス用の**チャットボット**
|
||||
- ドキュメントに関する質問に答えることができる**ナレッジベース**アシスタント
|
||||
- データをインテリジェントに処理する**ワークフロー**自動化ツール
|
||||
- マーケティングやライティング用の**コンテンツ生成ツール**
|
||||
- 複雑なタスクを実行できる**AIエージェント**
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 技術的な質問
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="DifyはどのAIモデルをサポートしていますか?">
|
||||
Difyは以下を含む幅広いAIモデルをサポートしています:
|
||||
|
||||
- **OpenAIモデル**:GPT-4、GPT-3.5など
|
||||
- **Anthropicモデル**:Claude 3とClaude 2
|
||||
- **オープンソースモデル**:Hugging Face、Ollamaなどのプロバイダー経由
|
||||
- **ローカルモデル**:独自のモデルをホストできます
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Difyは私のデータをどのように扱いますか?">
|
||||
データのセキュリティとプライバシーは私たちの最優先事項です:
|
||||
|
||||
- **あなたのデータはあなたのものです** - 私たちはあなたのプライベートデータでトレーニングを行いません
|
||||
- **転送中および保存時**の暗号化
|
||||
- エンタープライズ顧客向けの**SOC2コンプライアンス**
|
||||
- ヨーロッパのユーザー向けの**GDPRコンプライアンス**
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="Difyを商用目的で使用できますか?">
|
||||
はい!Difyは以下の両方を提供しています:
|
||||
|
||||
- セルフホスティング用のApache 2.0ライセンス付き**オープンソース版**
|
||||
- マネージドホスティング用の商用プラン付き**クラウド版**
|
||||
- 高度な機能とサポートを備えた**エンタープライズプラン**
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## トラブルシューティング
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="AIアプリケーションが誤った応答をします">
|
||||
以下のトラブルシューティング手順を試してください:
|
||||
|
||||
1. **プロンプトを確認する** - 明確かつ具体的であることを確認してください
|
||||
2. **ナレッジベースを確認する** - 関連ドキュメントがアップロードされていることを確認してください
|
||||
3. **モデルパラメータを調整する** - 異なる温度(temperature)やtop-k設定を試してください
|
||||
4. **異なるモデルでテストする** - 特定のタスクには、より適したモデルがあります
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="応答時間が遅いです">
|
||||
応答時間を改善するには:
|
||||
|
||||
1. **モデル設定を確認する** - モデルによっては他のモデルよりも高速なものがあります
|
||||
2. **ナレッジベースを最適化する** - 不要なドキュメントを削除してください
|
||||
3. **キャッシュを使用する** - よくある質問に対して応答キャッシュを有効にします
|
||||
4. パフォーマンス向上のためにプランの**アップグレードを検討**してください
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="サポートを受けるにはどうすればよいですか?">
|
||||
以下の方法でサポートを受けることができます:
|
||||
|
||||
- **コミュニティフォーラム** - 他のDifyユーザーと繋がります
|
||||
- **ドキュメンテーション** - 包括的なガイドとチュートリアル
|
||||
- **GitHubイシュー** - バグレポートや機能リクエスト用
|
||||
- **メールサポート** - 有料プランのお客様向け
|
||||
- **エンタープライズサポート** - エンタープライズ顧客向けの専用サポート
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
## 請求とプラン
|
||||
|
||||
<AccordionGroup>
|
||||
<Accordion title="どのような料金プランがありますか?">
|
||||
Difyはいくつかのプランを提供しています:
|
||||
|
||||
- **無料ティア** - 入門や小規模プロジェクトに最適です
|
||||
- **プロプラン** - 利用量の多い成長中のビジネス向け
|
||||
- **エンタープライズプラン** - 大規模組織向けのカスタムソリューション
|
||||
</Accordion>
|
||||
|
||||
<Accordion title="利用量はどのように計算されますか?">
|
||||
利用量は通常、以下に基づいて計算されます:
|
||||
|
||||
- AIモデルへの**API呼び出し**
|
||||
- ドキュメントとデータの**ストレージ**
|
||||
- アプリケーションの**アクティブユーザー**
|
||||
- プランに応じた**カスタム機能**
|
||||
|
||||
料金の詳細については、[料金ページ](https://dify.ai/pricing)をご覧ください。
|
||||
</Accordion>
|
||||
</AccordionGroup>
|
||||
|
||||
---
|
||||
|
||||
<Note>
|
||||
さらにサポートが必要ですか?サポートチームにお問い合わせいただくか、[包括的なドキュメンテーション](../../../guides/)をご覧ください。
|
||||
</Note>
|
||||
@@ -1,70 +0,0 @@
|
||||
---
|
||||
title: シングルページWebアプリとして公開
|
||||
---
|
||||
|
||||
|
||||
Difyを使ってAIアプリを作成するメリットの一つは、数分でユーザー向けのWebアプリを公開できることです。このアプリはあなたのプロンプトに基づいて機能します。
|
||||
|
||||
* 自己ホストのオープンソース版を使用する場合、そのアプリはあなたのサーバー上で動作します
|
||||
* クラウドサービスを使用する場合、そのアプリはUdify.appにホストされます
|
||||
|
||||
***
|
||||
|
||||
### AIサイトの公開
|
||||
|
||||
アプリ概要ページで、AIサイト(Webアプリ)に関するカードを見つけることができます。Webアプリのアクセスをオンにするだけで、ユーザーと共有できるリンクが得られます。
|
||||
|
||||

|
||||
|
||||
以下の2種類のアプリには、きれいなWebアプリのインターフェースを提供しています:
|
||||
|
||||
* テキスト生成型([前往预览](/ja-jp/guides/application-publishing/launch-your-webapp-quickly/text-generator))
|
||||
* 対話型([前往预览](/ja-jp/guides/application-publishing/launch-your-webapp-quickly/conversation-application))
|
||||
|
||||
***
|
||||
|
||||
### AIサイトの設定
|
||||
|
||||
Webアプリのカード上の**設定**ボタンをクリックすると、AIサイトのオプションをいくつか設定できます。これらは最終ユーザーに表示されます:
|
||||
|
||||
* アイコン
|
||||
* 名前
|
||||
* アプリの説明
|
||||
* インターフェース言語
|
||||
* 著作権情報
|
||||
* プライバシーポリシーリンク
|
||||
* カスタム免責事項
|
||||
|
||||
<Info>
|
||||
現在サポートされているインターフェース言語:英語、中国語(簡体字)、中国語(繁体字)、ポルトガル語、ドイツ語、日本語、韓国語、ウクライナ語、ベトナム語。追加の言語が必要な場合は、GitHubでイシューを提出するか、プルリクエストを提出してコードを提供してください。[サポートを求める](/ja-jp/community/support)。
|
||||
</Info>
|
||||
|
||||
***
|
||||
|
||||
### AIサイトの埋め込み
|
||||
|
||||
Difyは、あなたのAIアプリをビジネスWebサイトに埋め込むことをサポートしています。この機能を使えば、数分でビジネスデータを持つ公式サイトのAIカスタマーサポートやビジネス知識Q&Aなどのアプリを作成できます。Webアプリのカード上の埋め込みボタンをクリックし、埋め込みコードをコピーして、Webサイトの目標位置に貼り付けます。
|
||||
|
||||
* iframeタグの方法
|
||||
|
||||
iframeコードを、AIアプリを表示するあなたのWebサイトのタグ(例:`<div>`、`<section>`)にコピーします。
|
||||
* scriptタグの方法
|
||||
|
||||
scriptコードを、あなたのWebサイトの`<head>`または`<body>`タグにコピーします。
|
||||
|
||||

|
||||
|
||||
例えば、scriptコードを公式サイトの`<body>`に貼り付けると、公式サイトのAIロボットが得られます:
|
||||
|
||||

|
||||
|
||||
{/*
|
||||
Contributing Section
|
||||
DO NOT edit this section!
|
||||
It will be automatically generated by the script.
|
||||
*/}
|
||||
|
||||
---
|
||||
|
||||
[このページを編集する](https://github.com/langgenius/dify-docs/edit/main/ja-jp/guides/application-publishing/launch-your-webapp-quickly/README.mdx) | [問題を報告する](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)
|
||||
|
||||
@@ -1,11 +1,12 @@
|
||||
> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版](../../../en/guides/monitoring/README.mdx)を参照してください。
|
||||
|
||||
---
|
||||
title: モニタリング
|
||||
title: ダッシュボード
|
||||
---
|
||||
|
||||
**概要**セクションでは、本番環境でのアプリケーションのパフォーマンスを監視および追跡できます。データ分析ダッシュボードでは、使用コスト、レイテンシー、ユーザーフィードバック、本番環境でのパフォーマンスなど、さまざまなメトリクスを分析できます。継続的なデバッグとイテレーションにより、アプリケーションを継続的に改善できます。
|
||||
|
||||
**概要** で本番環境におけるアプリケーションのパフォーマンスをモニタリングし、データ分析ダッシュボードで本番環境におけるアプリケーションの使用コスト、レイテンシ、ユーザーフィードバック、パフォーマンスなどの指標を分析します。継続デバッグおよびイテレーションを通じてアプリケーションを絶えず改善します。
|
||||
|
||||

|
||||

|
||||
|
||||
{/*
|
||||
Contributing Section
|
||||
@@ -15,5 +16,4 @@ It will be automatically generated by the script.
|
||||
|
||||
---
|
||||
|
||||
[このページを編集する](https://github.com/langgenius/dify-docs/edit/main/ja-jp/guides/monitoring/README.mdx) | [問題を報告する](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)
|
||||
|
||||
[このページを編集](https://github.com/langgenius/dify-docs/edit/main/en/guides/monitoring/README.mdx) | [問題を報告](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)
|
||||
@@ -1,111 +0,0 @@
|
||||
---
|
||||
title: エラータイプの概要
|
||||
---
|
||||
|
||||
|
||||
本記事では、さまざまなノードで発生可能なトラブルと、それに伴うエラーの種類について解説します。
|
||||
|
||||
## チャットフロー/ワークフロー
|
||||
|
||||
* **システムエラー**
|
||||
システム関連の問題が原因で発生するエラーです。例えば、サービスが正しく起動していない、ネットワーク接続に問題がある場合などが該当します。
|
||||
|
||||
* **操作エラー**
|
||||
開発者がノードの設定や操作に失敗した際に生じるエラーです。
|
||||
|
||||
## コードノード
|
||||
[コードノード](/ja-jp/guides/workflow/nodes/code)を使用することで、PythonやJavaScriptのコードを実行し、データ変換を行うことができます。ここでは、よくある4つのエラーを紹介します:
|
||||
|
||||
1. **コードエラー(CodeNodeError)**
|
||||
開発者のコード内で例外が発生した場合にこのエラーが起きます。変数が不足している、計算ロジックが間違っている、文字列として扱うべき配列を誤って変数として扱っている場合などがあります。エラーメッセージや具体的な行番号で問題を特定できます。
|
||||
|
||||

|
||||
|
||||
2. **サンドボックスのネットワーク問題(System Error)**
|
||||
ネットワークのトラフィック異常や接続問題によって生じるエラーです。サンドボックスサービスが停止している、プロキシがネットワークをブロックしている場合などです。この問題は次の手順で解決可能です:
|
||||
a. ネットワークの品質を確認する
|
||||
b. サンドボックスサービスを再起動する
|
||||
c. プロキシ設定を見直す
|
||||
|
||||

|
||||
|
||||
3. **ネスト制限エラー(DepthLimitError)**
|
||||
現在のノードは、最大で5層までのネスト構造をサポートしています。これを超えるとエラーが発生します。
|
||||
|
||||

|
||||
|
||||
4. **出力検証エラー(OutputValidationError)**
|
||||
選択した出力変数の型と実際の出力変数の型が一致しない場合に生じるエラーです。開発者は適切な出力変数の型を選択し直すことで、この問題を回避することができます。
|
||||
|
||||

|
||||
|
||||
## LLMノード
|
||||
|
||||
[LLMノード](/ja-jp/guides/workflow/nodes/llm)は、チャットフローやワークフローの中核をなすコンポーネントであり、大規模言語モデルを用いて様々なタスクを処理します。
|
||||
|
||||
以下は、実行時に遭遇する可能性のある6つの一般的なエラーです:
|
||||
|
||||
1. **変数が見つからない(VariableNotFoundError)**
|
||||
システムプロンプトやコンテキストで指定された変数がLLMによって見つけられない場合にこのエラーが発生します。開発者は、補足となる変数を設定することで問題を解決できます。
|
||||
|
||||

|
||||
|
||||
2. **コンテキスト構造の無効 (InvalidContextStructureError)**
|
||||
LLMノードが不正なデータ構造を受け取った場合に報告されます。コンテキストは文字列データ構造のみをサポートします。
|
||||
|
||||
3. **無効な変数タイプ(InvalidVariableTypeError)**
|
||||
システムプロンプトの形式が一般的なテキストやJinja syntaxでない場合にこのエラーが生じます。
|
||||
|
||||
4. **モデルが存在しない(ModelNotExistError)**
|
||||
各LLMノードにはモデルの指定が必要です。モデルが選択されていない場合には、このエラーが発生します。
|
||||
|
||||
5. **LLMの認証が必要(LLMModeRequiredError)**
|
||||
選択されたモデルにAPIキーが設定されていない場合にこのエラーが報告されます。ドキュメントの指示に従ってモデルを認証してください。
|
||||
|
||||
6. **プロンプトが見つからない(NoPromptFoundError)**
|
||||
LLMノードのプロンプトが空の場合、エラーが生じます。
|
||||
|
||||
## HTTPノード
|
||||
|
||||
[HTTPノード](/ja-jp/guides/workflow/nodes/http-request)は、HTTPリクエストを送信してデータを取得、Webhookを発火、画像を生成、ファイルをダウンロードするなどの操作を可能にし、カスタマイズ可能なリクエストによって外部サービスとのシームレスな統合を実現します。ここでは、このノードで頻繁に発生する5つの一般的なエラーを紹介します:
|
||||
|
||||
1. **認証設定エラー(AuthorizationConfigError)**
|
||||
認証情報が設定されていない場合に発生するエラーです。
|
||||
|
||||
2. **ファイル取得エラー(FileFetchError)**
|
||||
ファイル変数が取得できない場合に発生するエラーです。
|
||||
|
||||
3. **不正なHTTPリクエストメソッド(InvalidHttpMethodError)**
|
||||
リクエストメソッドがGET、HEAD、POST、PUT、PATCH、DELETEのいずれにも該当しない場合にエラーが発生します。
|
||||
|
||||
4. **レスポンスサイズ超過(ResponseSizeError)**
|
||||
HTTPレスポンスが10MBの制限を超えると、このエラーが発生します。
|
||||
|
||||
5. **HTTPレスポンスコードエラー(HTTPResponseCodeError)**
|
||||
レスポンスコードが200系以外(例:400、404、500など)の場合にエラーが報告されます。例外処理が有効であれば、これらのステータスコードによるエラーが報告されますが、それ以外ではエラーは報告されません。
|
||||
|
||||
## ツールノード
|
||||
|
||||
ランタイムでよく遭遇する3つのエラーは以下のとおりです:
|
||||
|
||||
1. **ツール実行エラー(ToolNodeError)**
|
||||
ツール自体の実行に問題があった場合に報告されるエラーです。たとえば、目指すAPIのリクエスト制限に達した場合などがこれに該当します。
|
||||
|
||||

|
||||
|
||||
2. **ツールパラメータエラー(ToolParameterError)**
|
||||
ツールノードの設定パラメータに問題がある場合、つまりツールノードが要求するパラメータと異なる値が入力された場合にこのエラーが発生します。
|
||||
|
||||
3. **ツールファイル処理エラー(ToolFileError)**
|
||||
ツールノードの処理に必要なファイルが見つからない場合にこのエラーが発生します。
|
||||
|
||||
{/*
|
||||
Contributing Section
|
||||
DO NOT edit this section!
|
||||
It will be automatically generated by the script.
|
||||
*/}
|
||||
|
||||
---
|
||||
|
||||
[このページを編集する](https://github.com/langgenius/dify-docs/edit/main/ja-jp/guides/workflow/error-handling/error-type.mdx) | [問題を報告する](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)
|
||||
|
||||
@@ -1,115 +0,0 @@
|
||||
---
|
||||
title: オーケストレートノード
|
||||
---
|
||||
|
||||
チャットフローおよびワークフローアプリケーションは、ビジュアルなドラッグアンドドロップ機能を通じてノードのオーケストレーションをサポートしており、シリアルおよびパラレルの2つのオーケストレーションデザインパターンがあります。
|
||||
|
||||

|
||||
|
||||
## シリアルノードのデザインパターン
|
||||
|
||||
このパターンでは、ノードはあらかじめ定義された順序で順次実行されます。各ノードは、前のノードがタスクを完了し、出力を生成した後にのみ操作を開始します。これにより、タスクが論理的な順序で実行されることが保証されます。
|
||||
|
||||
シリアルパターンを実装した「小説生成」ワークフローアプリケーションを考えてみましょう。ユーザーが小説のスタイル、リズム、キャラクターを入力した後、LLMが順番に小説の概要、プロット、エンディングを完成させます。各ノードは前のノードの出力に基づいて動作し、小説のスタイルに一貫性をもたらします。
|
||||
|
||||
### シリアル構造の作り方
|
||||
|
||||
1. 2つのノードの間にある「+」アイコンをクリックして新しいシリアルノードを挿入します。
|
||||
2. ノードを順次リンクします。
|
||||
3. すべてのパスを「終了」ノード(ワークフロー)/「直接回答」ノード(チャットフロー)に収束させて、ワークフローを最終承認します。
|
||||
|
||||

|
||||
|
||||
### シリアル構造のアプリのログをチェックする
|
||||
|
||||
シリアル構造のアプリは、ログが順次ノードの操作を表示します。会話ボックスの右上にある "View Logs - Tracing" を順にクリックすると、各ノードの入力、出力、トークン消費、実行時間を含む完全なワークフロープロセスが表示されます。
|
||||
|
||||

|
||||
|
||||
## パラレルノードのデザインパターン
|
||||
|
||||
このアーキテクチャパターンは、複数のノードを並行して実行することを可能にします。前のノードは、パラレル構造内の複数のノードを同時にトリガーできます。これらのパラレルノードは独立して動作し、タスクを同時に実行することで、全体のワークフロー効率を大幅に向上させます。
|
||||
|
||||
パラレルアーキテクチャを実装した翻訳ワークフローアプリケーションを考えてみましょう。ユーザーがソーステキストを入力してワークフローをトリガーすると、パラレル構造内のすべてのノードが前のノードから同時に命令を受け取ります。これにより、複数の言語への同時翻訳が可能となり、全体の処理時間が大幅に短縮されます。
|
||||
|
||||
### パラレルノードのデザインパターン
|
||||
|
||||
次の4つの方法は、ノードの追加やビジュアル操作を通じてパラレル構造を作成する方法を示しています:
|
||||
|
||||
**方法1**\
|
||||
ノードの上にカーソルを合わせると「+」ボタンが表示されます。クリックすると、複数のノードが追加され、自動的にパラレル構造が形成されます。
|
||||
|
||||

|
||||
|
||||
**方法2**\
|
||||
ノードから接続を延長するには、ノードの「+」ボタンをドラッグしてパラレル構造を作成します。
|
||||
|
||||

|
||||
|
||||
**方法3**\
|
||||
キャンバス上に複数のノードがある場合は、ビジュアルにドラッグしてリンクし、パラレル構造を形成します。
|
||||
|
||||

|
||||
|
||||
**方法4**\
|
||||
キャンバスベースの方法に加えて、ノードの右側パネルの「Next Step」セクションからノードを追加することで、パラレル構造を生成することもできます。このアプローチにより、自動的にパラレル構成が作成されます。
|
||||
|
||||

|
||||
|
||||
**注意:**
|
||||
|
||||
* 任意のノードがパラレル構造の下流ノードとして機能します。
|
||||
* ワークフローアプリケーションには、単一かつ一意な「end」ノードが必要です。
|
||||
* チャットフローアプリケーションでは複数の「answer」ノードがサポートされます。これらのアプリケーションの各パラレル構造は、適切なコンテンツの出力を確保するために「answer」ノードで終了する必要があります。
|
||||
* すべてのパラレル構造は同時に実行されます。パラレル構造内のノードは、タスクを完了した後に結果を出力し、出力には順序関係がありません。パラレル構造が単純であればあるほど、結果の出力が速くなります。
|
||||
|
||||

|
||||
|
||||
### パラレル構造の作り方
|
||||
|
||||
以下の4つのパターンは、一般的なパラレル構造デザインを示しています:
|
||||
|
||||
#### 1. 通常のパラレル
|
||||
|
||||
通常のパラレルは、「開始 | パラレルノード | 終了」の3階層関係を指します。この構造は直感的で、ユーザー入力後に複数のタスクを同時に実行できます。
|
||||
|
||||
パラレルブランチの上限は10です。
|
||||
|
||||

|
||||
|
||||
#### 2. ネストされたパラレル
|
||||
|
||||
ネストされたパラレルは、「開始 | 複数のパラレル構造 | 終了」の多階層関係を指します。これは、外部APIを要求する必要があるノード内で同時に複数のタスクを処理し、結果を下流ノードに渡す必要があるような、より複雑なワークフローに適しています。
|
||||
|
||||
ワークフローは、最大3層までのネスト関係をサポートします。
|
||||
|
||||

|
||||
|
||||
#### 3. 条件分岐 + パラレル
|
||||
|
||||
パラレル構造は条件分岐と組み合わせて使用することもできます。
|
||||
|
||||

|
||||
|
||||
#### 4. イテレーション + パラレル
|
||||
|
||||
このパターンは、イテレーションとパラレル構造を組み合わせたものです。
|
||||
|
||||

|
||||
|
||||
### パラレル構造のアプリのログをチェックする
|
||||
|
||||
パラレル構造をもつアプリケーションは、ツリーのような形式でログを生成します。折りたたみ可能なパラレルノード グループにより、個々のノード ログを簡単に表示できます。
|
||||
|
||||

|
||||
|
||||
{/*
|
||||
Contributing Section
|
||||
DO NOT edit this section!
|
||||
It will be automatically generated by the script.
|
||||
*/}
|
||||
|
||||
---
|
||||
|
||||
[このページを編集する](https://github.com/langgenius/dify-docs/edit/main/ja-jp/guides/workflow/orchestrate-node.mdx) | [問題を報告する](https://github.com/langgenius/dify-docs/issues/new?template=docs.yml)
|
||||
|
||||
83
tools/translate/config.json
Normal file
83
tools/translate/config.json
Normal file
@@ -0,0 +1,83 @@
|
||||
{
|
||||
"path_mappings": {
|
||||
"en": ["zh-hans", "ja-jp"],
|
||||
"en/documentation": ["zh-hans/documentation", "ja-jp/documentation"],
|
||||
"en/self-hosting": ["zh-hans/self-hosting", "ja-jp/self-hosting"],
|
||||
"en/api-reference": ["zh-hans/api-reference", "ja-jp/api-reference"]
|
||||
},
|
||||
"label_translations": {
|
||||
"Getting Started": {
|
||||
"zh-hans": "快速开始",
|
||||
"ja-jp": "はじめに"
|
||||
},
|
||||
"Documentation": {
|
||||
"zh-hans": "文档",
|
||||
"ja-jp": "ドキュメント"
|
||||
},
|
||||
"Build": {
|
||||
"zh-hans": "构建",
|
||||
"ja-jp": "ビルド"
|
||||
},
|
||||
"Debug": {
|
||||
"zh-hans": "调试",
|
||||
"ja-jp": "デバッグ"
|
||||
},
|
||||
"Publish": {
|
||||
"zh-hans": "发布",
|
||||
"ja-jp": "公開"
|
||||
},
|
||||
"Monitor": {
|
||||
"zh-hans": "监控",
|
||||
"ja-jp": "モニタリング"
|
||||
},
|
||||
"Knowledge": {
|
||||
"zh-hans": "知识库",
|
||||
"ja-jp": "ナレッジベース"
|
||||
},
|
||||
"Workspace": {
|
||||
"zh-hans": "工作区",
|
||||
"ja-jp": "ワークスペース"
|
||||
},
|
||||
"Tutorials": {
|
||||
"zh-hans": "教程",
|
||||
"ja-jp": "チュートリアル"
|
||||
},
|
||||
"FAQ": {
|
||||
"zh-hans": "常见问题",
|
||||
"ja-jp": "よくある質問"
|
||||
},
|
||||
"Introduction": {
|
||||
"zh-hans": "介绍",
|
||||
"ja-jp": "紹介"
|
||||
},
|
||||
"Quick Start": {
|
||||
"zh-hans": "快速开始",
|
||||
"ja-jp": "クイックスタート"
|
||||
},
|
||||
"Key Concepts": {
|
||||
"zh-hans": "核心概念",
|
||||
"ja-jp": "主要概念"
|
||||
},
|
||||
"Nodes": {
|
||||
"zh-hans": "节点",
|
||||
"ja-jp": "ノード"
|
||||
},
|
||||
"Self Hosting": {
|
||||
"zh-hans": "自部署",
|
||||
"ja-jp": "セルフホスティング"
|
||||
},
|
||||
"API Reference": {
|
||||
"zh-hans": "API 参考",
|
||||
"ja-jp": "API リファレンス"
|
||||
},
|
||||
"Develop": {
|
||||
"zh-hans": "开发",
|
||||
"ja-jp": "開発"
|
||||
}
|
||||
},
|
||||
"docs_json_language_mapping": {
|
||||
"en": "en",
|
||||
"zh-hans": "zh-Hans",
|
||||
"ja-jp": "jp"
|
||||
}
|
||||
}
|
||||
4
tools/translate/notices.json
Normal file
4
tools/translate/notices.json
Normal file
@@ -0,0 +1,4 @@
|
||||
{
|
||||
"zh-hans": "> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版]({en_path})。\n\n",
|
||||
"ja-jp": "> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版]({en_path})を参照してください。\n\n"
|
||||
}
|
||||
532
tools/translate/sync_and_translate.py
Normal file
532
tools/translate/sync_and_translate.py
Normal file
@@ -0,0 +1,532 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Documentation Auto-Sync System
|
||||
Synchronizes English documentation structure and content to Chinese and Japanese versions.
|
||||
"""
|
||||
|
||||
import json
|
||||
import os
|
||||
import sys
|
||||
import asyncio
|
||||
import shutil
|
||||
from pathlib import Path
|
||||
from typing import Dict, List, Set, Tuple, Optional, Any
|
||||
import subprocess
|
||||
import tempfile
|
||||
|
||||
# Import the existing translation function
|
||||
from main import translate_text, load_md_mdx
|
||||
|
||||
# --- Configuration ---
|
||||
SCRIPT_DIR = Path(__file__).resolve().parent
|
||||
BASE_DIR = SCRIPT_DIR.parent.parent
|
||||
DOCS_JSON_PATH = BASE_DIR / "docs.json"
|
||||
|
||||
# Language configurations
|
||||
LANGUAGES = {
|
||||
"en": {
|
||||
"name": "English",
|
||||
"base_path": "en",
|
||||
"code": "en"
|
||||
},
|
||||
"zh-hans": {
|
||||
"name": "Chinese",
|
||||
"base_path": "zh-hans",
|
||||
"code": "zh-Hans"
|
||||
},
|
||||
"ja-jp": {
|
||||
"name": "Japanese",
|
||||
"base_path": "ja-jp",
|
||||
"code": "jp"
|
||||
}
|
||||
}
|
||||
|
||||
TARGET_LANGUAGES = ["zh-hans", "ja-jp"]
|
||||
|
||||
class DocsSynchronizer:
|
||||
def __init__(self, dify_api_key: str):
|
||||
self.dify_api_key = dify_api_key
|
||||
self.base_dir = BASE_DIR
|
||||
self.docs_json_path = DOCS_JSON_PATH
|
||||
self.config = self.load_config()
|
||||
self.notices = self.load_notices()
|
||||
|
||||
def load_config(self) -> Dict[str, Any]:
|
||||
"""Load configuration file with language mappings"""
|
||||
config_path = SCRIPT_DIR / "config.json"
|
||||
if config_path.exists():
|
||||
with open(config_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
return {
|
||||
"path_mappings": {
|
||||
"en": ["zh-hans", "ja-jp"]
|
||||
},
|
||||
"label_translations": {}
|
||||
}
|
||||
|
||||
def load_notices(self) -> Dict[str, str]:
|
||||
"""Load AI translation notice templates"""
|
||||
notices_path = SCRIPT_DIR / "notices.json"
|
||||
if notices_path.exists():
|
||||
with open(notices_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
return {
|
||||
"zh-hans": "> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版]({en_path})。\n\n",
|
||||
"ja-jp": "> ⚠️ このドキュメントはAIによって自動翻訳されています。不正確な部分がある場合は、[英語版]({en_path})を参照してください。\n\n"
|
||||
}
|
||||
|
||||
def get_changed_files(self, since_commit: str = "HEAD~1") -> Dict[str, List[str]]:
|
||||
"""Get changed files using git diff"""
|
||||
try:
|
||||
# Get file changes
|
||||
result = subprocess.run([
|
||||
"git", "diff", "--name-status", since_commit, "HEAD"
|
||||
], capture_output=True, text=True, cwd=self.base_dir)
|
||||
|
||||
changes = {
|
||||
"added": [],
|
||||
"modified": [],
|
||||
"deleted": [],
|
||||
"renamed": []
|
||||
}
|
||||
|
||||
for line in result.stdout.strip().split('\n'):
|
||||
if not line:
|
||||
continue
|
||||
|
||||
parts = line.split('\t')
|
||||
status = parts[0]
|
||||
|
||||
if status == 'A':
|
||||
changes["added"].append(parts[1])
|
||||
elif status == 'M':
|
||||
changes["modified"].append(parts[1])
|
||||
elif status == 'D':
|
||||
changes["deleted"].append(parts[1])
|
||||
elif status.startswith('R'):
|
||||
changes["renamed"].append((parts[1], parts[2]))
|
||||
|
||||
return changes
|
||||
except subprocess.CalledProcessError as e:
|
||||
print(f"Error getting git changes: {e}")
|
||||
return {"added": [], "modified": [], "deleted": [], "renamed": []}
|
||||
|
||||
def is_english_doc_file(self, file_path: str) -> bool:
|
||||
"""Check if file is an English documentation file that should be synced"""
|
||||
return (file_path.startswith("en/") and
|
||||
(file_path.endswith('.md') or file_path.endswith('.mdx')) and
|
||||
not file_path.startswith("en/api-reference/"))
|
||||
|
||||
def convert_path_to_target_language(self, en_path: str, target_lang: str) -> str:
|
||||
"""Convert English path to target language path"""
|
||||
if en_path.startswith("en/"):
|
||||
return en_path.replace("en/", f"{target_lang}/", 1)
|
||||
return en_path
|
||||
|
||||
def get_relative_en_path_for_notice(self, target_path: str) -> str:
|
||||
"""Get relative path to English version for AI notice"""
|
||||
# Convert zh-hans/documentation/pages/getting-started/faq.md
|
||||
# to ../../en/documentation/pages/getting-started/faq.md
|
||||
if target_path.startswith("zh-hans/"):
|
||||
en_path = target_path.replace("zh-hans/", "en/", 1)
|
||||
elif target_path.startswith("ja-jp/"):
|
||||
en_path = target_path.replace("ja-jp/", "en/", 1)
|
||||
else:
|
||||
return ""
|
||||
|
||||
# Count directory levels to create relative path
|
||||
target_dir_levels = len(Path(target_path).parent.parts)
|
||||
relative_prefix = "../" * target_dir_levels
|
||||
return relative_prefix + en_path
|
||||
|
||||
async def translate_file_with_notice(self, en_file_path: str, target_file_path: str, target_lang: str) -> bool:
|
||||
"""Translate a file and add AI notice at the top"""
|
||||
try:
|
||||
print(f"Translating {en_file_path} to {target_file_path}")
|
||||
|
||||
# Ensure target directory exists
|
||||
target_dir = Path(self.base_dir / target_file_path).parent
|
||||
target_dir.mkdir(parents=True, exist_ok=True)
|
||||
|
||||
# Get language names for translation API
|
||||
en_lang_name = LANGUAGES["en"]["name"]
|
||||
target_lang_name = LANGUAGES[target_lang]["name"]
|
||||
|
||||
# Translate content
|
||||
translated_content = await translate_text(
|
||||
str(self.base_dir / en_file_path),
|
||||
self.dify_api_key,
|
||||
en_lang_name,
|
||||
target_lang_name
|
||||
)
|
||||
|
||||
if not translated_content or not translated_content.strip():
|
||||
print(f"Warning: No translated content received for {en_file_path}")
|
||||
return False
|
||||
|
||||
# Prepare AI notice
|
||||
en_relative_path = self.get_relative_en_path_for_notice(target_file_path)
|
||||
notice = self.notices.get(target_lang, "").format(en_path=en_relative_path)
|
||||
|
||||
# Combine notice and translated content
|
||||
final_content = notice + translated_content
|
||||
|
||||
# Write to target file
|
||||
with open(self.base_dir / target_file_path, 'w', encoding='utf-8') as f:
|
||||
f.write(final_content)
|
||||
|
||||
print(f"✓ Successfully created {target_file_path}")
|
||||
return True
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error translating {en_file_path} to {target_file_path}: {e}")
|
||||
return False
|
||||
|
||||
def sync_file_operations(self, changes: Dict[str, List[str]]) -> List[str]:
|
||||
"""Sync file operations to target languages"""
|
||||
operations_log = []
|
||||
|
||||
# Handle added files
|
||||
for file_path in changes["added"]:
|
||||
if self.is_english_doc_file(file_path):
|
||||
for target_lang in TARGET_LANGUAGES:
|
||||
target_path = self.convert_path_to_target_language(file_path, target_lang)
|
||||
# We'll translate these in the async part
|
||||
operations_log.append(f"WILL_TRANSLATE: {file_path} -> {target_path}")
|
||||
|
||||
# Handle deleted files
|
||||
for file_path in changes["deleted"]:
|
||||
if self.is_english_doc_file(file_path):
|
||||
for target_lang in TARGET_LANGUAGES:
|
||||
target_path = self.convert_path_to_target_language(file_path, target_lang)
|
||||
target_full_path = self.base_dir / target_path
|
||||
if target_full_path.exists():
|
||||
target_full_path.unlink()
|
||||
operations_log.append(f"DELETED: {target_path}")
|
||||
|
||||
# Handle renamed files
|
||||
for old_path, new_path in changes["renamed"]:
|
||||
if self.is_english_doc_file(old_path) or self.is_english_doc_file(new_path):
|
||||
for target_lang in TARGET_LANGUAGES:
|
||||
old_target = self.convert_path_to_target_language(old_path, target_lang)
|
||||
new_target = self.convert_path_to_target_language(new_path, target_lang)
|
||||
|
||||
old_full_path = self.base_dir / old_target
|
||||
new_full_path = self.base_dir / new_target
|
||||
|
||||
if old_full_path.exists():
|
||||
# Ensure target directory exists
|
||||
new_full_path.parent.mkdir(parents=True, exist_ok=True)
|
||||
shutil.move(str(old_full_path), str(new_full_path))
|
||||
operations_log.append(f"RENAMED: {old_target} -> {new_target}")
|
||||
|
||||
return operations_log
|
||||
|
||||
async def translate_new_and_modified_files(self, changes: Dict[str, List[str]]) -> List[str]:
|
||||
"""Translate new and modified files"""
|
||||
translation_log = []
|
||||
tasks = []
|
||||
|
||||
# Collect translation tasks
|
||||
for file_path in changes["added"] + changes["modified"]:
|
||||
if self.is_english_doc_file(file_path):
|
||||
for target_lang in TARGET_LANGUAGES:
|
||||
target_path = self.convert_path_to_target_language(file_path, target_lang)
|
||||
task = self.translate_file_with_notice(file_path, target_path, target_lang)
|
||||
tasks.append((task, file_path, target_path))
|
||||
|
||||
# Handle renamed files that need translation
|
||||
for old_path, new_path in changes["renamed"]:
|
||||
if self.is_english_doc_file(new_path):
|
||||
for target_lang in TARGET_LANGUAGES:
|
||||
target_path = self.convert_path_to_target_language(new_path, target_lang)
|
||||
task = self.translate_file_with_notice(new_path, target_path, target_lang)
|
||||
tasks.append((task, new_path, target_path))
|
||||
|
||||
# Execute translations with concurrency control
|
||||
semaphore = asyncio.Semaphore(2) # Limit concurrent translations
|
||||
|
||||
async def bounded_translate(task, en_path, target_path):
|
||||
async with semaphore:
|
||||
success = await task
|
||||
return success, en_path, target_path
|
||||
|
||||
# Run translations
|
||||
if tasks:
|
||||
print(f"Starting {len(tasks)} translation tasks...")
|
||||
results = await asyncio.gather(*[
|
||||
bounded_translate(task, en_path, target_path)
|
||||
for task, en_path, target_path in tasks
|
||||
], return_exceptions=True)
|
||||
|
||||
for result in results:
|
||||
if isinstance(result, Exception):
|
||||
translation_log.append(f"ERROR: {result}")
|
||||
else:
|
||||
success, en_path, target_path = result
|
||||
if success:
|
||||
translation_log.append(f"TRANSLATED: {en_path} -> {target_path}")
|
||||
else:
|
||||
translation_log.append(f"FAILED: {en_path} -> {target_path}")
|
||||
|
||||
return translation_log
|
||||
|
||||
def load_docs_json(self) -> Dict[str, Any]:
|
||||
"""Load docs.json file"""
|
||||
try:
|
||||
with open(self.docs_json_path, 'r', encoding='utf-8') as f:
|
||||
return json.load(f)
|
||||
except Exception as e:
|
||||
print(f"Error loading docs.json: {e}")
|
||||
return {}
|
||||
|
||||
def save_docs_json(self, data: Dict[str, Any]) -> bool:
|
||||
"""Save docs.json file"""
|
||||
try:
|
||||
with open(self.docs_json_path, 'w', encoding='utf-8') as f:
|
||||
json.dump(data, f, ensure_ascii=False, indent=4)
|
||||
return True
|
||||
except Exception as e:
|
||||
print(f"Error saving docs.json: {e}")
|
||||
return False
|
||||
|
||||
def extract_english_structure_changes(self, changes: Dict[str, List[str]]) -> bool:
|
||||
"""Check if docs.json was modified"""
|
||||
return "docs.json" in changes["modified"] or "docs.json" in changes["added"]
|
||||
|
||||
def get_basic_label_translation(self, en_label: str, target_lang: str) -> str:
|
||||
"""Get basic translation for common labels"""
|
||||
basic_translations = {
|
||||
"zh-hans": {
|
||||
"Getting Started": "快速开始",
|
||||
"Documentation": "文档",
|
||||
"Build": "构建",
|
||||
"Debug": "调试",
|
||||
"Publish": "发布",
|
||||
"Monitor": "监控",
|
||||
"Knowledge": "知识库",
|
||||
"Workspace": "工作区",
|
||||
"Tutorials": "教程",
|
||||
"FAQ": "常见问题",
|
||||
"Introduction": "介绍",
|
||||
"Quick Start": "快速开始",
|
||||
"Key Concepts": "核心概念"
|
||||
},
|
||||
"ja-jp": {
|
||||
"Getting Started": "はじめに",
|
||||
"Documentation": "ドキュメント",
|
||||
"Build": "ビルド",
|
||||
"Debug": "デバッグ",
|
||||
"Publish": "公開",
|
||||
"Monitor": "モニタリング",
|
||||
"Knowledge": "ナレッジベース",
|
||||
"Workspace": "ワークスペース",
|
||||
"Tutorials": "チュートリアル",
|
||||
"FAQ": "よくある質問",
|
||||
"Introduction": "紹介",
|
||||
"Quick Start": "クイックスタート",
|
||||
"Key Concepts": "主要概念"
|
||||
}
|
||||
}
|
||||
|
||||
return basic_translations.get(target_lang, {}).get(en_label, en_label)
|
||||
|
||||
def sync_docs_json_structure(self) -> List[str]:
|
||||
"""Sync docs.json structure across languages"""
|
||||
sync_log = []
|
||||
|
||||
try:
|
||||
docs_data = self.load_docs_json()
|
||||
if not docs_data or "navigation" not in docs_data:
|
||||
sync_log.append("ERROR: Invalid docs.json structure")
|
||||
return sync_log
|
||||
|
||||
navigation = docs_data["navigation"]
|
||||
if "languages" not in navigation or not isinstance(navigation["languages"], list):
|
||||
sync_log.append("ERROR: No languages found in navigation")
|
||||
return sync_log
|
||||
|
||||
# Find language sections
|
||||
en_section = None
|
||||
zh_section = None
|
||||
ja_section = None
|
||||
|
||||
for lang_data in navigation["languages"]:
|
||||
if lang_data.get("language") == "en":
|
||||
en_section = lang_data
|
||||
elif lang_data.get("language") == "zh-Hans":
|
||||
zh_section = lang_data
|
||||
elif lang_data.get("language") == "jp":
|
||||
ja_section = lang_data
|
||||
|
||||
if not en_section:
|
||||
sync_log.append("ERROR: English section not found")
|
||||
return sync_log
|
||||
|
||||
# Extract Documentation dropdown from English section
|
||||
en_doc_dropdown = None
|
||||
for dropdown in en_section.get("dropdowns", []):
|
||||
if dropdown.get("dropdown") == "Documentation":
|
||||
en_doc_dropdown = dropdown
|
||||
break
|
||||
|
||||
if not en_doc_dropdown:
|
||||
sync_log.append("INFO: No Documentation dropdown found in English section")
|
||||
return sync_log
|
||||
|
||||
# Sync structure for Chinese and Japanese sections
|
||||
for target_section, target_lang, target_dropdown_name in [
|
||||
(zh_section, "zh-hans", "文档"),
|
||||
(ja_section, "ja-jp", "ドキュメント")
|
||||
]:
|
||||
if not target_section:
|
||||
sync_log.append(f"WARNING: {target_lang} section not found")
|
||||
continue
|
||||
|
||||
# Find existing Documentation dropdown (check both new and old names)
|
||||
target_doc_dropdown = None
|
||||
dropdown_index = -1
|
||||
old_names = ["使用文档"] if target_lang == "zh-hans" else ["ドキュメント"] if target_lang == "ja-jp" else []
|
||||
|
||||
for i, dropdown in enumerate(target_section.get("dropdowns", [])):
|
||||
dropdown_name = dropdown.get("dropdown", "")
|
||||
if dropdown_name == target_dropdown_name or dropdown_name in old_names:
|
||||
target_doc_dropdown = dropdown
|
||||
dropdown_index = i
|
||||
break
|
||||
|
||||
if not target_doc_dropdown:
|
||||
# Create new Documentation dropdown
|
||||
target_doc_dropdown = {
|
||||
"dropdown": target_dropdown_name,
|
||||
"icon": "book-open",
|
||||
"pages": []
|
||||
}
|
||||
target_section.setdefault("dropdowns", [])
|
||||
target_section["dropdowns"].append(target_doc_dropdown)
|
||||
sync_log.append(f"INFO: Created new Documentation dropdown for {target_lang}")
|
||||
else:
|
||||
# Update existing dropdown to new structure
|
||||
target_doc_dropdown["dropdown"] = target_dropdown_name # Update name if needed
|
||||
target_doc_dropdown["icon"] = "book-open" # Ensure icon is set
|
||||
# Remove old structure fields if they exist
|
||||
if "groups" in target_doc_dropdown:
|
||||
del target_doc_dropdown["groups"]
|
||||
sync_log.append(f"INFO: Updated existing Documentation dropdown for {target_lang}")
|
||||
|
||||
# Sync the structure by converting English paths to target language paths
|
||||
if "pages" in en_doc_dropdown:
|
||||
synced_pages = self.convert_pages_structure(en_doc_dropdown["pages"], target_lang)
|
||||
target_doc_dropdown["pages"] = synced_pages
|
||||
sync_log.append(f"INFO: Synced documentation structure for {target_lang}")
|
||||
|
||||
# Save the updated docs.json
|
||||
if self.save_docs_json(docs_data):
|
||||
sync_log.append("INFO: Updated docs.json with synced structure")
|
||||
else:
|
||||
sync_log.append("ERROR: Failed to save updated docs.json")
|
||||
|
||||
except Exception as e:
|
||||
sync_log.append(f"ERROR: Exception in docs.json sync: {e}")
|
||||
import traceback
|
||||
sync_log.append(f"TRACE: {traceback.format_exc()}")
|
||||
|
||||
return sync_log
|
||||
|
||||
def convert_pages_structure(self, pages_structure, target_lang: str):
|
||||
"""Recursively convert English page paths to target language paths"""
|
||||
if not pages_structure:
|
||||
return []
|
||||
|
||||
converted = []
|
||||
for item in pages_structure:
|
||||
if isinstance(item, str):
|
||||
# Convert path: en/documentation/pages/... -> target_lang/documentation/pages/...
|
||||
if item.startswith("en/"):
|
||||
converted_path = item.replace("en/", f"{target_lang}/", 1)
|
||||
converted.append(converted_path)
|
||||
else:
|
||||
converted.append(item)
|
||||
elif isinstance(item, dict):
|
||||
converted_item = {}
|
||||
for key, value in item.items():
|
||||
if key == "pages" and isinstance(value, list):
|
||||
converted_item[key] = self.convert_pages_structure(value, target_lang)
|
||||
elif key == "group":
|
||||
# Translate group names
|
||||
translated_group = self.get_basic_label_translation(value, target_lang)
|
||||
converted_item[key] = translated_group
|
||||
else:
|
||||
converted_item[key] = value
|
||||
converted.append(converted_item)
|
||||
else:
|
||||
converted.append(item)
|
||||
|
||||
return converted
|
||||
|
||||
async def run_sync(self, since_commit: str = "HEAD~1") -> Dict[str, List[str]]:
|
||||
"""Run the complete synchronization process"""
|
||||
print("=== Starting Documentation Synchronization ===")
|
||||
|
||||
# Get file changes
|
||||
changes = self.get_changed_files(since_commit)
|
||||
print(f"Detected changes: {changes}")
|
||||
|
||||
results = {
|
||||
"file_operations": [],
|
||||
"translations": [],
|
||||
"structure_sync": [],
|
||||
"errors": []
|
||||
}
|
||||
|
||||
try:
|
||||
# 1. Sync file operations (delete, rename)
|
||||
results["file_operations"] = self.sync_file_operations(changes)
|
||||
|
||||
# 2. Translate new and modified files
|
||||
results["translations"] = await self.translate_new_and_modified_files(changes)
|
||||
|
||||
# 3. Sync docs.json structure if needed
|
||||
if self.extract_english_structure_changes(changes):
|
||||
results["structure_sync"] = self.sync_docs_json_structure()
|
||||
|
||||
except Exception as e:
|
||||
results["errors"].append(f"CRITICAL: {e}")
|
||||
print(f"Critical error during sync: {e}")
|
||||
|
||||
print("=== Synchronization Complete ===")
|
||||
return results
|
||||
|
||||
async def main():
|
||||
"""Main entry point"""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python sync_and_translate.py <dify_api_key> [since_commit]")
|
||||
print(" since_commit: Git commit to compare against (default: HEAD~1)")
|
||||
sys.exit(1)
|
||||
|
||||
dify_api_key = sys.argv[1]
|
||||
since_commit = sys.argv[2] if len(sys.argv) > 2 else "HEAD~1"
|
||||
|
||||
# Initialize synchronizer
|
||||
synchronizer = DocsSynchronizer(dify_api_key)
|
||||
|
||||
# Run synchronization
|
||||
results = await synchronizer.run_sync(since_commit)
|
||||
|
||||
# Print results
|
||||
print("\n=== SYNCHRONIZATION RESULTS ===")
|
||||
for category, logs in results.items():
|
||||
if logs:
|
||||
print(f"\n{category.upper()}:")
|
||||
for log in logs:
|
||||
print(f" {log}")
|
||||
|
||||
# Return appropriate exit code
|
||||
if results["errors"]:
|
||||
sys.exit(1)
|
||||
else:
|
||||
print("\n✓ Synchronization completed successfully")
|
||||
sys.exit(0)
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
27
tools/translate/test_docs_sync.py
Normal file
27
tools/translate/test_docs_sync.py
Normal file
@@ -0,0 +1,27 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script for docs.json synchronization only"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
sys.path.append(os.path.dirname(__file__))
|
||||
|
||||
from sync_and_translate import DocsSynchronizer
|
||||
|
||||
def main():
|
||||
"""Test docs.json sync without API calls"""
|
||||
# Initialize synchronizer with dummy API key
|
||||
synchronizer = DocsSynchronizer("dummy-key")
|
||||
|
||||
print("=== Testing docs.json Structure Synchronization ===")
|
||||
|
||||
# Run only the docs.json sync
|
||||
results = synchronizer.sync_docs_json_structure()
|
||||
|
||||
print("\n=== SYNC RESULTS ===")
|
||||
for log in results:
|
||||
print(f" {log}")
|
||||
|
||||
print("\n✓ Test completed")
|
||||
|
||||
if __name__ == "__main__":
|
||||
main()
|
||||
58
tools/translate/test_faq_only.py
Normal file
58
tools/translate/test_faq_only.py
Normal file
@@ -0,0 +1,58 @@
|
||||
#!/usr/bin/env python3
|
||||
"""Test script for FAQ translation only"""
|
||||
|
||||
import sys
|
||||
import os
|
||||
import asyncio
|
||||
sys.path.append(os.path.dirname(__file__))
|
||||
|
||||
from sync_and_translate import DocsSynchronizer
|
||||
|
||||
async def main():
|
||||
"""Test FAQ translation only"""
|
||||
if len(sys.argv) < 2:
|
||||
print("Usage: python test_faq_only.py <dify_api_key>")
|
||||
sys.exit(1)
|
||||
|
||||
dify_api_key = sys.argv[1]
|
||||
synchronizer = DocsSynchronizer(dify_api_key)
|
||||
|
||||
print("=== Testing FAQ File Translation ===")
|
||||
|
||||
# Test translating just the FAQ file
|
||||
faq_file = "en/documentation/pages/getting-started/faq.mdx"
|
||||
|
||||
try:
|
||||
# Test Chinese translation
|
||||
print(f"\nTranslating {faq_file} to Chinese...")
|
||||
zh_result = await synchronizer.translate_file_with_notice(
|
||||
faq_file,
|
||||
"zh-hans/documentation/pages/getting-started/faq.mdx",
|
||||
"zh-hans"
|
||||
)
|
||||
print(f"Chinese result: {zh_result}")
|
||||
|
||||
# Test Japanese translation
|
||||
print(f"\nTranslating {faq_file} to Japanese...")
|
||||
ja_result = await synchronizer.translate_file_with_notice(
|
||||
faq_file,
|
||||
"ja-jp/documentation/pages/getting-started/faq.mdx",
|
||||
"ja-jp"
|
||||
)
|
||||
print(f"Japanese result: {ja_result}")
|
||||
|
||||
# Test docs.json sync
|
||||
print(f"\nTesting docs.json structure sync...")
|
||||
sync_results = synchronizer.sync_docs_json_structure()
|
||||
for result in sync_results:
|
||||
print(f" {result}")
|
||||
|
||||
print("\n✓ FAQ test completed")
|
||||
|
||||
except Exception as e:
|
||||
print(f"Error: {e}")
|
||||
import traceback
|
||||
traceback.print_exc()
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(main())
|
||||
311
tools/translate/test_sync.py
Normal file
311
tools/translate/test_sync.py
Normal file
@@ -0,0 +1,311 @@
|
||||
#!/usr/bin/env python3
|
||||
"""
|
||||
Test script for documentation sync functionality
|
||||
Simulates the Dify API for testing purposes
|
||||
"""
|
||||
|
||||
import asyncio
|
||||
import json
|
||||
import sys
|
||||
import os
|
||||
from pathlib import Path
|
||||
from unittest.mock import AsyncMock, patch
|
||||
|
||||
# Add the translate directory to the path
|
||||
sys.path.insert(0, str(Path(__file__).parent))
|
||||
|
||||
from sync_and_translate import DocsSynchronizer
|
||||
|
||||
# Mock translation responses
|
||||
MOCK_TRANSLATIONS = {
|
||||
"Chinese": """# 常见问题
|
||||
|
||||
欢迎来到 Dify 常见问题部分。在这里您可以找到关于使用 Dify 最常见问题的答案。
|
||||
|
||||
## 入门
|
||||
|
||||
### 什么是 Dify?
|
||||
|
||||
Dify 是一个开源的 AI 应用构建平台。它提供了一套全面的工具和功能,帮助您构建、部署和管理 AI 应用程序,无需大量编程知识。
|
||||
|
||||
### 如何开始使用 Dify?
|
||||
|
||||
开始使用 Dify:
|
||||
|
||||
1. **注册** Dify 账户,访问 [dify.ai](https://dify.ai)
|
||||
2. **创建您的第一个应用程序** 使用我们直观的界面
|
||||
3. **配置您的 AI 模型** 通过连接到 OpenAI、Anthropic 或其他提供商
|
||||
4. **测试和迭代** 您的应用程序
|
||||
5. **部署** 您的 AI 应用程序到生产环境
|
||||
|
||||
### 我可以用 Dify 构建什么类型的应用程序?
|
||||
|
||||
您可以使用 Dify 构建各种类型的 AI 应用程序:
|
||||
|
||||
- **聊天机器人** 用于客户服务
|
||||
- **知识库助手** 可以回答有关您文档的问题
|
||||
- **工作流自动化工具** 智能处理数据
|
||||
- **内容生成工具** 用于营销和写作
|
||||
- **AI 代理** 可以执行复杂任务
|
||||
|
||||
## 技术问题
|
||||
|
||||
### Dify 支持哪些 AI 模型?
|
||||
|
||||
Dify 支持广泛的 AI 模型,包括:
|
||||
|
||||
- **OpenAI 模型**: GPT-4、GPT-3.5 等
|
||||
- **Anthropic 模型**: Claude 3 和 Claude 2
|
||||
- **开源模型**: 通过 Hugging Face、Ollama 等提供商
|
||||
- **本地模型**: 您可以托管自己的模型
|
||||
|
||||
### Dify 如何处理我的数据?
|
||||
|
||||
数据安全和隐私是我们的首要任务:
|
||||
|
||||
- **您的数据仍然是您的** - 我们不会使用您的私人数据进行训练
|
||||
- **传输中和静态加密**
|
||||
- **企业客户的 SOC2 合规性**
|
||||
- **欧洲用户的 GDPR 合规性**
|
||||
|
||||
### 我可以将 Dify 用于商业目的吗?
|
||||
|
||||
是的!Dify 提供:
|
||||
|
||||
- **开源版本** 带有 Apache 2.0 许可证,用于自托管
|
||||
- **云版本** 带有托管托管的商业计划
|
||||
- **企业计划** 具有高级功能和支持
|
||||
|
||||
## 故障排除
|
||||
|
||||
### 我的 AI 应用程序给出了错误的响应
|
||||
|
||||
尝试这些故障排除步骤:
|
||||
|
||||
1. **检查您的提示** - 确保它清晰具体
|
||||
2. **检查您的知识库** - 确保上传了相关文档
|
||||
3. **调整模型参数** - 尝试不同的温度或 top-k 设置
|
||||
4. **使用不同的模型测试** - 某些模型更适合特定任务
|
||||
|
||||
### 我遇到了响应时间慢的问题
|
||||
|
||||
改善响应时间:
|
||||
|
||||
1. **检查您的模型配置** - 某些模型比其他模型更快
|
||||
2. **优化您的知识库** - 删除不必要的文档
|
||||
3. **使用缓存** - 为常见问题启用响应缓存
|
||||
4. **考虑升级** 您的计划以获得更好的性能
|
||||
|
||||
### 如何获得支持?
|
||||
|
||||
您可以通过以下方式获得支持:
|
||||
|
||||
- **社区论坛** - 与其他 Dify 用户联系
|
||||
- **文档** - 全面的指南和教程
|
||||
- **GitHub 问题** - 用于错误报告和功能请求
|
||||
- **电子邮件支持** - 适用于付费计划客户
|
||||
- **企业支持** - 为企业客户提供专门支持
|
||||
|
||||
## 计费和计划
|
||||
|
||||
### 不同的定价计划有哪些?
|
||||
|
||||
Dify 提供几种计划:
|
||||
|
||||
- **免费层** - 非常适合入门和小项目
|
||||
- **专业计划** - 适用于使用需求较高的成长型企业
|
||||
- **企业计划** - 为大型组织提供定制解决方案
|
||||
|
||||
### 如何计算使用量?
|
||||
|
||||
使用量通常基于以下因素计算:
|
||||
|
||||
- **API 调用** 到 AI 模型
|
||||
- **存储** 文档和数据
|
||||
- **活跃用户** 在您的应用程序上
|
||||
- **自定义功能** 取决于您的计划
|
||||
|
||||
有关详细的定价信息,请访问我们的 [定价页面](https://dify.ai/pricing)。
|
||||
|
||||
---
|
||||
|
||||
需要更多帮助?联系我们的支持团队或查看我们的 [综合文档](../../../guides/)。""",
|
||||
|
||||
"Japanese": """# よくある質問
|
||||
|
||||
Dify FAQ セクションへようこそ。ここでは、Dify の使用に関してよく寄せられる質問への回答を見つけることができます。
|
||||
|
||||
## はじめに
|
||||
|
||||
### Dify とは何ですか?
|
||||
|
||||
Dify は AI アプリケーションを構築するためのオープンソースプラットフォームです。広範なコーディング知識を必要とせずに、AI アプリケーションの構築、デプロイ、管理を支援する包括的なツールと機能セットを提供します。
|
||||
|
||||
### Dify を始めるにはどうすればよいですか?
|
||||
|
||||
Dify を開始するには:
|
||||
|
||||
1. [dify.ai](https://dify.ai) で Dify アカウントに **サインアップ** してください
|
||||
2. 直感的なインターフェースを使用して **最初のアプリケーションを作成** してください
|
||||
3. OpenAI、Anthropic、その他のプロバイダーに接続して **AI モデルを設定** してください
|
||||
4. アプリケーションを **テストし、反復** してください
|
||||
5. AI アプリケーションを本番環境に **デプロイ** してください
|
||||
|
||||
### Dify でどのようなタイプのアプリケーションを構築できますか?
|
||||
|
||||
Dify でさまざまなタイプの AI アプリケーションを構築できます:
|
||||
|
||||
- カスタマーサービス用の **チャットボット**
|
||||
- ドキュメントに関する質問に答えることができる **ナレッジベースアシスタント**
|
||||
- データを知的に処理する **ワークフロー自動化ツール**
|
||||
- マーケティングや執筆用の **コンテンツ生成ツール**
|
||||
- 複雑なタスクを実行できる **AI エージェント**
|
||||
|
||||
## 技術的な質問
|
||||
|
||||
### Dify はどの AI モデルをサポートしていますか?
|
||||
|
||||
Dify は幅広い AI モデルをサポートしています:
|
||||
|
||||
- **OpenAI モデル**: GPT-4、GPT-3.5 など
|
||||
- **Anthropic モデル**: Claude 3 と Claude 2
|
||||
- **オープンソースモデル**: Hugging Face、Ollama などのプロバイダー経由
|
||||
- **ローカルモデル**: 独自のモデルをホストできます
|
||||
|
||||
### Dify は私のデータをどのように処理しますか?
|
||||
|
||||
データセキュリティとプライバシーが最優先事項です:
|
||||
|
||||
- **あなたのデータはあなたのもの** - 私たちはあなたのプライベートデータでトレーニングしません
|
||||
- 転送中および保存時の **暗号化**
|
||||
- エンタープライズ顧客向けの **SOC2 コンプライアンス**
|
||||
- ヨーロッパユーザー向けの **GDPR コンプライアンス**
|
||||
|
||||
### Dify を商用目的で使用できますか?
|
||||
|
||||
はい!Dify は以下を提供しています:
|
||||
|
||||
- セルフホスティング用の Apache 2.0 ライセンス付き **オープンソース版**
|
||||
- マネージドホスティング用の商用プラン付き **クラウド版**
|
||||
- 高度な機能とサポート付き **エンタープライズプラン**
|
||||
|
||||
## トラブルシューティング
|
||||
|
||||
### AI アプリケーションが間違った回答をしています
|
||||
|
||||
これらのトラブルシューティング手順を試してください:
|
||||
|
||||
1. **プロンプトを確認** - 明確で具体的であることを確認してください
|
||||
2. **ナレッジベースを確認** - 関連するドキュメントがアップロードされていることを確認してください
|
||||
3. **モデルパラメータを調整** - 異なる温度や top-k 設定を試してください
|
||||
4. **異なるモデルでテスト** - 一部のモデルは特定のタスクにより適しています
|
||||
|
||||
### 応答時間が遅い問題が発生しています
|
||||
|
||||
応答時間を改善するには:
|
||||
|
||||
1. **モデル設定を確認** - 一部のモデルは他のモデルよりも高速です
|
||||
2. **ナレッジベースを最適化** - 不要なドキュメントを削除してください
|
||||
3. **キャッシュを使用** - よくある質問に対してレスポンスキャッシュを有効にしてください
|
||||
4. **プランのアップグレードを検討** - より良いパフォーマンスのために
|
||||
|
||||
### サポートを受けるにはどうすればよいですか?
|
||||
|
||||
以下の方法でサポートを受けることができます:
|
||||
|
||||
- **コミュニティフォーラム** - 他の Dify ユーザーとつながる
|
||||
- **ドキュメント** - 包括的なガイドとチュートリアル
|
||||
- **GitHub の課題** - バグレポートと機能リクエスト用
|
||||
- **メールサポート** - 有料プラン顧客向け
|
||||
- **エンタープライズサポート** - エンタープライズ顧客専用サポート
|
||||
|
||||
## 請求とプラン
|
||||
|
||||
### 異なる価格プランは何ですか?
|
||||
|
||||
Dify はいくつかのプランを提供しています:
|
||||
|
||||
- **無料ティア** - はじめと小さなプロジェクトに最適
|
||||
- **プロプラン** - より高い使用ニーズを持つ成長企業向け
|
||||
- **エンタープライズプラン** - 大規模組織向けのカスタムソリューション
|
||||
|
||||
### 使用量はどのように計算されますか?
|
||||
|
||||
使用量は通常以下に基づいて計算されます:
|
||||
|
||||
- AI モデルへの **API 呼び出し**
|
||||
- ドキュメントとデータの **ストレージ**
|
||||
- アプリケーションの **アクティブユーザー**
|
||||
- プランに応じた **カスタム機能**
|
||||
|
||||
詳細な価格情報については、[価格ページ](https://dify.ai/pricing) をご覧ください。
|
||||
|
||||
---
|
||||
|
||||
さらにヘルプが必要ですか?サポートチームにお問い合わせいただくか、[包括的なドキュメント](../../../guides/) をご確認ください。"""
|
||||
}
|
||||
|
||||
async def mock_translate_text(file_path, dify_api_key, original_language, target_language, termbase_path=None, max_retries=3):
|
||||
"""Mock translation function that returns predefined translations"""
|
||||
print(f"MOCK: Translating {file_path} from {original_language} to {target_language}")
|
||||
|
||||
# Simulate processing time
|
||||
await asyncio.sleep(0.5)
|
||||
|
||||
if target_language == "Chinese":
|
||||
return MOCK_TRANSLATIONS["Chinese"]
|
||||
elif target_language == "Japanese":
|
||||
return MOCK_TRANSLATIONS["Japanese"]
|
||||
else:
|
||||
return "Mock translation for " + target_language
|
||||
|
||||
async def test_sync_workflow():
|
||||
"""Test the synchronization workflow"""
|
||||
print("=== Testing Documentation Sync Workflow ===")
|
||||
|
||||
# Create a mock API key
|
||||
mock_api_key = "test_api_key_12345"
|
||||
|
||||
# Patch the translate_text function
|
||||
with patch('sync_and_translate.translate_text', side_effect=mock_translate_text):
|
||||
# Initialize synchronizer
|
||||
synchronizer = DocsSynchronizer(mock_api_key)
|
||||
|
||||
# Test the sync process with git changes
|
||||
print("\n1. Testing change detection...")
|
||||
changes = synchronizer.get_changed_files("HEAD~1")
|
||||
print(f"Detected changes: {changes}")
|
||||
|
||||
# Test file operations
|
||||
print("\n2. Testing file operations...")
|
||||
file_ops = synchronizer.sync_file_operations(changes)
|
||||
for op in file_ops:
|
||||
print(f" {op}")
|
||||
|
||||
# Test translation (this will actually create files)
|
||||
print("\n3. Testing translation process...")
|
||||
translations = await synchronizer.translate_new_and_modified_files(changes)
|
||||
for trans in translations:
|
||||
print(f" {trans}")
|
||||
|
||||
# Test docs.json structure sync
|
||||
print("\n4. Testing docs.json structure sync...")
|
||||
structure_sync = synchronizer.sync_docs_json_structure()
|
||||
for sync in structure_sync:
|
||||
print(f" {sync}")
|
||||
|
||||
# Run full sync
|
||||
print("\n5. Running full synchronization...")
|
||||
results = await synchronizer.run_sync("HEAD~1")
|
||||
|
||||
print("\n=== FINAL RESULTS ===")
|
||||
for category, logs in results.items():
|
||||
if logs:
|
||||
print(f"\n{category.upper()}:")
|
||||
for log in logs:
|
||||
print(f" {log}")
|
||||
|
||||
print("\n=== Test Complete ===")
|
||||
|
||||
if __name__ == "__main__":
|
||||
asyncio.run(test_sync_workflow())
|
||||
104
zh-hans/documentation/pages/build/additional-features.mdx
Normal file
104
zh-hans/documentation/pages/build/additional-features.mdx
Normal file
@@ -0,0 +1,104 @@
|
||||
> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版](../../../../en/documentation/pages/build/additional-features.mdx)。
|
||||
|
||||
---
|
||||
title: "附加功能"
|
||||
icon: "circle-plus"
|
||||
---
|
||||
|
||||
添加功能,让你的应用更加实用。点击右上角的 **功能** 来添加功能。
|
||||
|
||||
<iframe
|
||||
src="https://www.motionshot.app/walkthrough/6773d34ad27e58127b913945/embed?fullscreen=1&hideAsSteps=1&hideCopy=1&hideDownload=1&hideSteps=1"
|
||||
width="100%"
|
||||
height="400px"
|
||||
frameborder="0"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
|
||||
## 工作流应用
|
||||
|
||||
<Info>
|
||||
对于工作流应用,通过“功能”上传文件的方式已被弃用。请改用[开始节点上的文件变量](/zh/guides/workflow/node/start)。
|
||||
</Info>
|
||||
|
||||
工作流应用仅通过“功能”支持**图片上传**:
|
||||
|
||||
<iframe
|
||||
src="https://www.motionshot.app/walkthrough/6773d3d86a0c3ed534f24da9/embed?fullscreen=1&hideAsSteps=1&hideCopy=1&hideDownload=1&hideSteps=1"
|
||||
width="100%"
|
||||
height="400px"
|
||||
frameborder="0"
|
||||
allowfullscreen
|
||||
></iframe>
|
||||
|
||||
**如何设置:**
|
||||
1. 在“功能”中启用图片上传
|
||||
2. 添加具备视觉能力的 LLM 节点
|
||||
3. 启用 VISION 并选择 `sys.files` 变量
|
||||
4. 连接到结束节点
|
||||
|
||||
## 对话流应用
|
||||
|
||||
对话流应用支持更多功能:
|
||||
|
||||
- **对话开场白** - AI 会先打招呼
|
||||
- **后续问题建议** - 在每次回复后建议下一个问题
|
||||
- **文本转语音** - 朗读回复内容(需要在模型供应商中设置 TTS)
|
||||
- **文件上传** - 用户可以上传文件
|
||||
- **引用** - 在使用知识检索时显示信息来源
|
||||
- **内容审查** - 过滤不当内容
|
||||
|
||||
## 文件上传
|
||||
|
||||
大多数功能启用后即可自动生效。文件上传需要进行更多设置。
|
||||
|
||||
**对于用户**:点击回形针图标上传文件
|
||||
|
||||

|
||||
|
||||
**对于开发者**:文件会出现在 `sys.files` 变量中。不同文件类型需要不同的处理方式:
|
||||
|
||||
### 文档
|
||||
|
||||
大型语言模型无法直接读取文件。请先使用“文档提取器”。
|
||||
|
||||
1. 在文件类型中启用“文档”
|
||||
2. 添加“文档提取器”节点,并以 `sys.files` 作为输入
|
||||
3. 添加 LLM 节点,使用文档提取器的输出
|
||||
4. 添加“回答”节点,使用 LLM 的输出
|
||||
|
||||
<Warning>
|
||||
此方式不会在多次对话中记住文件。用户每次都需要重新上传。对于持久化文件,请使用[开始节点的文件变量](/zh/guides/workflow/node/start)。
|
||||
</Warning>
|
||||
|
||||
### 图片
|
||||
|
||||
一些大型语言模型可以直接分析图片。
|
||||
|
||||
1. 在文件类型中启用“图片”
|
||||
2. 添加启用了 VISION 的 LLM 节点
|
||||
3. 选择 `sys.files` 变量
|
||||
4. 添加“回答”节点,使用 LLM 的输出
|
||||
|
||||

|
||||
|
||||
### 混合文件类型
|
||||
|
||||
同时处理文档和图片:
|
||||
|
||||
1. 同时启用“图片”和“文档”
|
||||
2. 添加两个“列表操作”节点以筛选文件类型
|
||||
3. 将图片发送到具备视觉能力的 LLM
|
||||
4. 将文档发送到“文档提取器”
|
||||
5. 在“回答”节点中合并结果
|
||||
|
||||

|
||||
|
||||
### 音频和视频
|
||||
|
||||
大型语言模型无法直接处理这些文件。你需要使用[外部工具](/zh/guides/extension/api-based-extension/external-data-tool)来处理音频/视频。
|
||||
|
||||
## 限制
|
||||
|
||||
- 每个文件最大 15MB
|
||||
- 一次最多 10 个文件
|
||||
36
zh-hans/documentation/pages/build/orchestrate-node.mdx
Normal file
36
zh-hans/documentation/pages/build/orchestrate-node.mdx
Normal file
@@ -0,0 +1,36 @@
|
||||
> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版](../../../../en/documentation/pages/build/orchestrate-node.mdx)。
|
||||
|
||||
---
|
||||
title: "流逻辑"
|
||||
icon: "diagram-project"
|
||||
---
|
||||
|
||||
节点的执行方式取决于您如何连接它们。
|
||||
|
||||

|
||||
|
||||
## 串行执行
|
||||
|
||||
当您将节点一个接一个地连接时,它们会按顺序执行。每个节点都会等待前一个节点完成后才开始。
|
||||
|
||||

|
||||
|
||||
每个节点都可以使用链中在其之前运行的任何节点的变量。
|
||||
|
||||
## 并行执行
|
||||
|
||||
当您将多个节点连接到同一个起始节点时,它们会同时运行。
|
||||
|
||||

|
||||
|
||||
<Note>
|
||||
一个节点最多可以有 10 个并行分支,并且最多支持 3 层嵌套的并行结构。
|
||||
</Note>
|
||||
|
||||
## 变量访问
|
||||
|
||||
在串行流中,节点可以访问链中任何先前节点的变量。
|
||||
|
||||
在并行流中,节点可以访问并行分支开始前运行的节点的变量,但无法访问其他并行节点的变量,因为它们是同时运行的。
|
||||
|
||||
并行分支完成后,下游节点可以访问所有并行分支的输出变量。
|
||||
150
zh-hans/documentation/pages/build/shortcut-key.mdx
Normal file
150
zh-hans/documentation/pages/build/shortcut-key.mdx
Normal file
@@ -0,0 +1,150 @@
|
||||
> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版](../../../../en/documentation/pages/build/shortcut-key.mdx)。
|
||||
|
||||
---
|
||||
title: "快捷键"
|
||||
icon: "keyboard"
|
||||
---
|
||||
|
||||
使用键盘快捷键加快你的工作流构建速度。
|
||||
|
||||
## 节点操作
|
||||
在画布上选中任意节点后:
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Windows</th>
|
||||
<th>macOS</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>C</code></td>
|
||||
<td><code>Cmd</code> + <code>C</code></td>
|
||||
<td>复制节点</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>V</code></td>
|
||||
<td><code>Cmd</code> + <code>V</code></td>
|
||||
<td>粘贴节点</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>D</code></td>
|
||||
<td><code>Cmd</code> + <code>D</code></td>
|
||||
<td>创建副本</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Delete</code></td>
|
||||
<td><code>Delete</code></td>
|
||||
<td>删除所选节点</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>O</code></td>
|
||||
<td><code>Cmd</code> + <code>O</code></td>
|
||||
<td>自动排列节点</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Shift</code></td>
|
||||
<td><code>Shift</code></td>
|
||||
<td>可视化变量依赖关系(仅限单个节点)</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 画布导航
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Windows</th>
|
||||
<th>macOS</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>1</code></td>
|
||||
<td><code>Cmd</code> + <code>1</code></td>
|
||||
<td>适应视图</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>-</code></td>
|
||||
<td><code>Cmd</code> + <code>-</code></td>
|
||||
<td>缩小</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>=</code></td>
|
||||
<td><code>Cmd</code> + <code>=</code></td>
|
||||
<td>放大</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Shift</code> + <code>1</code></td>
|
||||
<td><code>Shift</code> + <code>1</code></td>
|
||||
<td>重置为 100%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Shift</code> + <code>5</code></td>
|
||||
<td><code>Shift</code> + <code>5</code></td>
|
||||
<td>设置为 50%</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>H</code></td>
|
||||
<td><code>H</code></td>
|
||||
<td>抓手工具(平移)</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>V</code></td>
|
||||
<td><code>V</code></td>
|
||||
<td>选择工具</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 历史记录
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Windows</th>
|
||||
<th>macOS</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>Z</code></td>
|
||||
<td><code>Cmd</code> + <code>Z</code></td>
|
||||
<td>撤销</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>Y</code></td>
|
||||
<td><code>Cmd</code> + <code>Y</code></td>
|
||||
<td>重做</td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td><code>Ctrl</code> + <code>Shift</code> + <code>Z</code></td>
|
||||
<td><code>Cmd</code> + <code>Shift</code> + <code>Z</code></td>
|
||||
<td>重做</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
## 测试
|
||||
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th>Windows</th>
|
||||
<th>macOS</th>
|
||||
<th>操作</th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr>
|
||||
<td><code>Alt</code> + <code>R</code></td>
|
||||
<td><code>Option</code> + <code>R</code></td>
|
||||
<td>运行工作流</td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
103
zh-hans/documentation/pages/build/version-control.mdx
Normal file
103
zh-hans/documentation/pages/build/version-control.mdx
Normal file
@@ -0,0 +1,103 @@
|
||||
> ⚠️ 本文档由 AI 自动翻译。如有任何不准确之处,请参考[英文原版](../../../../en/documentation/pages/build/version-control.mdx)。
|
||||
|
||||
---
|
||||
title: "版本控制"
|
||||
icon: "layer-group"
|
||||
---
|
||||
|
||||
在对话流和工作流应用中跟踪变更并管理版本。
|
||||
|
||||
<Info>
|
||||
目前仅适用于对话流和工作流应用。
|
||||
</Info>
|
||||
|
||||
## 工作原理
|
||||
|
||||
**当前草稿**:你的工作版本。你可以在这里进行更改。此版本不会对用户生效。
|
||||
|
||||

|
||||
|
||||
**最新版本**:用户看到的线上版本。
|
||||
|
||||

|
||||
|
||||
**过往版本**:已发布的旧版本。
|
||||
|
||||

|
||||
|
||||
## 发布版本
|
||||
|
||||
点击 **发布** → **发布更新** 以将你的草稿上线。
|
||||
|
||||

|
||||
|
||||
你的草稿将成为新的最新版本,同时你会得到一个新的草稿用于后续工作。
|
||||
|
||||

|
||||
|
||||
## 查看版本
|
||||
|
||||
点击历史记录图标查看所有版本:
|
||||
|
||||

|
||||
|
||||
筛选条件:
|
||||
- **所有版本** 或 **仅自己创建的**
|
||||
- **仅已命名的版本**(跳过自动生成的名称)
|
||||
|
||||

|
||||
|
||||
## 管理版本
|
||||
|
||||
**命名版本**:为其指定一个正式名称,以替代自动生成的名称
|
||||
|
||||

|
||||
|
||||
**编辑版本信息**:更改名称并添加发布说明
|
||||
|
||||

|
||||
|
||||
**删除旧版本**:清理不再需要的版本
|
||||
|
||||

|
||||
|
||||
<Warning>
|
||||
你不能删除当前草稿或最新版本。
|
||||
</Warning>
|
||||
|
||||
**恢复版本**:将旧版本加载回你的草稿中
|
||||
|
||||

|
||||
|
||||
<Warning>
|
||||
此操作会完全替换你当前的草稿。请确保没有未保存的工作。
|
||||
</Warning>
|
||||
|
||||
## 示例工作流
|
||||
|
||||
以下是版本在典型开发周期中的工作方式:
|
||||
|
||||
### 1. 从草稿开始
|
||||

|
||||
|
||||
### 2. 发布第一个版本
|
||||

|
||||
|
||||
### 3. 发布第二个版本
|
||||

|
||||
|
||||
### 4. 将旧版本恢复至草稿
|
||||

|
||||
|
||||
### 5. 发布恢复后的版本
|
||||

|
||||
|
||||
完整演示:
|
||||

|
||||
|
||||
## 提示
|
||||
|
||||
- 发布前务必在草稿中进行测试
|
||||
- 为重要版本使用描述性的版本名称
|
||||
- 当需要快速回滚时,恢复旧版本
|
||||
- 保留旧版本以供参考
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user