MedlinePlus for Mycroft

I have the initial (alpha) release of MedlinePlusSkill for looking up basic health topics from medlineplus.gov

Here is the link:


Try it with “git clone”

The goal is to retrieve information from MedlinePlus using the spoken search term.

Passing: It runs, and returns a response related to requests.

Leave feedback through “Issues” on GitHub.

5 Likes

Hey there, welcome to Mycroft and congrats on your first Skill!

Looks like a great use case

Thank you. I previously visited the forum and introduced this as an idea. Currently, the skill passes the test runner, but Mycroft on the Raspberry PI does not seem to run the skill.

Check the logs (/var/log/mycroft/skills.log) to see if anything of note is happening.

Hey I had a quick look and there are a few issues:

  • Python is very specific about indentation (as opposed to other languages that rely on braces etc). This makes it more readable but means you need to be careful with it. Also need to stick with either spaces or tabs, they can’t be mixed.
  • you are importing intent_file_handler but using the new intent_handler.
  • You also seem to be mixing up Padatious and Adapt intents - more detail on that here in our docs. Basically Padatious (.intent files) are whole sentence examples. Adapt (.voc files) are keywords to spot.
  • if a dialog file expects an entity eg {disease} this must be passed in as data to the speak_dialog method
  • some other little syntax errors that were causing the Skill not to load.

I’ve fixed up a few of these things here so the Skill will load:

import requests
from bs4 import BeautifulSoup
from mycroft import MycroftSkill, intent_handler


class MedlinePlusSkill(MycroftSkill):

    @intent_handler("medline.intent")
    def handle_medlineplus_intent(self, message):
        topic = message.data.get("topic")
        self.speak_dialog("let_me_find", {"disease": topic})
        # medlineplus refers to the topic-summary defined by the disease on medlineplus.gov
        if topic is None:
            response = self.get_response('notfound', num_retries=0)
            if response is None:
                return
            else:
                self.speak_dialog('found', data={"disease": topic})
        else:
            try:
                url = "https://medlineplus.gov/{disease}.html"
                html_content = requests.get(url).text
                soup = BeautifulSoup(html_content, "html5lib")
                main_class = soup.find("div",id="topic-summary")
                link = main_class.find("a")
                res = main_class.text
                self.result.append(str(res))
            except:
                pass

def create_skill():
    return MedlinePlusSkill()

If you then change your vocab/en-us/medline.intent file to include whole phrase examples such as:

tell me about {topic}
get me medline information (on|about) {topic}
get me information (on|about) {topic} from medline

This will let your Skill extract the topic from a user utterance and it will make a request to the medlineplus.gov site, however it looks like you were still working on what to do with the returned data at that point.

You will also need to consider how you convert multi-word topics into url slugs eg:
“heart disease” may need to be:
https://medlineplus.gov/heartdisease.html
https://medlineplus.gov/heart-disease.html
or something else…

Scraping is always a dangerous game as things can change at any time. If you can instead use their search function and return a page result it will likely be a more resilient option.

Keep at it :slight_smile:

Thank you, I see my mistakes now. I am still very new at learning Python and how to work with Mycroft AI.