Skip to content
This repository has been archived by the owner on Dec 16, 2022. It is now read-only.

fancy version of the configuration wizard #1344

Merged
merged 17 commits into from
Jun 12, 2018

Conversation

joelgrus
Copy link
Contributor

@joelgrus joelgrus commented Jun 5, 2018

  • sort of works
  • is really ugly
  • handles subconfigurations correctly
  • does not handle List / Dict / Tuple types correctly
  • "generate config" button doesn't do anything yet

screen shot 2018-06-05 at 4 57 56 pm

@matt-gardner
Copy link
Contributor

What's the right command to try this? Last time I did it I had to resort to a bit of hackery; I assume you have a command that just works from this branch.

@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 6, 2018

just do

python allennlp/service/config_explorer.py

and then take your browser to

http://localhost:8123/wizard/

@matt-gardner
Copy link
Contributor

When I run that I get No module named 'allennlp', so I need to do the path munging that we do in our other scripts. Have you modified your PYTHONPATH, or something?

@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 6, 2018

probably, I usually export PYTHONPATH=. in the root directory of the repo

@matt-gardner
Copy link
Contributor

Very nice! This is going to be super cool when it's done.

@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 6, 2018

  • slightly less ugly
  • handles lists and dicts correctly, except where they're lists/dicts of Registrable things
  • highlights in red things that need attention (but doesn't handle lists / dicts correctly, because I need to feed the state of the list items back up)
  • maintains a top level state that's the desired JSON object (right now the generate button just logs it to the console)

next steps:

  • handle list / dict items that are themselves registrable
  • handle done-ness of lists / dicts
  • place output of generate on page
  • make more attractive

@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 8, 2018

  • big refactoring to a more correct design (refactoring javascript with no types is hard!)
  • mostly works (even lists and dicts of configurable items)
  • a small amount of styling
  • "completeness" should inherit correctly (a top-level item is complete iff all of its required subitems are complete)
  • still relies on the "generate" button (reactjs got into an infinite loop when I tried to generate the json automatically)
  • doesn't handle the (unusual) Tuple case yet
  • could use more styling + UX thought

@joelgrus joelgrus changed the title [WIP] fancy version of the configuration wizard fancy version of the configuration wizard Jun 8, 2018
@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 8, 2018

ok, this is probably as good as I'm going to get it for now.

there are a few edge cases (union types + tuples) that it probably doesn't handle right, but they come up rarely. I tried to make it moderately attractive, but I don't know if I succeeded on that.

I'll demo it at the team meeting today.

@joelgrus
Copy link
Contributor Author

joelgrus commented Jun 8, 2018

btw this fixes #1125

@matt-gardner
Copy link
Contributor

This is awesome! Very nice work! It looks way better than what I would have done; thanks for doing this. My only suggestion would be to give a type hint for dicts and lists, so you don't have to guess what the "+" button does.

One option is to use the new `allennlp configure` command, which
produces stubs that can be used to produce configuration files.

If you run it without any options, you get an output corresponding to the top-level configuration:
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You should probably note here that it's for the train command.

Copy link
Contributor

@DeNeutoy DeNeutoy left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

So great to play with, looks awesome! A few minor comments.

assert '"type": "rmsprop"' in html
assert '// "weight_decay"' in html
assert config["type"] == "rmsprop"
assert any(item["name"] == "lr" for item in items)

def test_rnn_hack(self):
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This could be a little more informative - are we testing that we get the torch class docstrings, instead of our wrapper?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

no, it's something different, I added a comment

@@ -143,8 +219,8 @@ def _auto_config(cla55: Type[T]) -> Config[T]:
"""
typ3 = _get_config_type(cla55)

# Don't include self
names_to_ignore = {"self"}
# Don't include self, or vocab
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The vocab can still be configured at the top level, right? this is just to weed out all the other occurrences.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

exactly, this is inside auto_config, which uses reflection to figure out the config for some object. the top level config is arbitrary (it's just whatever commands/train expects), so it doesn't use this method.


if self.typ3:
item_dict["type"] = self.typ3
#items.insert(0, {"name": "type", "type": self.typ3})
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Delete this commented out line.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

done

<body>
$body
</body>
<head>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think you can avoid this duplication by adding the html file to MANIFEST.in in the root of the repo - this dictates non python stuff which is included/excluded by pip.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm going to leave this for a future PR, I looked into it a bit and it seems like it's tricky to get right

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sure

<script src="https://unpkg.com/tippy.js@2.5.2/dist/tippy.all.min.js"></script>
<script type="text/babel">
/*
ConfigItem = {
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Looks like you've replaced these below, right?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

sorry, that's not javascript code, that's a comment about the types that come from the API, I'll add a comment to that effect

}
*/

// A configItem is optional if it has no default value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

If it does have a default value?

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed


componentDidMount() {
// Fetch the top level configuration
fetch('/api/')
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Is it possible that this API is going to be extended to include partial json configurations/recommendations etc? It might be better to call this api /annotate or something, if that is the case.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'll make it /api/config/ to leave room for other /api/ routes

return <span>
{configureButton}
<div class="choices-dropdown">
{choicesDropdown}{deleteButton}{renderedValue}
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Nit: render the deleteButton first so that it's always in the same place - currently, for List items, it is before the entry field, but here it's after.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I don't like this way, but if I make that change then a Dict[str, Configurable] element becomes a huge mess

const renderedValue = config ? <Config path={path.push('value')} config={config} setData={setData}/> : null

return <span>
{configureButton}
Copy link
Contributor

@DeNeutoy DeNeutoy Jun 12, 2018

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think if you render the configureButton in it's own span the spacing between things will look nicer:

image

Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

That is bigger visually than I intended

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

fixed with css

return (
<div class="wizard">
<Config path={Immutable.List(['value'])} setData={this.setData} config={config}/>
<JsonBox config={config}/>
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Idea: it would be nice if the rendered JSON contained empty dictionaries for required fields - e.g you might want to fill in a partial config and then fill in the rest later, or something.

@joelgrus joelgrus merged commit d844a9a into allenai:master Jun 12, 2018
gabrielStanovsky pushed a commit to gabrielStanovsky/allennlp that referenced this pull request Sep 7, 2018
* initial version

* progress

* more features

* progress

* clean up

* add docstring

* provide type annotations for Dicts and Lists

* rewrite

* rewrite the whole thing

* fix bugs

* fix tests + final touches

* add tutorial

* fix broken link

* fix typo
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

3 participants