Across a couple of recent posts, I’ve explored how to use a webhook manager to implement the a simple Slack bot that handles queries from Slack and return information from the UK Parliament data API (Searching the UK Parliament API from Slack Slash Commands Using a Python Microservice via Hook.io Webhooks) and how to use AWS Lambda functions to construct a simple Slack slash command responder (Implementing Slack Slash Commands Using Amazon Lambda Functions – Getting Started).
So this morning, I thought I’d have a go at getting a Slack slash command responder using AWS Lambda functions to handle a couple more queries. Here’s where I got to…
First up, asking for committees that a member of parliament sits on:
Secondly, a query on who the current members of a particular committee are:
One rationale for supporting this sort of query is to provide fingertips information access to a researcher through a unified conversational interface.
To trigger the responses, I’ve used a regular expression that tries to capture several different question types:
x='committees that Andrew Turner is on"
regexp=re.compile(r'.*(?:committees[ (?:that|does|is)]*) (.*?)(( (:?is )?(on|sits on|sit on|a member of))|$)')
m=re.match(regexp,x)
Obviously, this is not very advanced in terms of natural language processing, but the domain is a simple one and the number of forms that a query requesting this sort of information might take will probably be quite simplistic – and predictable!
Having extracted the member’s name (for a lookup of the committees a member is on) or the committee name when trying to look up the members of a particular committee), a URL is generated that can request the data from the Parliament members API. For example:
def committee_URL(c): comm_url='http://data.parliament.uk/membersdataplatform/services/mnis/members/query/House=commons%7C{}/Committees/' urlargs={'committee':c} return comm_url.format(urlencode(urlargs))
We can this use this URL to get some JSON data back:
def getJSON(url): q = Request(url) q.add_header('accept', 'application/json') r= urlopen(q) a=r.read() return json.loads(a.decode('utf-8-sig'))
The next step is to parse the JSON response to pull out the information we want, and convert it to a simple text string:
def committeeMembers(members,c): tl=[] if members['Members'] is None: return None for m in members['Members']['Member']: tl.append('{} ({})'.format(m['FullTitle'],m['Party']['#text'])) return 'Members of the {}: {}'.format(c,', '.join(tl))
This text string can then be returned to Slack as the slash command response.
[UPDATE…] Here’s another example… The members’ API can look up MP by location, constituency or postcode; so if we try them in turn, we can take in a wide variety of location styles; and it only takes a really simple regular expression to prime the pattern match for what I guess is a wide range of possible conversational gambits for requesting this information:
As with the members API, the Parliament data API will also return JSON responses to valid queries (I used the Parliament data API in the original Hook.io demo). There’s quite a few APIs to play with – data.parliament.uk datasets so as and when I get a moment, I may try to code some more of them up as conversational responders:-)
This is really cool and should be the future of Open Data interfaces. People shouldn’t have to download a dataset to get key insights from it, and they shouldn’t have to decypher labels to create a custom visualisations, which is the state of the art of “accessible” open data portals today.
Would it be easy to query a google spreadsheet using this method? That sounds like a great way for a team member to query internal data that s/he might not be acquainted with.
Thanks for sharing!