Custom Skills in Skillsets
Complete the full lesson to earn 25 points
Work through each section, then tap “Mark as Complete” on the last one.
✦ Skip the page breaks and see fewer ads — read each lesson on a single page with Pro
Mastering Custom Skills in Azure AI Search
Introduction: Bridging the Gap in Information Extraction
In the modern enterprise, data is rarely uniform. While Azure AI Search provides a powerful suite of built-in capabilities—such as Optical Character Recognition (OCR), entity recognition, and language detection—these pre-built tools often fall short when dealing with highly specialized domain knowledge. Whether you are dealing with proprietary legal contracts, medical charts with unique shorthand, or technical manuals containing custom hardware identifiers, the standard "off-the-shelf" models may fail to extract the specific data points your business needs to function.
This is where Custom Skills come into play. A Custom Skill is essentially a user-defined operation that you plug into the Azure AI Search indexing pipeline. By creating a custom skill, you extend the enrichment process to include your own code, external APIs, or machine learning models. This capability turns a standard search indexer into a sophisticated knowledge mining engine capable of processing unstructured data into highly structured, actionable intelligence. Understanding how to build, deploy, and manage these skills is critical for any data engineer or architect looking to unlock the true value of their organization's document repositories.
Understanding the Skillset Architecture
To grasp how custom skills work, we must first understand the concept of a "Skillset." A skillset is a reusable resource in Azure AI Search that defines a sequence of enrichment steps. When an indexer runs, it pulls documents from your data source, cracks them open to extract text or images, and then passes that content through the skillset.
Each step in the skillset is called a "Skill." Skills take input from the document (or from the output of a previous skill) and produce an output that can be mapped to fields in your search index. Custom skills differ from built-in skills because they rely on your own logic, usually hosted via an Azure Function or a similar compute resource.
The Anatomy of a Custom Skill
At its core, a custom skill is an HTTP-based interface. Azure AI Search sends a JSON payload to your endpoint, and your endpoint must return a JSON response containing the enriched data. This simple request-response contract is the foundation for all custom extensions. Because it is HTTP-based, you are not restricted by language or platform; you can write your custom skill in Python, C#, Node.js, or any other language that supports web services.
Callout: Built-in vs. Custom Skills It is important to distinguish between the two. Built-in skills are managed, pre-configured, and maintained by Microsoft. They are easier to implement but lack flexibility. Custom skills offer total control over logic, allowing you to integrate proprietary algorithms, external databases, or specialized AI models. If you need to perform a lookup in your own SQL database or run a specific regex pattern on a document, a custom skill is your only choice.
Designing Your First Custom Skill
Before writing code, you need a clear definition of what your skill will do. Let's imagine a scenario where we have a collection of invoices. The built-in skills can extract text, but they might not recognize your company's specific "Internal Project Code" format. You decide to build a custom skill that uses a regular expression to identify and extract these codes from the invoice text.
Step 1: Defining the Input/Output Schema
Your custom skill must conform to the expected Azure AI Search schema. The input is a JSON object containing a values array, where each item represents a document or a chunk of a document. Your output must also be a JSON object containing a values array, matching the input structure.
Step 2: Developing the Logic
If you are using an Azure Function, you will create an HTTP Trigger. The function will receive the request, iterate through the values array, apply your logic to each record, and construct the response.
Here is an example of what that logic looks like in Python:
import azure.functions as func
import json
import re
def main(req: func.HttpRequest) -> func.HttpResponse:
try:
body = json.loads(req.get_body())
values = body.get("values", [])
results = {"values": []}
for value in values:
record_id = value.get("recordId")
text = value.get("data", {}).get("text", "")
# Logic: Find project codes starting with 'PRJ-' followed by 4 digits
matches = re.findall(r'PRJ-\d{4}', text)
results["values"].append({
"recordId": record_id,
"data": {
"project_codes": matches
}
})
return func.HttpResponse(json.dumps(results), mimetype="application/json")
except Exception as e:
return func.HttpResponse(str(e), status_code=500)
Step 3: Configuring the Skillset
Once your code is deployed to an Azure Function, you must tell Azure AI Search about it. You do this by adding a WebApiSkill to your skillset definition.
{
"@odata.type": "#Microsoft.Skills.Custom.WebApiSkill",
"name": "ProjectCodeExtractor",
"description": "Extracts internal project codes from text",
"uri": "https://your-function-app.azurewebsites.net/api/ExtractCodes",
"httpMethod": "POST",
"timeout": "PT30S",
"batchSize": 10,
"inputs": [
{ "name": "text", "source": "/document/content" }
],
"outputs": [
{ "name": "project_codes", "targetName": "project_codes" }
]
}
Best Practices for Custom Skill Development
Building custom skills is powerful, but it introduces complexity. To ensure your search indexer remains performant and reliable, follow these industry-standard practices.
1. Optimize for Batching
Azure AI Search sends documents in batches to your custom skill. Your code should be written to handle multiple records in a single request. If your skill processes records one by one, you will incur significant latency and overhead. Always iterate through the values array provided in the request body.
2. Implement Proper Error Handling
If your skill fails, the entire indexing process for that document (or batch) may fail. You should wrap your logic in try-except blocks. If a specific record fails, return a partial success response with an error message in the errors or warnings field of the response object. This allows the indexer to continue processing other documents rather than halting entirely.
3. Handle Timeouts Gracefully
Azure AI Search has a default timeout for skill execution. If your custom skill involves complex machine learning inference or long-running database lookups, you may hit this limit. Optimize your code to run quickly, or consider breaking complex tasks into multiple sequential skills.
Note: Always set the
timeoutparameter in yourWebApiSkilldefinition to be slightly less than the timeout of the underlying Azure Function to ensure you receive a meaningful error message instead of a generic gateway timeout.
4. Secure Your Endpoints
Since your custom skill is exposed via an HTTP endpoint, it is vulnerable to unauthorized access. Always use API keys or Azure Active Directory (Managed Identity) to secure your function. Azure AI Search supports passing an API key in the header, which is the standard way to ensure only your search service can trigger the skill.
Common Pitfalls and Troubleshooting
Even experienced engineers run into issues when integrating custom skills. Here are the most frequent mistakes and how to avoid them.
Incorrect JSON Schema
The most common error is returning a JSON structure that does not match the expected format. The response must contain a values array, and each object inside must have a recordId that matches the input recordId. If the IDs do not match, the indexer will fail to correlate the enriched data with the original document.
Over-processing Data
Sometimes developers try to do too much in a single custom skill. If you find your skill is becoming a monolithic block of code that does entity extraction, translation, and database lookups, it is time to refactor. Split these into separate skills in the skillset. This makes debugging easier and allows you to reuse individual components across different skillsets.
Ignoring Throughput Limits
If you are running a large-scale indexing job, your custom skill might become a bottleneck. If your Azure Function is configured with a low plan (like a Consumption plan), it might not have enough concurrency to handle the volume of requests from the indexer. Use the Azure Portal to monitor your function's performance and scale out your compute resources accordingly.
Callout: Monitoring and Debugging Always enable Application Insights for your Azure Functions. It provides a detailed view of the request flow, execution time, and any exceptions thrown by your code. When a document fails to index, the first place you should look is the Application Insights logs for your custom skill.
Comparison: Custom Skill Hosting Options
When deciding where to host your custom skill, consider the following table:
| Hosting Option | Pros | Cons |
|---|---|---|
| Azure Functions | Serverless, cost-effective, easy to scale | Cold start latency, limited execution time |
| Azure Container Apps | Highly scalable, supports custom libraries | Requires container management |
| Azure App Service | Consistent performance, always-on | Higher cost, manual scaling |
Step-by-Step Implementation Workflow
To ensure a successful deployment, follow this structured process:
- Draft the Logic Locally: Build your logic in a local development environment (VS Code is excellent for this). Use sample JSON payloads to verify that your function correctly processes the input and returns the expected output.
- Deploy to a Staging Environment: Never deploy directly to production. Use a separate Azure Function app to test the integration with the Azure AI Search indexer.
- Configure the Skillset: Use the Azure AI Search REST API or the SDK to update your skillset. Ensure the
uripoints to your function's production endpoint. - Run a Small Batch Test: Trigger the indexer for a small subset of documents (e.g., 5-10 files). Verify that the output fields appear in your search index correctly.
- Monitor Logs: Keep Application Insights open during the initial run to catch any serialization errors or timeouts.
- Scale Up: Once the test run is successful, trigger the indexer for your full dataset. Monitor the function's CPU and memory usage to ensure it handles the load.
Advanced Concepts: Asynchronous Custom Skills
In some scenarios, your custom skill might take several minutes to run—for example, if it is calling a third-party AI service or performing a deep analysis of a massive document. For these cases, you can use the asynchronous custom skill pattern.
In this pattern, Azure AI Search makes an initial request to your skill. Your skill returns an "Accepted" status (HTTP 202) along with a URI that the indexer can poll. The indexer will then periodically check that URI until the skill returns the final results. This is a more complex implementation but is necessary for long-running processes that would otherwise time out.
Best Practices for Data Privacy and Security
When processing documents, you are often handling sensitive information. Ensure that your custom skill complies with your organization's data protection policies.
- Encryption at Rest and in Transit: Ensure your Azure Function uses HTTPS and that the communication between the search service and the function is encrypted.
- Data Minimization: Do not pass the entire document to your custom skill if you only need a specific section. Extract only what is necessary to reduce the payload size and potential exposure.
- Identity-Based Access: Use Managed Identities whenever possible to grant your Azure AI Search service access to your function, rather than relying on shared secrets or API keys that can be leaked.
Practical Example: Integrating a Translation Service
Imagine you have a document store containing reports in multiple languages. You want to extract key terms and translate them into English. You can create a custom skill that calls an external translation API.
# Pseudo-code for a translation skill
def translate_text(text, target_language):
# Call an external translation service
response = requests.post(TRANSLATION_API_URL, json={"text": text, "lang": target_language})
return response.json()['translated_text']
# Your main function would iterate through records,
# call translate_text, and return the result in the JSON response.
By chaining this skill with a built-in "Key Phrase Extraction" skill, you can first translate the document and then extract the key phrases in English. This demonstrates the power of combining built-in and custom skills into a cohesive pipeline.
Managing Skill Versioning
As your requirements evolve, you may need to update your custom skills. Versioning is crucial to avoid breaking existing indexes.
- Endpoint Versioning: Include a version number in your function URL (e.g.,
/api/v1/ExtractCodes). When you need to make a breaking change, create a new endpoint (e.g.,/api/v2/ExtractCodes). - Skillset Versioning: Keep your skillset definitions in source control (like GitHub or Azure DevOps). This allows you to roll back to a previous configuration if a new custom skill deployment causes unexpected issues.
- Parallel Deployment: During a migration, you can have two versions of the skill running simultaneously for different indexes, ensuring a transition without downtime.
Handling Large Documents
One common challenge is the "token limit." Many AI models have a maximum number of tokens they can process at once. If your document is very long, a single custom skill call might fail.
To handle this, implement a "chunking" strategy. Before passing text to your custom skill, use a text-splitting skill or a pre-processing step to break the document into smaller, manageable chunks. Your custom skill can then process these chunks independently, and you can aggregate the results afterward.
Troubleshooting Checklist
If you find that your custom skill is not working, work through this list:
- Check the Indexer Status: Go to the Azure Portal and check the "Indexer" status. It will often give you a specific error message if a skill fails.
- Verify Inputs: Ensure that the input fields mapped in the skillset actually exist in the source document.
- Check Output Mapping: Ensure the output names in your skill match the
targetNamein the skillset definition. - Test the Endpoint Independently: Use a tool like Postman to send a POST request to your function with a sample JSON payload to ensure it behaves as expected.
- Review Function Logs: Check the "Invocations" tab in your Azure Function to see if your code is hitting any unhandled exceptions.
- Verify Authentication: Confirm that the API key or Managed Identity configuration is correct and that the search service has permission to execute the function.
The Role of Custom Skills in Knowledge Mining
Knowledge mining is about transforming raw data into a structured knowledge graph. Custom skills are the "connective tissue" in this process. They allow you to define the specific logic that characterizes your domain. Without them, you are limited to generic extraction. With them, you can build a system that understands the nuances of your business, recognizes your unique terminology, and extracts the specific data points that drive your decision-making.
Whether you are extracting sentiment from customer feedback, identifying risk factors in legal documents, or categorizing technical support tickets, the custom skill architecture provides the necessary flexibility to adapt to any challenge. By mastering this component of Azure AI Search, you move from simply "searching" your data to "understanding" it at scale.
Key Takeaways
- Flexibility is Key: Custom skills allow you to extend Azure AI Search beyond its built-in capabilities, enabling the extraction of domain-specific data that off-the-shelf models would miss.
- HTTP Contract: A custom skill is just an HTTP-based service. As long as your code accepts the standard JSON
valuesarray and returns a response in the same format, it can be integrated into the pipeline. - Performance Matters: Always design your custom skills to handle batch requests. Avoid processing one record at a time to keep your indexing jobs fast and cost-effective.
- Resilience through Error Handling: Always wrap your code in robust error-handling logic. A single failed document should not crash your entire indexing process.
- Security First: Protect your custom skill endpoints using API keys or Managed Identities. Treat these endpoints as production-grade services that require monitoring and access control.
- Iterative Development: Start with a small, focused skill, test it locally with sample data, and only then deploy it to your search pipeline. Use staging environments to validate changes before pushing to production.
- Monitoring is Non-Negotiable: Use Application Insights to keep an eye on your skills. If a search indexer starts failing, the logs in your function app are usually where the answer lies.
Frequently Asked Questions (FAQ)
Q: Can I use a programming language other than Python or C#? A: Yes. Because the interface is based on HTTP and JSON, you can use any language (Node.js, Java, Go, etc.) as long as it can host an HTTP endpoint.
Q: Will custom skills slow down my indexing process? A: They can, especially if the skill involves heavy computation or external API calls. You can mitigate this by using asynchronous patterns, scaling your compute resources, or optimizing your code for performance.
Q: How do I update a custom skill without interrupting the search service?
A: Use versioned endpoints (e.g., /api/v2/myskill). Update the skillset definition to point to the new version only after you have verified that the new version works correctly.
Q: Is there a limit to how many custom skills I can have in a single skillset? A: While there is no hard limit, each skill adds complexity and potential points of failure. Keep your skillsets modular and focused to make them easier to manage and debug.
Q: Can a custom skill call another custom skill? A: Yes, you can chain skills in a skillset by using the output of one as the input for the next. This is a common pattern for complex enrichment pipelines.
Enjoying the courses?
Everything stays free. Pro shows fewer ads, doubles your daily points limit so you progress twice as fast, and lets you read each lesson on one page.
- ✓ Fewer advertisements
- ✓ 2× daily points limit
- ✓ Distraction-free lessons