Skip to content

Commit 0c8ad50

Browse files
committed
AI agent
1 parent 054cce3 commit 0c8ad50

27 files changed

Lines changed: 2280 additions & 0 deletions
Lines changed: 97 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,97 @@
1+
# AI Agent Coding Test: Dynamsoft Barcode Reader SDK
2+
3+
A comprehensive experiment testing multiple AI coding agents' ability to generate accurate, up-to-date code for the Dynamsoft Barcode Reader Python SDK.
4+
5+
## Project Overview
6+
7+
This project documents an experiment comparing six major AI coding agents using a single prompt:
8+
9+
> **"Create a command line barcode scanner in Python using the Dynamsoft Barcode Reader SDK"**
10+
11+
### Tested AI Agents
12+
13+
1. **Claude Sonnet 4**
14+
2. **Claude Sonnet 4.5** ✅ (Only agent with correct code initially)
15+
3. **Gemini 2.5 Pro**
16+
4. **GPT-5**
17+
5. **GPT-5 Codex**
18+
6. **Grok Code**
19+
20+
## Key Findings
21+
22+
### The Problem
23+
24+
Out of six AI agents tested, only **Claude Sonnet 4.5** generated code using the **latest version** of the Dynamsoft Barcode Reader SDK. The other five agents produced code based on the outdated `dbr` package instead of the current `dynamsoft-barcode-reader-bundle`.
25+
26+
### The Solution
27+
28+
By creating a **custom agent definition** in `.github/agents/python-barcode-scanner.agent.md`, we achieved:
29+
30+
- **100% success rate** across all AI agents
31+
- All agents now fetch latest documentation before coding
32+
- Consistent, accurate code generation
33+
- Up-to-date API usage
34+
35+
## Results Comparison
36+
37+
### Before Custom Agent
38+
39+
| AI Agent | Package Used | Result |
40+
|----------|--------------|--------|
41+
| Claude Sonnet 4 | `dbr` (outdated) | ❌ Failed |
42+
| Claude Sonnet 4.5 | `dynamsoft-barcode-reader-bundle` | ✅ Success |
43+
| Gemini 2.5 Pro | `dbr` (outdated) | ❌ Failed |
44+
| GPT-5 | `dbr` (outdated) | ❌ Failed |
45+
| GPT-5 Codex | `dbr` (outdated) | ❌ Failed |
46+
| Grok Code | `dbr` (outdated) | ❌ Failed |
47+
48+
### After Custom Agent
49+
50+
| AI Agent | Package Used | Result |
51+
|----------|--------------|--------|
52+
| All Agents | `dynamsoft-barcode-reader-bundle` | ✅ Success |
53+
54+
**Achievement: 100% success rate!**
55+
56+
## The Custom Agent Solution
57+
58+
The custom agent definition includes:
59+
60+
### Key Components
61+
62+
1. **Tool Specifications**: Forces agents to use `fetch`, `githubRepo`, `search`, and `edit` tools
63+
2. **Golden Rules**: Explicit instructions to:
64+
- Always use the latest package (`dynamsoft-barcode-reader-bundle`)
65+
- Fetch documentation before generating code
66+
- Trust documentation over training data
67+
- Create actual code files, not just snippets
68+
69+
3. **Documentation URLs**: Direct links to:
70+
- Official Python SDK documentation
71+
- User guide and API reference
72+
- GitHub sample repositories
73+
74+
### Example Custom Agent Structure
75+
76+
```markdown
77+
````chatagent
78+
---
79+
description: 'Python helper for Dynamsoft Barcode Reader that always checks the latest docs'
80+
tools:
81+
- fetch # read web pages for latest docs
82+
- githubRepo # search Dynamsoft sample repos
83+
- search # workspace/code search
84+
- edit # edit files in the workspace
85+
---
86+
87+
# Role
88+
You are an expert Python assistant for the Dynamsoft Barcode Reader SDK.
89+
90+
## Golden rules
91+
1. **Always use latest Python package**: `dynamsoft-barcode-reader-bundle`
92+
2. **Always check documentation first**: Use fetch tool before coding
93+
3. **Trust the docs**: If docs conflict with training data, follow docs
94+
4. **Create actual files**: Generate complete, runnable scripts
95+
````
96+
```
97+
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
# Command-Line Barcode Scanner
2+
3+
A Python command-line application for scanning barcodes from images using the Dynamsoft Barcode Reader SDK.
4+
5+
## Features
6+
7+
- Scan barcodes from a single image file
8+
- Batch scan multiple images from a directory
9+
- Supports various barcode formats (QR Code, Code 39, Code 128, EAN, UPC, DataMatrix, PDF417, and more)
10+
- Simple command-line interface
11+
12+
## Prerequisites
13+
14+
- Python 3.8 or higher
15+
- Internet connection (for license validation on first use)
16+
17+
## Installation
18+
19+
1. Install the Dynamsoft Barcode Reader SDK:
20+
21+
```bash
22+
pip install dynamsoft-barcode-reader-bundle
23+
```
24+
25+
2. Clone or download this repository
26+
27+
## Usage
28+
29+
### Scan a Single Image
30+
31+
```bash
32+
python barcode_scanner.py <image_path>
33+
```
34+
35+
Example:
36+
```bash
37+
python barcode_scanner.py barcode.jpg
38+
```
39+
40+
### Scan All Images in a Directory
41+
42+
```bash
43+
python barcode_scanner.py --dir <directory_path>
44+
```
45+
46+
Example:
47+
```bash
48+
python barcode_scanner.py --dir ./images
49+
```
50+
51+
### Help
52+
53+
```bash
54+
python barcode_scanner.py --help
55+
```
56+
57+
## License
58+
59+
This application uses a public trial license that requires a network connection. The license key is embedded in the code: `DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9`
60+
61+
For production use or offline applications, you can request a 30-day free trial license from the [Dynamsoft Customer Portal](https://www.dynamsoft.com/customer/license/trialLicense?product=dbr&package=python).
62+
63+
## Output Format
64+
65+
The scanner will display:
66+
- Number of barcodes detected
67+
- Barcode format (e.g., QR_CODE, CODE_128, EAN_13)
68+
- Decoded text content
69+
70+
Example output:
71+
```
72+
Scanning barcode from: barcode.jpg
73+
74+
✓ Decoded 2 barcode(s):
75+
76+
Result 1:
77+
Format: QR_CODE
78+
Text: https://www.dynamsoft.com
79+
80+
Result 2:
81+
Format: CODE_128
82+
Text: 1234567890
83+
```
84+
85+
## Supported Barcode Formats
86+
87+
The Dynamsoft Barcode Reader SDK supports:
88+
- 1D barcodes: Code 39, Code 93, Code 128, Codabar, EAN-8, EAN-13, UPC-A, UPC-E, Interleaved 2 of 5, Industrial 2 of 5, ITF-14
89+
- 2D barcodes: QR Code, DataMatrix, PDF417, Aztec, MaxiCode
90+
- Postal Codes: USPS Intelligent Mail, Postnet, Planet, Australian Post, UK Royal Mail (RM4SCC)
91+
- GS1 barcodes: GS1 DataBar, GS1 Composite
92+
93+
## Documentation
94+
95+
For more information about the Dynamsoft Barcode Reader SDK:
96+
- [Python SDK Documentation](https://www.dynamsoft.com/barcode-reader/docs/server/programming/python/)
97+
- [API Reference](https://www.dynamsoft.com/barcode-reader/docs/server/programming/python/api-reference/)
98+
- [Sample Code Repository](https://github.com/Dynamsoft/barcode-reader-python-samples)
Lines changed: 162 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,162 @@
1+
#!/usr/bin/env python3
2+
"""
3+
Command-line barcode scanner using Dynamsoft Barcode Reader SDK
4+
"""
5+
import sys
6+
import os
7+
from dynamsoft_barcode_reader_bundle import *
8+
9+
10+
def scan_barcode(image_path):
11+
"""
12+
Scan barcode from a single image file
13+
14+
Args:
15+
image_path: Path to the image file containing barcode
16+
"""
17+
# Check if file exists
18+
if not os.path.exists(image_path):
19+
print(f"Error: File '{image_path}' not found.")
20+
return
21+
22+
# Initialize license
23+
# Using public trial license (requires network connection)
24+
errorCode, errorMsg = LicenseManager.init_license("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9")
25+
if errorCode != EnumErrorCode.EC_OK and errorCode != EnumErrorCode.EC_LICENSE_CACHE_USED:
26+
print(f"License initialization failed: ErrorCode: {errorCode}, ErrorString: {errorMsg}")
27+
return
28+
29+
# Create CaptureVisionRouter instance
30+
cvr_instance = CaptureVisionRouter()
31+
32+
# Capture barcode from image
33+
print(f"Scanning barcode from: {image_path}")
34+
result = cvr_instance.capture(image_path, EnumPresetTemplate.PT_READ_BARCODES.value)
35+
36+
# Check for errors
37+
if result.get_error_code() != EnumErrorCode.EC_OK:
38+
print(f"Error: {result.get_error_code()} - {result.get_error_string()}")
39+
return
40+
41+
# Get barcode results
42+
barcode_result = result.get_decoded_barcodes_result()
43+
if barcode_result is None or len(barcode_result.get_items()) == 0:
44+
print("No barcode detected.")
45+
return
46+
47+
# Display results
48+
items = barcode_result.get_items()
49+
print(f"\n✓ Decoded {len(items)} barcode(s):\n")
50+
for index, item in enumerate(items):
51+
print(f"Result {index + 1}:")
52+
print(f" Format: {item.get_format_string()}")
53+
print(f" Text: {item.get_text()}")
54+
print()
55+
56+
57+
def scan_directory(directory_path):
58+
"""
59+
Scan barcodes from all images in a directory
60+
61+
Args:
62+
directory_path: Path to directory containing images
63+
"""
64+
# Check if directory exists
65+
if not os.path.isdir(directory_path):
66+
print(f"Error: Directory '{directory_path}' not found.")
67+
return
68+
69+
# Initialize license
70+
errorCode, errorMsg = LicenseManager.init_license("DLS2eyJvcmdhbml6YXRpb25JRCI6IjIwMDAwMSJ9")
71+
if errorCode != EnumErrorCode.EC_OK and errorCode != EnumErrorCode.EC_LICENSE_CACHE_USED:
72+
print(f"License initialization failed: ErrorCode: {errorCode}, ErrorString: {errorMsg}")
73+
return
74+
75+
# Create CaptureVisionRouter instance
76+
cvr_instance = CaptureVisionRouter()
77+
78+
# Set up DirectoryFetcher as input
79+
fetcher = DirectoryFetcher()
80+
fetcher.set_directory(directory_path)
81+
cvr_instance.set_input(fetcher)
82+
83+
# Create result receiver
84+
class MyCapturedResultReceiver(CapturedResultReceiver):
85+
def __init__(self):
86+
super().__init__()
87+
88+
def on_decoded_barcodes_received(self, result):
89+
tag = result.get_original_image_tag()
90+
if isinstance(tag, FileImageTag):
91+
print(f"\nFile: {tag.get_file_path()}")
92+
93+
if result.get_error_code() != EnumErrorCode.EC_OK:
94+
print(f"Error: {result.get_error_string()}")
95+
else:
96+
items = result.get_items()
97+
if len(items) > 0:
98+
print(f"Detected {len(items)} barcode(s):")
99+
for index, item in enumerate(items):
100+
print(f" Result {index + 1}:")
101+
print(f" Format: {item.get_format_string()}")
102+
print(f" Text: {item.get_text()}")
103+
else:
104+
print("No barcodes detected.")
105+
106+
# Create image source state listener
107+
class MyImageSourceStateListener(ImageSourceStateListener):
108+
def __init__(self, cvr_instance):
109+
super().__init__()
110+
self.cvr_instance = cvr_instance
111+
112+
def on_image_source_state_received(self, state):
113+
if state == EnumImageSourceState.ISS_EXHAUSTED:
114+
if self.cvr_instance is not None:
115+
self.cvr_instance.stop_capturing()
116+
117+
# Register listeners
118+
receiver = MyCapturedResultReceiver()
119+
cvr_instance.add_result_receiver(receiver)
120+
listener = MyImageSourceStateListener(cvr_instance)
121+
cvr_instance.add_image_source_state_listener(listener)
122+
123+
# Start capturing
124+
print(f"Scanning barcodes from directory: {directory_path}\n")
125+
errorCode, errorMsg = cvr_instance.start_capturing("", True)
126+
if errorCode != EnumErrorCode.EC_OK:
127+
print(f"Error: {errorMsg}")
128+
else:
129+
print("\n✓ Directory scan completed.")
130+
131+
132+
def print_usage():
133+
"""Print usage information"""
134+
print("Command-line Barcode Scanner using Dynamsoft Barcode Reader SDK")
135+
print("\nUsage:")
136+
print(" python barcode_scanner.py <image_path> # Scan a single image")
137+
print(" python barcode_scanner.py --dir <directory> # Scan all images in a directory")
138+
print("\nExamples:")
139+
print(" python barcode_scanner.py barcode.jpg")
140+
print(" python barcode_scanner.py --dir ./images")
141+
142+
143+
def main():
144+
"""Main entry point"""
145+
if len(sys.argv) < 2:
146+
print_usage()
147+
sys.exit(1)
148+
149+
if sys.argv[1] == "--dir":
150+
if len(sys.argv) < 3:
151+
print("Error: Directory path required.")
152+
print_usage()
153+
sys.exit(1)
154+
scan_directory(sys.argv[2])
155+
elif sys.argv[1] in ["-h", "--help"]:
156+
print_usage()
157+
else:
158+
scan_barcode(sys.argv[1])
159+
160+
161+
if __name__ == "__main__":
162+
main()
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
dynamsoft-barcode-reader-bundle

0 commit comments

Comments
 (0)