Bagaimana bisa digunakan sebagai layanan REST API. Kirim teks mentah dan doccano menanggapi data yang diuraikan?
Pendokumentasian tentang API sedang berlangsung. Harap tunggu sebentar!
https://github.com/chakki-works/doccano/projects/3#card -22665439
Adakah pembaruan untuk rilis berikutnya dengan ini? Saya juga ingin fitur ini untuk proyek anotasi yang sedang saya kerjakan.
@luispsantos , @Hironsan di https://github.com/chakki-works/doccano/issues/6 memberikan contoh kelas untuk menggambarkan interaksi dengan doccano
API. Dari pengalaman saya, ini cukup mudah digunakan dan dipahami.
Saya perhatikan bahwa karena perubahan terbaru, otentikasi berfungsi melalui token API sekarang, jadi Anda hanya perlu menyesuaikan skema otentikasi dalam kode itu dan meneruskan header otentikasi setiap kali dengan permintaan Anda.
class Client(object):
def __init__(self, entrypoint, username=None, password=None):
self.entrypoint = entrypoint
self.client = requests.Session()
api_token = self.get_api_token(username, password)
self.auth_headers = {"Authorization": "Token {}".format(api_token)}
def get_api_token(self, username, password):
url = f"{self.entrypoint}/v1/auth-token"
login = {"username": username, "password": password}
response = self.client.post(url, json=login)
return response.json()["token"]
def fetch_projects(self):
url = f"{self.entrypoint}/v1/projects"
response = self.client.get(url, headers=self.auth_headers)
return response
@rbagd Terima kasih untuk kelas contoh, ini akan bermanfaat bagi orang lain yang menemukan masalah ini tentang cara berinteraksi dengan Doccano di level API (terutama dengan otentikasi token tambahan pada contoh ini). Saya setuju bahwa contoh yang diberikan oleh @Hironsan cukup intuitif, dan sementara itu saya berhasil menyesuaikannya dengan kasus penggunaan saya menggunakan otentikasi token :+1:
Pertanyaan yang diajukan di #410 .
Saya berhasil membuat proyek dan mengunggah dokumen menggunakan titik akhir ini
https://github.com/chakki-works/doccano/blob/master/app/api/urls.py#L27 -L28
tetapi metadata tidak diunggah.
Dari apa yang saya lihat di sini https://github.com/chakki-works/doccano/blob/master/app/api/views.py#L125 bidang meta
tidak didukung oleh API meskipun dalam Serializer, yang akan menjelaskan bahwa metadata tidak diunggah. Apakah pemahaman saya benar?
Saya mencoba mengunggah dokumen menggunakan titik akhir ini
https://github.com/chakki-works/doccano/blob/master/app/api/urls.py#L37 -L38
Apa jenis argumen file
sini https://github.com/chakki-works/doccano/blob/master/app/api/views.py#L207 ?
Saya mencoba meneruskan file JSONLine sebagai string, dan saya mendapatkan {"detail":"Unsupported media type \"application/json\" in request."}
Untuk menindaklanjuti pertanyaan saya di atas, berikut adalah beberapa kode yang dapat direproduksi.
Klien yang saya gunakan
class Client(object):
"""
Client code was inspired by: https://github.com/chakki-works/doccano/issues/6#issuecomment-489924577
Endpoints can be found here: https://github.com/chakki-works/doccano/blob/master/app/api/urls.py
"""
def __init__(self, entrypoint, username=None, password=None):
self.entrypoint = entrypoint
self.client = requests.Session()
self._login(username, password)
def _login(self, username, password):
url = f"{self.entrypoint}/v1/auth-token"
login = {"username": username, "password": password}
response = self.client.post(url, json=login)
api_token = response.json()["token"]
self.client.headers.update({"Authorization": f"Token {api_token}"})
def add_document(self, project_id, data):
url = f'{self.entrypoint}/v1/projects/{project_id}/docs'
response = self.client.post(url, data=data)
return response.json()
def upload_data(self, project_id, file, file_format='csv'):
"""
file is (?) of type file object (BytesIO or StringIO ...)
"""
data = {
'file': file,
'format': file_format
}
url = f'{self.entrypoint}/v1/projects/{project_id}/docs/upload'
response = self.client.post(url, data=data)
return response
>>> c = Client(
'https://labelling-onefootball.herokuapp.com',
os.environ.get('DOCANNO_ADMIN'),
os.environ.get('DOCANNO_PWD')
)
>>> doc = {'text': 'Mercato / PSG\xa0: ce qu’a dit Tuchel à Neymar va vous surprendre',
'meta': {'article_id': 27551814,
'published_at_str': '2019-10-08 08:23:35',
'provider_name': 'InfoMercato',
'article_link': 'https://consumer-web.onefootball.com/cms/fr/27551814'}}
>>> c.add_document(project_id, doc)
# meta fields are not uploaded
>>> jsonline_dataset = '{"text":"Mercato \\/ PSG\\u00a0: ce qu\\u2019a dit Tuchel \\u00e0 Neymar va vous surprendre","meta":{"article_id":27551814,"published_at_str":"2019-10-08 08:23:35","provider_name":"InfoMercato","article_link":"https:\\/\\/consumer-web.onefootball.com\\/cms\\/fr\\/27551814"}}\n{"text":"Bingo Challenge : Le num\\u00e9ro \\u00ab\\u00a0Tres\\u00a0\\u00bb","meta":{"article_id":27577681,"published_at_str":"2019-10-10 10:30:01","provider_name":"Furia Liga","article_link":"https:\\/\\/consumer-web.onefootball.com\\/cms\\/fr\\/27577681"}}'
>>> file_obj = io.StringIO(jsonline_dataset)
>>> r = c.upload_data(4, file_obj, 'json')
# I get <iframe src="//www.herokucdn.com/error-pages/application-error.html"></iframe>
@louisguitton Apakah Anda pernah dapat menemukan solusi? Saya menggunakan kode yang sangat mirip dan sayangnya menerima respons berikut dengan /upload
:
{'detail': 'Unsupported media type "application/x-www-form-urlencoded" in request.'}
Permintaan get
untuk titik akhir seperti /me
berfungsi dengan baik.
@icoxfog417 Anda mereferensikan dokumentasi pada bulan Juni; dapatkah saya menemukan dokumentasi ini di suatu tempat?
@louisguitton Apakah Anda pernah dapat menemukan solusi?
Tidak, menunggu dokumentasi juga. Tapi mereka cukup sibuk berurusan dengan refactoring frontend untuk v1.0.0 jadi saya tidak keberatan menunggu.
@louisguitton
Pembaruan kecil: Saya pikir itu mungkin dari Content-Type multipart/form-data
. Saya sudah mencoba dengan itu dan menerima:
{'detail': 'Empty content'}
Jadi itu setidaknya _different_ . Kita lihat saja apakah itu termasuk kemajuan atau tidak.
Pembaruan 2: Saya mendapat <Response [201]>
:
requests.post(
'http://<URL>/v1/projects/1/docs/upload',
files={'file': ('d1.json', open('d1.json', 'rb'))},
data={'file': ('d1.json', open('d1.json', 'rb')), 'format': 'json'},
headers = {
'Authorization': 'Token {token}'.format(token=token)
}
)
Meskipun tanggapannya positif, dokumen tersebut tampaknya tidak ditambahkan ke proyek.
Pembaruan 3: Dikonfirmasi berfungsi! Ini juga berfungsi dengan requests.Session()
pra-otorisasi, seperti yang ditunjukkan di bawah ini.
# this is part of the Client class
def upload(
self,
project_id: str,
file_format: str,
file_name: str,
file_path: str = './',
) -> requests.models.Response:
"""
"""
url = '{}/v1/projects/{}/docs/upload'.format(self.entrypoint, project_id)
files = {'file': (file_name, open(os.path.join(file_path, file_name), 'rb'))}
data = {'file': (file_name, open(os.path.join(file_path, file_name), 'rb')), 'format': file_format}
return self.client.post(url, files=files, data=data)
doccano-client
untuk memanggil API.@louisguitton @Hironsan
Saya membuat pembungkus API sederhana untuk penggunaan sementara saat tim bekerja membangun klien resmi.
https://github.com/afparsons/doccano_api_client
@luispsantos - Saya lupa menandai Anda tetapi Anda juga tertarik pada suatu saat saya pikir.
Saya perhatikan bahwa titik akhir get_doc_download
tidak memformat data menggunakan pemformatan JSON.
Adakah saran untuk mengimplementasikan kelas JSONPainter
untuk mengembalikan struktur data yang sama dari titik akhir ini?
Hai @Hironsan , di mana dokumen API tersedia? Hanya spesifikasi OpenAPI yang akan dihargai juga. Terima kasih!
Saya telah menggunakan doccano ke aws dan sekarang mencoba menggunakan klien untuk mengunggah data dari pipa aliran udara tetapi sepertinya saya tidak dapat terhubung dengan klien doccano. Saya mengikuti instruksi tetapi saya terus mendapatkan kesalahan:
from doccano_api_client import DoccanoClient
doccano_client = DoccanoClient(
'https://doccano-dev.test.com/',
os.environ.get('DOCANNO_ADMIN'),
os.environ.get('DOCANNO_PWD')
)
Saya kemudian mendapatkan kesalahan di bawah ini
JSONDecodeError Traceback (most recent call last)
<ipython-input-100-60f5cf7a0cc5> in <module>
4 'https://doccano-dev.test.com/',
5 os.environ.get('DOCANNO_ADMIN'),
----> 6 os.environ.get('DOCANNO_PWD')
7 )
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/doccano_api_client/__init__.py in __init__(self, baseurl, username, password)
107 self.baseurl = baseurl if baseurl[-1] == '/' else baseurl+'/'
108 self.session = requests.Session()
--> 109 self._login(username, password)
110
111 def _login(
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/doccano_api_client/__init__.py in _login(self, username, password)
125 url = 'v1/auth-token'
126 auth = {'username': username, 'password': password}
--> 127 response = self.post(url, auth)
128 token = response['token']
129 self.session.headers.update(
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/doccano_api_client/__init__.py in post(self, endpoint, data, json, files)
62 request_url = urljoin(self.baseurl, endpoint)
63 return self.session.post(
---> 64 request_url, data=data, files=files, json=json).json()
65
66 def delete(
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/requests/models.py in json(self, **kwargs)
896 # used.
897 pass
--> 898 return complexjson.loads(self.text, **kwargs)
899
900 <strong i="9">@property</strong>
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/simplejson/__init__.py in loads(s, encoding, cls, object_hook, parse_float, parse_int, parse_constant, object_pairs_hook, use_decimal, **kw)
523 parse_constant is None and object_pairs_hook is None
524 and not use_decimal and not kw):
--> 525 return _default_decoder.decode(s)
526 if cls is None:
527 cls = JSONDecoder
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/simplejson/decoder.py in decode(self, s, _w, _PY3)
368 if _PY3 and isinstance(s, bytes):
369 s = str(s, self.encoding)
--> 370 obj, end = self.raw_decode(s)
371 end = _w(s, end).end()
372 if end != len(s):
~/.pyenv/versions/3.6.10/lib/python3.6/site-packages/simplejson/decoder.py in raw_decode(self, s, idx, _w, _PY3)
398 elif ord0 == 0xef and s[idx:idx + 3] == '\xef\xbb\xbf':
399 idx += 3
--> 400 return self.scan_once(s, idx=_w(s, idx).end())
JSONDecodeError: Expecting value: line 2 column 1 (char 1)
Komentar yang paling membantu
@louisguitton @Hironsan
Saya membuat pembungkus API sederhana untuk penggunaan sementara saat tim bekerja membangun klien resmi.
https://github.com/afparsons/doccano_api_client
@luispsantos - Saya lupa menandai Anda tetapi Anda juga tertarik pada suatu saat saya pikir.