mirror of
				https://github.com/explosion/spaCy.git
				synced 2025-10-31 16:07:41 +03:00 
			
		
		
		
	* Integrate Python kernel via Binder * Add live model test for languages with examples * Update docs and code examples * Adjust margin (if not bootstrapped) * Add binder version to global config * Update terminal and executable code mixins * Pass attributes through infobox and section * Hide v-cloak * Fix example * Take out model comparison for now * Add meta text for compat * Remove chart.js dependency * Tidy up and simplify JS and port big components over to Vue * Remove chartjs example * Add Twitter icon * Add purple stylesheet option * Add utility for hand cursor (special cases only) * Add transition classes * Add small option for section * Add thumb object for small round thumbnail images * Allow unset code block language via "none" value (workaround to still allow unset language to default to DEFAULT_SYNTAX) * Pass through attributes * Add syntax highlighting definitions for Julia, R and Docker * Add website icon * Remove user survey from navigation * Don't hide GitHub icon on small screens * Make top navigation scrollable on small screens * Remove old resources page and references to it * Add Universe * Add helper functions for better page URL and title * Update site description * Increment versions * Update preview images * Update mentions of resources * Fix image * Fix social images * Fix problem with cover sizing and floats * Add divider and move badges into heading * Add docstrings * Reference converting section * Add section on converting word vectors * Move converting section to custom section and fix formatting * Remove old fastText example * Move extensions content to own section Keep weird ID to not break permalinks for now (we don't want to rewrite URLs if not absolutely necessary) * Use better component example and add factories section * Add note on larger model * Use better example for non-vector * Remove similarity in context section Only works via small models with tensors so has always been kind of confusing * Add note on init-model command * Fix lightning tour examples and make excutable if possible * Add spacy train CLI section to train * Fix formatting and add video * Fix formatting * Fix textcat example description (resolves #2246) * Add dummy file to try resolve conflict * Delete dummy file * Tidy up [ci skip] * Ensure sufficient height of loading container * Add loading animation to universe * Update Thebelab build and use better startup message * Fix asset versioning * Fix typo [ci skip] * Add note on project idea label
		
			
				
	
	
		
			439 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
			
		
		
	
	
			439 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			Plaintext
		
	
	
	
	
	
| //- 💫 DOCS > USAGE > PROCESSING PIPELINES > EXTENSIONS
 | ||
| 
 | ||
| p
 | ||
|     |  As of v2.0, spaCy allows you to set any custom attributes and methods
 | ||
|     |  on the #[code Doc], #[code Span] and #[code Token], which become
 | ||
|     |  available as #[code Doc._], #[code Span._] and #[code Token._] – for
 | ||
|     |  example, #[code Token._.my_attr]. This lets you store additional
 | ||
|     |  information relevant to your application, add new features and
 | ||
|     |  functionality to spaCy, and implement your own models trained with other
 | ||
|     |  machine learning libraries. It also lets you take advantage of spaCy's
 | ||
|     |  data structures and the #[code Doc] object as the "single source of
 | ||
|     |  truth".
 | ||
| 
 | ||
| +aside("Why ._?")
 | ||
|     |  Writing to a #[code ._] attribute instead of to the #[code Doc] directly
 | ||
|     |  keeps a clearer separation and makes it easier to ensure backwards
 | ||
|     |  compatibility. For example, if you've implemented your own #[code .coref]
 | ||
|     |  property and spaCy claims it one day, it'll break your code. Similarly,
 | ||
|     |  just by looking at the code, you'll immediately know what's built-in and
 | ||
|     |  what's custom – for example, #[code doc.sentiment] is spaCy, while
 | ||
|     |  #[code doc._.sent_score] isn't.
 | ||
| 
 | ||
| p
 | ||
|     |  There are three main types of extensions, which can be defined using the
 | ||
|     |  #[+api("doc#set_extension") #[code Doc.set_extension]],
 | ||
|     |  #[+api("span#set_extension") #[code Span.set_extension]] and
 | ||
|     |  #[+api("token#set_extension") #[code Token.set_extension]] methods.
 | ||
| 
 | ||
| +list("numbers")
 | ||
|     +item #[strong Attribute extensions].
 | ||
|         |  Set a default value for an attribute, which can be overwritten
 | ||
|         |  manually at any time. Attribute extensions work like "normal"
 | ||
|         |  variables and are the quickest way to store arbitrary information
 | ||
|         |  on a #[code Doc], #[code Span] or #[code Token]. Attribute defaults
 | ||
|         |  behaves just like argument defaults
 | ||
|         |  #[+a("http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments") in Python functions],
 | ||
|         |  and should not be used for mutable values like dictionaries or lists.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code.
 | ||
|                 Doc.set_extension('hello', default=True)
 | ||
|                 assert doc._.hello
 | ||
|                 doc._.hello = False
 | ||
| 
 | ||
|     +item #[strong Property extensions].
 | ||
|         |  Define a getter and an optional setter function. If no setter is
 | ||
|         |  provided, the extension is immutable. Since the getter and setter
 | ||
|         |  functions are only called when you #[em retrieve] the attribute,
 | ||
|         |  you can also access values of previously added attribute extensions.
 | ||
|         |  For example, a #[code Doc] getter can average over #[code Token]
 | ||
|         |   attributes. For #[code Span] extensions, you'll almost always want
 | ||
|         |  to use a property – otherwise, you'd have to write to
 | ||
|         |  #[em every possible] #[code Span] in the #[code Doc] to set up the
 | ||
|         |  values correctly.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code.
 | ||
|                 Doc.set_extension('hello', getter=get_hello_value, setter=set_hello_value)
 | ||
|                 assert doc._.hello
 | ||
|                 doc._.hello = 'Hi!'
 | ||
| 
 | ||
|     +item #[strong Method extensions].
 | ||
|         |  Assign a function that becomes available as an object method. Method
 | ||
|         |  extensions are always immutable. For more details and implementation
 | ||
|         |  ideas, see
 | ||
|         |  #[+a("/usage/examples#custom-components-attr-methods") these examples].
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code.o-no-block.
 | ||
|                 Doc.set_extension('hello', method=lambda doc, name: 'Hi {}!'.format(name))
 | ||
|                 assert doc._.hello('Bob') == 'Hi Bob!'
 | ||
| 
 | ||
| p
 | ||
|     |  Before you can access a custom extension, you need to register it using
 | ||
|     |  the #[code set_extension] method on the object you want
 | ||
|     |  to add it to, e.g. the #[code Doc]. Keep in mind that extensions are
 | ||
|     |  always #[strong added globally] and not just on a particular instance.
 | ||
|     |  If an attribute of the same name
 | ||
|     |  already exists, or if you're trying to access an attribute that hasn't
 | ||
|     |  been registered, spaCy will raise an #[code AttributeError].
 | ||
| 
 | ||
| +code("Example").
 | ||
|     from spacy.tokens import Doc, Span, Token
 | ||
| 
 | ||
|     fruits = ['apple', 'pear', 'banana', 'orange', 'strawberry']
 | ||
|     is_fruit_getter = lambda token: token.text in fruits
 | ||
|     has_fruit_getter = lambda obj: any([t.text in fruits for t in obj])
 | ||
| 
 | ||
|     Token.set_extension('is_fruit', getter=is_fruit_getter)
 | ||
|     Doc.set_extension('has_fruit', getter=has_fruit_getter)
 | ||
|     Span.set_extension('has_fruit', getter=has_fruit_getter)
 | ||
| 
 | ||
| +aside-code("Usage example").
 | ||
|     doc = nlp(u"I have an apple and a melon")
 | ||
|     assert doc[3]._.is_fruit      # get Token attributes
 | ||
|     assert not doc[0]._.is_fruit
 | ||
|     assert doc._.has_fruit        # get Doc attributes
 | ||
|     assert doc[1:4]._.has_fruit   # get Span attributes
 | ||
| 
 | ||
| p
 | ||
|     |  Once you've registered your custom attribute, you can also use the
 | ||
|     |  built-in #[code set], #[code get] and #[code has] methods to modify and
 | ||
|     |  retrieve the attributes. This is especially useful it you want to pass in
 | ||
|     |  a string instead of calling #[code doc._.my_attr].
 | ||
| 
 | ||
| +table(["Method", "Description", "Valid for", "Example"])
 | ||
|     +row
 | ||
|         +cell #[code ._.set()]
 | ||
|         +cell Set a value for an attribute.
 | ||
|         +cell Attributes, mutable properties.
 | ||
|         +cell #[code.u-break token._.set('my_attr', True)]
 | ||
| 
 | ||
|     +row
 | ||
|         +cell #[code ._.get()]
 | ||
|         +cell Get the value of an attribute.
 | ||
|         +cell Attributes, mutable properties, immutable properties, methods.
 | ||
|         +cell #[code.u-break my_attr = span._.get('my_attr')]
 | ||
| 
 | ||
|     +row
 | ||
|         +cell #[code ._.has()]
 | ||
|         +cell Check if an attribute exists.
 | ||
|         +cell Attributes, mutable properties, immutable properties, methods.
 | ||
|         +cell #[code.u-break doc._.has('my_attr')]
 | ||
| 
 | ||
| +infobox("How the ._ is implemented")
 | ||
|     |  Extension definitions – the defaults, methods, getters and setters you
 | ||
|     |  pass in to #[code set_extension] – are stored in class attributes on the
 | ||
|     |  #[code Underscore] class. If you write to an extension attribute, e.g.
 | ||
|     |  #[code doc._.hello = True], the data is stored within the
 | ||
|     |  #[+api("doc#attributes") #[code Doc.user_data]] dictionary. To keep the
 | ||
|     |  underscore data separate from your other dictionary entries, the string
 | ||
|     |  #[code "._."] is placed before the name, in a tuple.
 | ||
| 
 | ||
| +h(4, "component-example1") Example: Custom sentence segmentation logic
 | ||
| 
 | ||
| p
 | ||
|     |  Let's say you want to implement custom logic to improve spaCy's sentence
 | ||
|     |  boundary detection. Currently, sentence segmentation is based on the
 | ||
|     |  dependency parse, which doesn't always produce ideal results. The custom
 | ||
|     |  logic should therefore be applied #[strong after] tokenization, but
 | ||
|     |  #[strong before] the dependency parsing – this way, the parser can also
 | ||
|     |  take advantage of the sentence boundaries.
 | ||
| 
 | ||
| +code-exec.
 | ||
|     import spacy
 | ||
| 
 | ||
|     def sbd_component(doc):
 | ||
|         for i, token in enumerate(doc[:-2]):
 | ||
|             # define sentence start if period + titlecase token
 | ||
|             if token.text == '.' and doc[i+1].is_title:
 | ||
|                 doc[i+1].sent_start = True
 | ||
|         return doc
 | ||
| 
 | ||
|     nlp = spacy.load('en_core_web_sm')
 | ||
|     nlp.add_pipe(sbd_component, before='parser')  # insert before the parser
 | ||
|     doc = nlp(u"This is a sentence. This is another sentence.")
 | ||
|     for sent in doc.sents:
 | ||
|         print(sent.text)
 | ||
| 
 | ||
| +h(4, "component-example2")
 | ||
|     |  Example: Pipeline component for entity matching and tagging with
 | ||
|     |  custom attributes
 | ||
| 
 | ||
| p
 | ||
|     |  This example shows how to create a spaCy extension that takes a
 | ||
|     |  terminology list (in this case, single- and multi-word company names),
 | ||
|     |  matches the occurences in a document, labels them as #[code ORG] entities,
 | ||
|     |  merges the tokens and sets custom #[code is_tech_org] and
 | ||
|     |  #[code has_tech_org] attributes. For efficient matching, the example uses
 | ||
|     |  the #[+api("phrasematcher") #[code PhraseMatcher]] which accepts
 | ||
|     |  #[code Doc] objects as match patterns and works well for large
 | ||
|     |  terminology lists. It also ensures your patterns will always match, even
 | ||
|     |  when you customise spaCy's tokenization rules. When you call #[code nlp]
 | ||
|     |  on a text, the custom pipeline component is applied to the #[code Doc]
 | ||
| 
 | ||
| +github("spacy", "examples/pipeline/custom_component_entities.py", 500)
 | ||
| 
 | ||
| p
 | ||
|     |  Wrapping this functionality in a
 | ||
|     |  pipeline component allows you to reuse the module with different
 | ||
|     |  settings, and have all pre-processing taken care of when you call
 | ||
|     |  #[code nlp] on your text and receive a #[code Doc] object.
 | ||
| 
 | ||
| +h(4, "component-example3")
 | ||
|     |  Example: Pipeline component for GPE entities and country meta data via a
 | ||
|     |  REST API
 | ||
| 
 | ||
| p
 | ||
|     |  This example shows the implementation of a pipeline component
 | ||
|     |  that fetches country meta data via the
 | ||
|     |  #[+a("https://restcountries.eu") REST Countries API] sets entity
 | ||
|     |  annotations for countries, merges entities into one token and
 | ||
|     |  sets custom attributes on the #[code Doc], #[code Span] and
 | ||
|     |  #[code Token] – for example, the capital, latitude/longitude coordinates
 | ||
|     |  and even the country flag.
 | ||
| 
 | ||
| +github("spacy", "examples/pipeline/custom_component_countries_api.py", 500)
 | ||
| 
 | ||
| p
 | ||
|     |  In this case, all data can be fetched on initialisation in one request.
 | ||
|     |  However, if you're working with text that contains incomplete country
 | ||
|     |  names, spelling mistakes or foreign-language versions, you could also
 | ||
|     |  implement a #[code like_country]-style getter function that makes a
 | ||
|     |  request to the search API endpoint and returns the best-matching
 | ||
|     |  result.
 | ||
| 
 | ||
| +h(4, "custom-components-usage-ideas") Other usage ideas
 | ||
| 
 | ||
| +list
 | ||
|     +item
 | ||
|         |  #[strong Adding new features and hooking in models]. For example,
 | ||
|         |  a sentiment analysis model, or your preferred solution for
 | ||
|         |  lemmatization or sentiment analysis. spaCy's built-in tagger,
 | ||
|         |  parser and entity recognizer respect annotations that were already
 | ||
|         |  set on the #[code Doc] in a previous step of the pipeline.
 | ||
|     +item
 | ||
|         |  #[strong Integrating other libraries and APIs]. For example, your
 | ||
|         |  pipeline component can write additional information and data
 | ||
|         |  directly to the #[code Doc] or #[code Token] as custom attributes,
 | ||
|         |  while making sure no information is lost in the process. This can
 | ||
|         |  be output generated by other libraries and models, or an external
 | ||
|         |  service with a REST API.
 | ||
|     +item
 | ||
|         |  #[strong Debugging and logging]. For example, a component which
 | ||
|         |  stores and/or exports relevant information about the current state
 | ||
|         |  of the processed document, and insert it at any point of your
 | ||
|         |  pipeline.
 | ||
| 
 | ||
| +infobox("Developing third-party extensions")
 | ||
|     |  The new pipeline management and custom attributes finally make it easy
 | ||
|     |  to develop your own spaCy extensions and plugins and share them with
 | ||
|     |  others. Extensions can claim their own #[code ._] namespace and exist as
 | ||
|     |  standalone packages. If you're developing a tool or library and want to
 | ||
|     |  make it easy for others to use it with spaCy and add it to their
 | ||
|     |  pipeline, all you have to do is expose a function that takes a
 | ||
|     |  #[code Doc], modifies it and returns it. For more details and
 | ||
|     |  #[strong best practices], see the section on
 | ||
|     |  #[+a("#extensions") developing spaCy extensions].
 | ||
| 
 | ||
| +h(3, "custom-components-user-hooks") User hooks
 | ||
| 
 | ||
| p
 | ||
|     |  While it's generally recommended to use the #[code Doc._], #[code Span._]
 | ||
|     |  and #[code Token._] proxies to add your own custom attributes, spaCy
 | ||
|     |  offers a few exceptions to allow #[strong customising the built-in methods]
 | ||
|     |  like #[+api("doc#similarity") #[code Doc.similarity]] or
 | ||
|     |  #[+api("doc#vector") #[code Doc.vector]]. with your own hooks, which can
 | ||
|     |  rely on statistical models you train yourself. For instance, you can
 | ||
|     |  provide your own on-the-fly sentence segmentation algorithm or document
 | ||
|     |  similarity method.
 | ||
| 
 | ||
| p
 | ||
|     |  Hooks let you customize some of the behaviours of the #[code Doc],
 | ||
|     |  #[code Span] or #[code Token] objects by adding a component to the
 | ||
|     |  pipeline. For instance, to customize the
 | ||
|     |  #[+api("doc#similarity") #[code Doc.similarity]] method, you can add a
 | ||
|     |  component that sets a custom function to
 | ||
|     |  #[code doc.user_hooks['similarity']]. The built-in #[code Doc.similarity]
 | ||
|     |  method will check the #[code user_hooks] dict, and delegate to your
 | ||
|     |  function if you've set one. Similar results can be achieved by setting
 | ||
|     |  functions to #[code Doc.user_span_hooks] and #[code Doc.user_token_hooks].
 | ||
| 
 | ||
| +aside("Implementation note")
 | ||
|     |  The hooks live on the #[code Doc] object because the #[code Span] and
 | ||
|     |  #[code Token] objects are created lazily, and don't own any data. They
 | ||
|     |  just proxy to their parent #[code Doc]. This turns out to be convenient
 | ||
|     |  here — we only have to worry about installing hooks in one place.
 | ||
| 
 | ||
| +table(["Name", "Customises"])
 | ||
|     +row
 | ||
|         +cell #[code user_hooks]
 | ||
|         +cell
 | ||
|             +api("doc#vector") #[code Doc.vector]
 | ||
|             +api("doc#has_vector") #[code Doc.has_vector]
 | ||
|             +api("doc#vector_norm") #[code Doc.vector_norm]
 | ||
|             +api("doc#sents") #[code Doc.sents]
 | ||
| 
 | ||
|     +row
 | ||
|         +cell #[code user_token_hooks]
 | ||
|         +cell
 | ||
|             +api("token#similarity") #[code Token.similarity]
 | ||
|             +api("token#vector") #[code Token.vector]
 | ||
|             +api("token#has_vector") #[code Token.has_vector]
 | ||
|             +api("token#vector_norm") #[code Token.vector_norm]
 | ||
|             +api("token#conjuncts") #[code Token.conjuncts]
 | ||
| 
 | ||
|     +row
 | ||
|         +cell #[code user_span_hooks]
 | ||
|         +cell
 | ||
|             +api("span#similarity") #[code Span.similarity]
 | ||
|             +api("span#vector") #[code Span.vector]
 | ||
|             +api("span#has_vector") #[code Span.has_vector]
 | ||
|             +api("span#vector_norm") #[code Span.vector_norm]
 | ||
|             +api("span#root") #[code Span.root]
 | ||
| 
 | ||
| +code("Add custom similarity hooks").
 | ||
|     class SimilarityModel(object):
 | ||
|         def __init__(self, model):
 | ||
|             self._model = model
 | ||
| 
 | ||
|         def __call__(self, doc):
 | ||
|             doc.user_hooks['similarity'] = self.similarity
 | ||
|             doc.user_span_hooks['similarity'] = self.similarity
 | ||
|             doc.user_token_hooks['similarity'] = self.similarity
 | ||
| 
 | ||
|         def similarity(self, obj1, obj2):
 | ||
|             y = self._model([obj1.vector, obj2.vector])
 | ||
|             return float(y[0])
 | ||
| 
 | ||
| +h(3, "extensions") Developing spaCy extensions
 | ||
| 
 | ||
| p
 | ||
|     |  We're very excited about all the new possibilities for community
 | ||
|     |  extensions and plugins in spaCy v2.0, and we can't wait to see what
 | ||
|     |  you build with it! To get you started, here are a few tips, tricks and
 | ||
|     |  best practices. #[+a("/universe/?category=pipeline") See here] for
 | ||
|     |  examples of other spaCy extensions.
 | ||
| 
 | ||
| +list
 | ||
|     +item
 | ||
|         |  Make sure to choose a #[strong descriptive and specific name] for
 | ||
|         |  your pipeline component class, and set it as its #[code name]
 | ||
|         |  attribute. Avoid names that are too common or likely to clash with
 | ||
|         |  built-in or a user's other custom components. While it's fine to call
 | ||
|         |  your package "spacy_my_extension", avoid component names including
 | ||
|         |  "spacy", since this can easily lead to confusion.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new name = 'myapp_lemmatizer'
 | ||
|             +code-old name = 'lemmatizer'
 | ||
| 
 | ||
|     +item
 | ||
|         |  When writing to #[code Doc], #[code Token] or #[code Span] objects,
 | ||
|         |  #[strong use getter functions] wherever possible, and avoid setting
 | ||
|         |  values explicitly. Tokens and spans don't own any data themselves,
 | ||
|         |  so you should provide a function that allows them to compute the
 | ||
|         |  values instead of writing static properties to individual objects.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new.
 | ||
|                 is_fruit = lambda token: token.text in ('apple', 'orange')
 | ||
|                 Token.set_extension('is_fruit', getter=is_fruit)
 | ||
|             +code-old.
 | ||
|                 token._.set_extension('is_fruit', default=False)
 | ||
|                 if token.text in ('apple', 'orange'):
 | ||
|                     token._.set('is_fruit', True)
 | ||
| 
 | ||
|     +item
 | ||
|         |  When using #[strong mutable values] like dictionaries or lists as
 | ||
|         |  the #[code default] argument, keep in mind that they behave just like
 | ||
|         |  mutable default arguments
 | ||
|         |  #[+a("http://docs.python-guide.org/en/latest/writing/gotchas/#mutable-default-arguments") in Python functions].
 | ||
|         |  This can easily cause unintended results, like the same value being
 | ||
|         |  set on #[em all] objects instead of only one particular instance.
 | ||
|         |  In most cases, it's better to use #[strong getters and setters], and
 | ||
|         |  only set the #[code default] for boolean or string values.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new.
 | ||
|                 Doc.set_extension('fruits', getter=get_fruits, setter=set_fruits)
 | ||
| 
 | ||
|             +code-old.
 | ||
|                 Doc.set_extension('fruits', default={})
 | ||
|                 doc._.fruits['apple'] = u'🍎'  # all docs now have {'apple': u'🍎'}
 | ||
| 
 | ||
|     +item
 | ||
|         |  Always add your custom attributes to the #[strong global] #[code Doc]
 | ||
|         |  #[code Token] or #[code Span] objects, not a particular instance of
 | ||
|         |  them. Add the attributes #[strong as early as possible], e.g. in
 | ||
|         |  your extension's #[code __init__] method or in the global scope of
 | ||
|         |  your module. This means that in the case of namespace collisions,
 | ||
|         |  the user will see an error immediately, not just when they run their
 | ||
|         |  pipeline.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new.
 | ||
|                 from spacy.tokens import Doc
 | ||
|                 def __init__(attr='my_attr'):
 | ||
|                     Doc.set_extension(attr, getter=self.get_doc_attr)
 | ||
|             +code-old.
 | ||
|                 def __call__(doc):
 | ||
|                     doc.set_extension('my_attr', getter=self.get_doc_attr)
 | ||
| 
 | ||
|     +item
 | ||
|         |  If your extension is setting properties on the #[code Doc],
 | ||
|         |  #[code Token] or #[code Span], include an option to
 | ||
|         |  #[strong let the user to change those attribute names]. This makes
 | ||
|         |  it easier to avoid namespace collisions and accommodate users with
 | ||
|         |  different naming preferences. We recommend adding an #[code attrs]
 | ||
|         |  argument to the #[code __init__] method of your class so you can
 | ||
|         |  write the names to class attributes and reuse them across your
 | ||
|         |  component.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new Doc.set_extension(self.doc_attr, default='some value')
 | ||
|             +code-old Doc.set_extension('my_doc_attr', default='some value')
 | ||
| 
 | ||
|     +item
 | ||
|         |  Ideally, extensions should be #[strong standalone packages] with
 | ||
|         |  spaCy and optionally, other packages specified as a dependency. They
 | ||
|         |  can freely assign to their own #[code ._] namespace, but should stick
 | ||
|         |  to that. If your extension's only job is to provide a better
 | ||
|         |  #[code .similarity] implementation, and your docs state this
 | ||
|         |  explicitly, there's no problem with writing to the
 | ||
|         |  #[+a("#custom-components-user-hooks") #[code user_hooks]], and
 | ||
|         |  overwriting spaCy's built-in method. However, a third-party
 | ||
|         |  extension should #[strong never silently overwrite built-ins], or
 | ||
|         |  attributes set by other extensions.
 | ||
| 
 | ||
|     +item
 | ||
|         |  If you're looking to publish a model that depends on a custom
 | ||
|         |  pipeline component, you can either #[strong require it] in the model
 | ||
|         |  package's dependencies, or – if the component is specific and
 | ||
|         |  lightweight – choose to #[strong ship it with your model package]
 | ||
|         |  and add it to the #[code Language] instance returned by the
 | ||
|         |  model's #[code load()] method. For examples of this, check out the
 | ||
|         |  implementations of spaCy's
 | ||
|         |  #[+api("util#load_model_from_init_py") #[code load_model_from_init_py]]
 | ||
|         |  and  #[+api("util#load_model_from_path") #[code load_model_from_path]]
 | ||
|         |  utility functions.
 | ||
| 
 | ||
|         +code-wrapper
 | ||
|             +code-new.
 | ||
|                 nlp.add_pipe(my_custom_component)
 | ||
|                 return nlp.from_disk(model_path)
 | ||
| 
 | ||
|     +item
 | ||
|         |  Once you're ready to share your extension with others, make sure to
 | ||
|         |  #[strong add docs and installation instructions] (you can
 | ||
|         |  always link to this page for more info). Make it easy for others to
 | ||
|         |  install and use your extension, for example by uploading it to
 | ||
|         |  #[+a("https://pypi.python.org") PyPi]. If you're sharing your code on
 | ||
|         |  GitHub, don't forget to tag it
 | ||
|         |  with #[+a("https://github.com/topics/spacy?o=desc&s=stars") #[code spacy]]
 | ||
|         |  and #[+a("https://github.com/topics/spacy-extension?o=desc&s=stars") #[code spacy-extension]]
 | ||
|         |  to help people find it. If you post it on Twitter, feel free to tag
 | ||
|         |  #[+a("https://twitter.com/" + SOCIAL.twitter) @#{SOCIAL.twitter}]
 | ||
|         |  so we can check it out.
 |